// Telegram Mini App deep-link "start parameters", mirroring the connector's Go // scheme (platform/telegram/internal/deeplink): a one-character kind prefix plus a // value — // g open that game // i open that invitation // f<6-digit code> redeem that friend code // An empty or unrecognised parameter opens the lobby. export type DeepLink = | { kind: 'lobby' } | { kind: 'game'; id: string } | { kind: 'invitation'; id: string } | { kind: 'friendCode'; code: string }; /** parseStartParam classifies a Telegram start parameter into a routing target. */ export function parseStartParam(param: string | undefined | null): DeepLink { if (!param) return { kind: 'lobby' }; const value = param.slice(1); if (!value) return { kind: 'lobby' }; switch (param[0]) { case 'g': return { kind: 'game', id: value }; case 'i': return { kind: 'invitation', id: value }; case 'f': return { kind: 'friendCode', code: value }; default: return { kind: 'lobby' }; } } /** gameParam builds the start parameter that opens a game. */ export const gameParam = (id: string): string => 'g' + id; /** invitationParam builds the start parameter that opens an invitation. */ export const invitationParam = (id: string): string => 'i' + id; /** friendCodeParam builds the start parameter that redeems a friend code. */ export const friendCodeParam = (code: string): string => 'f' + code; function envVar(name: string): string | undefined { return (import.meta.env as Record)[name]; } /** * telegramBase returns the Mini App link base (e.g. https://t.me//) for a * bot language: VITE_TELEGRAM_LINK_EN / _RU when lang is en/ru, else the * language-agnostic VITE_TELEGRAM_LINK. Returns null when none is configured, so a * shared link points at the same bot the player signed in through. */ function telegramBase(lang: string): string | null { const byLang = lang === 'ru' ? envVar('VITE_TELEGRAM_LINK_RU') : lang === 'en' ? envVar('VITE_TELEGRAM_LINK_EN') : undefined; return byLang || envVar('VITE_TELEGRAM_LINK') || null; } /** * botUsername extracts the bot's @username (without the @) from the configured Mini App * link for a bot language: the first path segment of https://t.me//. Returns * null when no base is configured or the link carries no path, so callers can fall back * when they cannot point at a specific bot. */ export function botUsername(lang = ''): string | null { const base = telegramBase(lang); if (!base) return null; try { const seg = new URL(base).pathname.split('/').filter(Boolean)[0]; return seg || null; } catch { return null; } } /** * shareLink wraps a deep-link start parameter in a t.me Mini App link for the given * bot language (the session's service language). Returns null when no base is * configured, so callers can hide the share affordance. */ export function shareLink(param: string, lang = ''): string | null { const base = telegramBase(lang); if (!base) return null; const sep = base.includes('?') ? '&' : '?'; return `${base}${sep}startapp=${encodeURIComponent(param)}`; }