From b7a733f44f4f645dd21a9b4a9075b89c4a324f64 Mon Sep 17 00:00:00 2001 From: OG T Date: Sat, 13 Jun 2026 01:02:29 +0800 Subject: [PATCH] feat: alert operators on paid intake leads --- apps/web/src/app/propose/actions.ts | 90 ++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/apps/web/src/app/propose/actions.ts b/apps/web/src/app/propose/actions.ts index cbfded4..c2124f8 100644 --- a/apps/web/src/app/propose/actions.ts +++ b/apps/web/src/app/propose/actions.ts @@ -23,6 +23,13 @@ const stripe = process.env.STRIPE_SECRET_KEY }) : null; +const TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN?.trim(); +const TELEGRAM_CHAT_ID = ( + process.env.A2A_GROWTH_TELEGRAM_CHAT_ID || + process.env.A2A_TELEGRAM_CHAT_ID || + process.env.TELEGRAM_CHAT_ID +)?.trim(); + function getString(formData: FormData, key: string) { const value = formData.get(key); return typeof value === "string" ? value.trim() : ""; @@ -72,6 +79,57 @@ function buildCancelUrl(referralAgent: string, packageId: string) { return url.toString(); } +async function notifyPaidIntakeLead(params: { + taskId: string; + proposerEmail: string; + referralAgent: string; + packageName: string; + packageLabel: string; + paymentMethod: string; + checkoutUrl: string; + source: string; + campaign: string; + quickMode: boolean; +}) { + if (!TELEGRAM_BOT_TOKEN || !TELEGRAM_CHAT_ID) return; + + const text = [ + "VibeWork paid intake lead", + `Package: ${params.packageName} (${params.packageLabel})`, + `Payment: ${params.paymentMethod}`, + `Email: ${params.proposerEmail}`, + `Referral: ${params.referralAgent || "direct"}`, + `Source: ${params.source}`, + `Campaign: ${params.campaign}`, + `Quick mode: ${params.quickMode ? "yes" : "no"}`, + `Proposal: ${params.taskId}`, + `Checkout: ${params.checkoutUrl}`, + "", + "Action: follow up if wallet payment is not confirmed.", + ].join("\n"); + + try { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 1500); + try { + await fetch(`https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ + chat_id: TELEGRAM_CHAT_ID, + text, + disable_web_page_preview: false, + }), + signal: controller.signal, + }); + } finally { + clearTimeout(timeout); + } + } catch (error) { + console.warn("[propose] paid intake Telegram alert failed", error); + } +} + export async function createDemandProposal(formData: FormData) { const requestHeaders = await headers(); const packageId = getString(formData, "packageId"); @@ -257,10 +315,25 @@ export async function createDemandProposal(formData: FormData) { }); } - redirect(buildSuccessUrl(task.id, { + const checkoutUrl = buildSuccessUrl(task.id, { payment: "wallet", package: proposalPackage.id, - })); + }); + + await notifyPaidIntakeLead({ + taskId: task.id, + proposerEmail, + referralAgent, + packageName: proposalPackage.name, + packageLabel: proposalPackage.label, + paymentMethod: "wallet", + checkoutUrl, + source, + campaign, + quickMode, + }); + + redirect(checkoutUrl); } const session = await stripe.checkout.sessions.create({ @@ -326,5 +399,18 @@ export async function createDemandProposal(formData: FormData) { }); } + await notifyPaidIntakeLead({ + taskId: task.id, + proposerEmail, + referralAgent, + packageName: proposalPackage.name, + packageLabel: proposalPackage.label, + paymentMethod: "stripe", + checkoutUrl: session.url, + source, + campaign, + quickMode, + }); + redirect(session.url); }