import { pool } from "../db.js"; const TOKEN_TTL_SEC = 600; // 10 минут export async function createTgLoginToken({ token, intent, userId, ipAddress, userAgent }) { const expires = new Date(Date.now() + TOKEN_TTL_SEC * 1000); await pool.query( `INSERT INTO uno_bff.tg_login_tokens (token, intent, status, user_id, ip_address, user_agent, expires_at) VALUES ($1, $2, 'pending', $3, $4, $5, $6)`, [token, intent, userId || null, ipAddress, userAgent, expires] ); return { token, expiresAt: expires, ttlSec: TOKEN_TTL_SEC }; } export async function findTgLoginToken(token) { const r = await pool.query( `SELECT * FROM uno_bff.tg_login_tokens WHERE token = $1`, [token] ); return r.rows[0] || null; } export async function markTgTokenConfirmed(token, { telegramId, telegramUsername, telegramFirstName, telegramLastName, userId }) { await pool.query( `UPDATE uno_bff.tg_login_tokens SET status = 'confirmed', telegram_id = $2, telegram_username = $3, telegram_first_name = $4, telegram_last_name = $5, user_id = COALESCE($6, user_id), confirmed_at = now() WHERE token = $1 AND status = 'pending' AND expires_at > now()`, [token, telegramId, telegramUsername, telegramFirstName, telegramLastName, userId || null] ); } export async function markTgTokenError(token, errorCode) { await pool.query( `UPDATE uno_bff.tg_login_tokens SET status = 'error', error_code = $2 WHERE token = $1 AND status = 'pending'`, [token, errorCode] ); } export async function consumeTgToken(token) { const r = await pool.query( `UPDATE uno_bff.tg_login_tokens SET status = 'consumed', consumed_at = now() WHERE token = $1 AND status = 'confirmed' RETURNING *`, [token] ); return r.rows[0] || null; } export async function countTgStartsByIpLastMinutes(ipAddress, minutes = 10) { if (!ipAddress) return 0; const r = await pool.query( `SELECT count(*)::int AS c FROM uno_bff.tg_login_tokens WHERE ip_address = $1 AND created_at > now() - ($2 || ' minutes')::interval`, [ipAddress, String(minutes)] ); return r.rows[0]?.c || 0; }