feat: add telegram webhook handler to receive phone replies and push to visitor chat
This commit is contained in:
1 parent
1941064933
commit
a73c2aa8e5
2 files changed
+87
-3
No files matched your search
@@ -11,8 +11,35 @@ interface ChatMessage {
|
||||
time: number;
|
||||
}
|
||||
|
||||
// Global in-memory session store across endpoints in the same runtime instance
|
||||
const sessions = new Map<string, ChatMessage[]>();
|
||||
|
||||
export function addCrisReply(sessionId: string, text: string) {
|
||||
const crisMsg: ChatMessage = {
|
||||
id: 'cris_' + Date.now(),
|
||||
sender: 'cris',
|
||||
text,
|
||||
time: Date.now(),
|
||||
};
|
||||
|
||||
// Find matching session (direct or prefix match)
|
||||
let key = sessionId;
|
||||
if (!sessions.has(sessionId)) {
|
||||
for (const k of sessions.keys()) {
|
||||
if (k.startsWith(sessionId) || sessionId.startsWith(k)) {
|
||||
key = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const history = sessions.get(key) || [];
|
||||
history.push(crisMsg);
|
||||
if (history.length > 30) history.shift();
|
||||
sessions.set(key, history);
|
||||
return crisMsg;
|
||||
}
|
||||
|
||||
export const POST: APIRoute = async ({ request }) => {
|
||||
try {
|
||||
const { sessionId, message, userName } = await request.json();
|
||||
@@ -36,7 +63,6 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
|
||||
const history = sessions.get(sessionId) || [];
|
||||
history.push(userMsg);
|
||||
// Keep last 30 messages per session
|
||||
if (history.length > 30) history.shift();
|
||||
sessions.set(sessionId, history);
|
||||
|
||||
@@ -47,10 +73,11 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
if (botToken && chatId) {
|
||||
const telegramText =
|
||||
`💬 *New Portfolio Live Message*\n\n` +
|
||||
`👤 *From:* ${userName || 'Visitor'} (\`#${sessionId.slice(0, 8)}\`)\n` +
|
||||
`👤 *From:* ${userName || 'Visitor'}\n` +
|
||||
`🔑 *Session:* #${sessionId}\n` +
|
||||
`📍 *Origin:* ${locationStr}\n\n` +
|
||||
`📝 *Message:*\n"${message.trim()}"\n\n` +
|
||||
`_To reply to this visitor, swipe right and reply to this message!_`;
|
||||
`_👉 To reply to this visitor, swipe right and reply to this message!_`;
|
||||
|
||||
try {
|
||||
await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { addCrisReply } from './live-chat';
|
||||
|
||||
export const prerender = false;
|
||||
|
||||
/**
|
||||
* Telegram Webhook Handler
|
||||
* Telegram sends an update whenever you reply to a message in the bot chat.
|
||||
*/
|
||||
export const POST: APIRoute = async ({ request }) => {
|
||||
try {
|
||||
const payload = await request.json();
|
||||
|
||||
// Check if the update is a message reply
|
||||
const message = payload?.message;
|
||||
if (!message || !message.text) {
|
||||
return new Response(JSON.stringify({ ok: true, note: 'No text message' }), { status: 200 });
|
||||
}
|
||||
|
||||
const replyToMessage = message.reply_to_message;
|
||||
const replyText = message.text.trim();
|
||||
|
||||
// Find the session ID from the replied message
|
||||
// When visitor sends message, we tagged it with (#user_xxxxxxxx)
|
||||
let targetSessionId = '';
|
||||
|
||||
if (replyToMessage?.text) {
|
||||
const match = replyToMessage.text.match(/#([a-zA-Z0-9_-]+)/);
|
||||
if (match && match[1]) {
|
||||
targetSessionId = match[1];
|
||||
}
|
||||
}
|
||||
|
||||
// If you replied without swiping or session wasn't found, check caption or fallback
|
||||
if (!targetSessionId && replyToMessage?.caption) {
|
||||
const match = replyToMessage.caption.match(/#([a-zA-Z0-9_-]+)/);
|
||||
if (match && match[1]) targetSessionId = match[1];
|
||||
}
|
||||
|
||||
if (targetSessionId) {
|
||||
addCrisReply(targetSessionId, replyText);
|
||||
return new Response(JSON.stringify({ ok: true, matchedSession: targetSessionId }), { status: 200 });
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({ ok: true, note: 'No session ID found in reply' }), { status: 200 });
|
||||
} catch (err: any) {
|
||||
console.error('Telegram webhook error:', err);
|
||||
return new Response(JSON.stringify({ error: err.message }), { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
export const GET: APIRoute = async () => {
|
||||
return new Response(
|
||||
JSON.stringify({ status: 'Telegram Webhook Endpoint Active' }),
|
||||
{ status: 200, headers: { 'Content-Type': 'application/json' } }
|
||||
);
|
||||
};
|
||||
Reference in new issue
Block a user