mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-21 19:35:10 +00:00
core: keep Go referral links crediting new signups
This commit is contained in:
@@ -81,7 +81,7 @@ function CopyInviteLink(props: { summary: GoReferralSummary }) {
|
||||
? window.location.origin
|
||||
: undefined
|
||||
const inviteUrl = createMemo(() => {
|
||||
const path = `/go?ref=${props.summary.inviteCode}`
|
||||
const path = `/go?ref=${props.summary.referralCode}`
|
||||
if (!origin) return path
|
||||
return new URL(path, origin).toString()
|
||||
})
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import { Referral } from "@opencode-ai/console-core/referral.js"
|
||||
|
||||
const INVITE_COOKIE = "oc_referral"
|
||||
const INVITE_MAX_AGE = 60 * 60 * 24 * 30
|
||||
const REFERRAL_COOKIE = "oc_referral"
|
||||
const REFERRAL_MAX_AGE = 60 * 60 * 24 * 30
|
||||
|
||||
export function normalizeInviteCode(code?: string | null) {
|
||||
export function normalizeReferralCode(code?: string | null) {
|
||||
return Referral.normalizeCode(code)
|
||||
}
|
||||
|
||||
export function inviteCookie(code: string) {
|
||||
return `${INVITE_COOKIE}=${encodeURIComponent(code)}; Path=/; Max-Age=${INVITE_MAX_AGE}; SameSite=Lax; HttpOnly`
|
||||
export function referralCookie(code: string) {
|
||||
return `${REFERRAL_COOKIE}=${encodeURIComponent(code)}; Path=/; Max-Age=${REFERRAL_MAX_AGE}; SameSite=Lax; HttpOnly`
|
||||
}
|
||||
|
||||
export function clearInviteCookie() {
|
||||
return `${INVITE_COOKIE}=; Path=/; Max-Age=0; SameSite=Lax; HttpOnly`
|
||||
export function clearReferralCookie() {
|
||||
return `${REFERRAL_COOKIE}=; Path=/; Max-Age=0; SameSite=Lax; HttpOnly`
|
||||
}
|
||||
|
||||
export function inviteFromCookieHeader(header: string | null) {
|
||||
export function referralCodeFromCookieHeader(header: string | null) {
|
||||
if (!header) return undefined
|
||||
|
||||
return normalizeInviteCode(
|
||||
return normalizeReferralCode(
|
||||
header
|
||||
.split(";")
|
||||
.map((x) => x.trim())
|
||||
.find((x) => x.startsWith(`${INVITE_COOKIE}=`))
|
||||
?.slice(`${INVITE_COOKIE}=`.length),
|
||||
.find((x) => x.startsWith(`${REFERRAL_COOKIE}=`))
|
||||
?.slice(`${REFERRAL_COOKIE}=`.length),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createMiddleware } from "@solidjs/start/middleware"
|
||||
import { LOCALE_HEADER, cookie, fromPathname, strip } from "~/lib/language"
|
||||
import { inviteCookie, normalizeInviteCode } from "~/lib/referral-invite"
|
||||
import { normalizeReferralCode, referralCookie } from "~/lib/referral-invite"
|
||||
|
||||
export default createMiddleware({
|
||||
onRequest(event) {
|
||||
@@ -14,7 +14,7 @@ export default createMiddleware({
|
||||
event.response.headers.append("set-cookie", cookie(locale))
|
||||
}
|
||||
|
||||
const inviteCode = normalizeInviteCode(url.searchParams.get("ref"))
|
||||
if (inviteCode) event.response.headers.append("set-cookie", inviteCookie(inviteCode))
|
||||
const referralCode = normalizeReferralCode(url.searchParams.get("ref"))
|
||||
if (referralCode) event.response.headers.append("set-cookie", referralCookie(referralCode))
|
||||
},
|
||||
})
|
||||
|
||||
@@ -5,7 +5,7 @@ import { AuthClient } from "~/context/auth"
|
||||
import { useAuthSession } from "~/context/auth"
|
||||
import { i18n } from "~/i18n"
|
||||
import { localeFromRequest, route } from "~/lib/language"
|
||||
import { clearInviteCookie, inviteFromCookieHeader } from "~/lib/referral-invite"
|
||||
import { clearReferralCookie, referralCodeFromCookieHeader } from "~/lib/referral-invite"
|
||||
|
||||
export async function GET(input: APIEvent) {
|
||||
const url = new URL(input.request.url)
|
||||
@@ -19,7 +19,7 @@ export async function GET(input: APIEvent) {
|
||||
if (result.err) throw new Error(result.err.message)
|
||||
const decoded = AuthClient.decode(result.tokens.access, {} as any)
|
||||
if (decoded.err) throw new Error(decoded.err.message)
|
||||
const inviteCode = inviteFromCookieHeader(input.request.headers.get("cookie"))
|
||||
const referralCode = referralCodeFromCookieHeader(input.request.headers.get("cookie"))
|
||||
const session = await useAuthSession()
|
||||
const id = decoded.subject.properties.accountID
|
||||
await session.update((value) => {
|
||||
@@ -35,14 +35,14 @@ export async function GET(input: APIEvent) {
|
||||
current: id,
|
||||
}
|
||||
})
|
||||
if (decoded.subject.properties.newAccount && inviteCode) {
|
||||
await Referral.createFromAccount({ accountID: id, inviteCode }).catch((error) => {
|
||||
if (decoded.subject.properties.newAccount && referralCode) {
|
||||
await Referral.createFromAccount({ accountID: id, referralCode }).catch((error) => {
|
||||
console.error("Referral create failed", error)
|
||||
})
|
||||
}
|
||||
const next = url.pathname === "/auth/callback" ? "/auth" : url.pathname.replace("/auth/callback", "")
|
||||
const response = redirect(route(locale, next))
|
||||
if (inviteCode) response.headers.append("set-cookie", clearInviteCookie())
|
||||
if (referralCode) response.headers.append("set-cookie", clearReferralCookie())
|
||||
return response
|
||||
} catch (e: any) {
|
||||
return new Response(
|
||||
|
||||
@@ -226,11 +226,12 @@ function LimitsGraph(props: { href: string }) {
|
||||
export default function Home() {
|
||||
const location = useLocation()
|
||||
const workspaceID = createAsync(() => checkLoggedIn())
|
||||
const inviteCode = createMemo(() => new URLSearchParams(location.search).get("ref") ?? undefined)
|
||||
const referralCode = createMemo(() => new URLSearchParams(location.search).get("ref") ?? undefined)
|
||||
const subscribeUrl = createMemo(() => {
|
||||
const invite = inviteCode() ? `?ref=${encodeURIComponent(inviteCode()!)}` : ""
|
||||
if (workspaceID()) return `/workspace/${workspaceID()}/go${invite}`
|
||||
return `/auth${invite}`
|
||||
const code = referralCode()
|
||||
const referral = code ? `?ref=${encodeURIComponent(code)}` : ""
|
||||
if (workspaceID()) return `/workspace/${workspaceID()}/go${referral}`
|
||||
return `/auth${referral}`
|
||||
})
|
||||
const i18n = useI18n()
|
||||
const language = useLanguage()
|
||||
|
||||
@@ -153,7 +153,7 @@ export namespace Referral {
|
||||
(a, b) => new Date(b.timeCreated).getTime() - new Date(a.timeCreated).getTime(),
|
||||
)
|
||||
return {
|
||||
inviteCode: code.code,
|
||||
referralCode: code.code,
|
||||
inviteCount: allRewards.length,
|
||||
hasActiveGo: !!rows.lite,
|
||||
rewardAmount: microCentsToCents(REWARD_AMOUNT),
|
||||
@@ -279,16 +279,16 @@ export namespace Referral {
|
||||
|
||||
export async function createFromAccount(input: {
|
||||
accountID: string
|
||||
inviteCode?: string
|
||||
referralCode?: string
|
||||
}) {
|
||||
const inviteCode = normalizeCode(input.inviteCode)
|
||||
if (!inviteCode) return { status: "missing-code" as const }
|
||||
const referralCode = normalizeCode(input.referralCode)
|
||||
if (!referralCode) return { status: "missing-code" as const }
|
||||
|
||||
return Database.transaction(async (tx) => {
|
||||
const code = await tx
|
||||
.select({ workspaceID: WorkspaceTable.id })
|
||||
.from(WorkspaceTable)
|
||||
.where(and(eq(WorkspaceTable.referralCode, inviteCode), isNull(WorkspaceTable.timeDeleted)))
|
||||
.where(and(eq(WorkspaceTable.referralCode, referralCode), isNull(WorkspaceTable.timeDeleted)))
|
||||
.then((rows) => rows[0])
|
||||
if (!code) return { status: "invalid-code" as const }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user