Чат с клиентом из карточки через бот анкеты

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zabudko-ruandClaude Opus 5.5 committed 2026-10-26 03:17:12 +04:00
1 parent 7fdabd07a4
commit dba03b8970
19 files changed
+5145 -62

No files matched your search

+8 -4
View File
@@ -79,10 +79,13 @@ export interface OutboxDeps {
sleep?: (ms: number) => Promise<void>;
}
const openButton = (config: Config, lang: string, leadId: number): Keyboard[number] => {
const openButton = (config: Config, lang: string, leadId: number): Keyboard[number] => openPathButton(config, lang, `/leads/${leadId}`);
/** Кнопка «Открыть» страницу CRM в Mini App. */
const openPathButton = (config: Config, lang: string, path: string): Keyboard[number] => {
// Telegram принимает в кнопках только https-адреса; на локальном стенде кнопки «Открыть» нет.
if (!config.appUrl.startsWith('https://')) return [];
return [{ text: texts(lang).open, webApp: `${config.appUrl}/leads/${leadId}` }];
return [{ text: texts(lang).open, webApp: `${config.appUrl}${path}` }];
};
/** Отправляет одну пачку сообщений из очереди. Возвращает число обработанных. */
@@ -117,7 +120,7 @@ export async function processOutbox({ db, tg, config, sleep }: OutboxDeps): Prom
const t = texts(user.lang);
if (job.kind === 'text') {
const p = job.payload as { raw?: string; key?: string; args?: unknown[]; buttons?: { key: string; callback: string }[] };
const p = job.payload as { raw?: string; key?: string; args?: unknown[]; buttons?: { key: string; callback: string }[]; openPath?: string };
// Кнопки под сообщением: подпись берётся из текстов бота на языке получателя.
const buttons: Keyboard | undefined = p.buttons?.length
? [p.buttons.map((b) => ({ text: String((t as unknown as Record<string, unknown>)[b.key] ?? b.key), callback: b.callback }))]
@@ -129,7 +132,8 @@ export async function processOutbox({ db, tg, config, sleep }: OutboxDeps): Prom
: typeof fn === 'function'
? (fn as (...a: unknown[]) => string)(...(p.args ?? []).map((a) => (typeof a === 'string' ? esc(a) : a)))
: String(fn ?? '');
if (text) await tg.sendMessage(chatId, text, buttons ?? (job.leadId ? [openButton(config, user.lang, job.leadId)].filter((r) => r.length) : undefined));
const open = p.openPath ? openPathButton(config, user.lang, p.openPath) : job.leadId ? openButton(config, user.lang, job.leadId) : [];
if (text) await tg.sendMessage(chatId, text, buttons ?? (open.length ? [open] : undefined));
await finish();
} else if (job.kind === 'lead') {
const [row] = await db