Files
IdP/apps/sso-core/src/domain/bot/bot-token.util.ts
2026-06-25 23:48:57 +03:00

45 lines
1.4 KiB
TypeScript

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}`));
}