feat(04-04): /start carries the araharah logo (static-asset URL, resilient text fallback) + repo icon assets
This commit is contained in:
+1
-1
@@ -42,7 +42,7 @@ export function createBot(env: Env, opts: { baseFetch?: typeof fetch } = {}): Bo
|
||||
const bot = opts.baseFetch
|
||||
? new Bot(env.BOT_TOKEN, { client: { fetch: opts.baseFetch } })
|
||||
: new Bot(env.BOT_TOKEN);
|
||||
registerStart(bot); // /start + /mula (D-04)
|
||||
registerStart(bot, env.MINI_APP_URL); // /start + /mula (D-04) — carries the logo asset
|
||||
registerHelp(bot); // /help
|
||||
registerPrivacy(bot); // /privacy + /privasi (D-04)
|
||||
registerLocationFallback(bot, env.chat_sessions); // GEO-02 location reply fallback
|
||||
|
||||
@@ -6,8 +6,14 @@
|
||||
*
|
||||
* D-02 (structural, pinned by test/commands.test.mjs): the reply is plain
|
||||
* text with link previews disabled — no reply menus, no inline button
|
||||
* payloads, no callback routes anywhere in this tree. Telegram commands
|
||||
* are the interface until the Mini App launch path lands (Phase 4).
|
||||
* payloads, no callback routes anywhere in this tree.
|
||||
*
|
||||
* Device-gate feedback (2026-10-24): /start now carries the app logo —
|
||||
* sendPhoto by its STATIC-ASSET public URL (<MINI_APP_URL>/logo_arah2.png,
|
||||
* deployed from web/public/). Telegram fetches it server-side; the repo
|
||||
* asset stays the single source (assets/logo_arah2.png). Photo send is
|
||||
* resilient: if the fetch/send fails (e.g. asset not deployed yet), the
|
||||
* text reply still goes out — the greeting is never lost.
|
||||
*
|
||||
* All copy comes from src/i18n/strings.ts (D-05) — nothing inline here.
|
||||
*/
|
||||
@@ -20,13 +26,35 @@ export function startReplyText(locale: Locale): string {
|
||||
return strings[locale].startIntro;
|
||||
}
|
||||
|
||||
async function handleStart(ctx: Context): Promise<void> {
|
||||
/** The logo's public URL — derived from the same configured origin the
|
||||
* deep link uses (single origin of truth, D-11). Empty when unconfigured
|
||||
* (tests/dev without vars): the caller then skips the photo send. */
|
||||
export function startLogoUrl(origin: string | undefined): string | null {
|
||||
if (!origin) return null;
|
||||
try {
|
||||
return `${new URL(origin).origin}/logo_arah2.png`;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStart(ctx: Context, origin: string | undefined): Promise<void> {
|
||||
const locale = pickLocale(ctx.from?.language_code);
|
||||
await ctx.reply(startReplyText(locale), { link_preview_options: { is_disabled: true } });
|
||||
const text = startReplyText(locale);
|
||||
const logoUrl = startLogoUrl(origin);
|
||||
if (logoUrl !== null) {
|
||||
try {
|
||||
await ctx.replyWithPhoto(logoUrl, { caption: text });
|
||||
return;
|
||||
} catch {
|
||||
// fall through to the text reply — the greeting survives asset loss
|
||||
}
|
||||
}
|
||||
await ctx.reply(text, { link_preview_options: { is_disabled: true } });
|
||||
}
|
||||
|
||||
/** Register the command stack entry: /start and its Malay alias /mula. */
|
||||
export function registerStart(bot: Bot): void {
|
||||
bot.command("start", handleStart);
|
||||
bot.command("mula", handleStart);
|
||||
export function registerStart(bot: Bot, origin?: string): void {
|
||||
bot.command("start", (ctx) => handleStart(ctx, origin));
|
||||
bot.command("mula", (ctx) => handleStart(ctx, origin));
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
Reference in New Issue
Block a user