import { createHash, randomBytes } from 'node:crypto'; const BOT_USERNAME_PATTERN = /^[a-z][a-z0-9_]{4,31}$/; export function normalizeBotUsername(username: string) { return username.trim().toLowerCase().replace(/[^a-z0-9_]/g, ''); } export function assertValidBotUsername(username: string) { const normalized = normalizeBotUsername(username); if (!BOT_USERNAME_PATTERN.test(normalized)) { throw new Error('INVALID_BOT_USERNAME'); } if (normalized.endsWith('_bot')) { throw new Error('INVALID_BOT_USERNAME'); } return `${normalized}_bot`; } export function generateTelegramStyleBotToken() { const botId = randomBytes(4).readUInt32BE(0) % 900_000_000 + 100_000_000; const secret = randomBytes(32) .toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/g, ''); const token = `${botId}:${secret}`; return { token, tokenPrefix: `${botId}:${secret.slice(0, 6)}…` }; } export function hashBotToken(token: string) { return createHash('sha256').update(token.trim()).digest('hex'); } export function deriveTelegramChatId(source: string) { const hash = createHash('sha256').update(source).digest(); const value = hash.readBigInt64BE(0); const positive = value < 0n ? -value : value; return positive % 9_000_000_000_000n + 1_000_000_000_000n; } export function deriveTelegramUserId(userId: string) { return Number(deriveTelegramChatId(`user:${userId}`)); }