Вход через Telegram: код из бота вместо сломанного deep-link

Deep-link авторизация в Telegram-виджете не работала (не было отдельной
кнопки для завершения флоу). Заменяет на код-флоу: бот выдаёт разовый код,
пользователь вводит его в Login.tsx/LoginButton.tsx, useAuthStore дергает
loginTelegramCode(). api.ts вместо startTelegramLogin/TelegramLoginSession
получает getBotUsername() (кэширует bot_username из GET /api/v1/config) для
кнопки "Открыть бота".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 22:52:04 +07:00
parent 626e3b8fd4
commit 5f6e06589c
4 changed files with 137 additions and 128 deletions
+22 -14
View File
@@ -166,20 +166,11 @@ export async function loginWithSeed(seed: string): Promise<void> {
localStorage.setItem(SEED_KEY, seed);
}
export interface TelegramLoginSession {
authCode: string;
deepLink: string;
}
/** Создаёт ожидающую подтверждения сессию для входа через Telegram-бота (magic-link). */
export async function startTelegramLogin(): Promise<TelegramLoginSession> {
const res = await fetch(`${API_V1}/auth/telegram/session`, { method: "POST" });
if (!res.ok) throw new Error(`telegram/session failed: ${res.status}`);
const data = (await res.json()) as { auth_code: string; deep_link: string };
return { authCode: data.auth_code, deepLink: data.deep_link };
}
/** Опрашивает статус подтверждения; `true` — юзер подтвердил вход в боте. */
/**
* Обменивает код на сессию. Код теперь генерирует сам бот по кнопке
* "Код для входа" (уже подтверждённым — см. AuthService::create_bot_login_code),
* поэтому это одноразовый обмен, а не поллинг: `true` при первом же успешном вызове.
*/
export async function pollTelegramLogin(authCode: string): Promise<boolean> {
const res = await fetch(`${API_V1}/auth/telegram/session/${authCode}`);
if (res.status === 401 || res.status === 410) {
@@ -213,3 +204,20 @@ export async function fetchUsage(): Promise<UsageInfo> {
};
return { usedBytes: data.data_used_bytes, limitBytes: data.data_limit_bytes };
}
let cachedBotUsername: string | null = null;
/** Юзернейм бота для ссылки "открыть чат" на экране входа (без `?start=` —
* код теперь вводится вручную, см. pollTelegramLogin). */
export async function getBotUsername(): Promise<string | null> {
if (cachedBotUsername) return cachedBotUsername;
try {
const res = await fetch(`${API_V1}/config`);
if (!res.ok) return null;
const data = (await res.json()) as { bot_username: string };
cachedBotUsername = data.bot_username;
return cachedBotUsername;
} catch {
return null;
}
}