Files
DLE/backend/services/telegramBot.js

183 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { Telegraf } = require('telegraf');
const logger = require('../utils/logger');
const db = require('../db');
const authService = require('./auth-service');
let botInstance = null;
const verificationCodes = new Map();
// Простая остановка бота
async function stopBot() {
if (botInstance) {
await botInstance.stop();
botInstance = null;
}
}
// Создание и настройка бота
async function getBot() {
if (!botInstance) {
botInstance = new Telegraf(process.env.TELEGRAM_BOT_TOKEN);
// Обработка команды /start
botInstance.command('start', (ctx) => {
ctx.reply('Добро пожаловать! Отправьте код подтверждения для аутентификации.');
});
// Обработка кодов верификации
botInstance.on('text', async (ctx) => {
const code = ctx.message.text.trim();
const verification = verificationCodes.get(code);
if (!verification) {
ctx.reply('Неверный код подтверждения');
return;
}
try {
logger.info('Starting Telegram auth process for code:', code);
logger.info('Verification data:', verification);
// Сначала проверяем, существует ли пользователь с этим Telegram ID
let userId;
const existingUser = await db.query(
`SELECT u.id
FROM users u
JOIN user_identities ui ON u.id = ui.user_id
WHERE ui.provider = $1
AND ui.provider_id = $2`,
['telegram', ctx.from.id.toString()]
);
if (existingUser.rows.length > 0) {
userId = existingUser.rows[0].id;
logger.info('Found existing user with ID:', userId);
} else {
// Создаем нового пользователя
const result = await db.query(
`INSERT INTO users (created_at, updated_at)
VALUES (NOW(), NOW())
RETURNING id`,
[]
);
userId = result.rows[0].id;
logger.info('Created new user with ID:', userId);
}
// Связываем Telegram с пользователем
await db.query(
`INSERT INTO user_identities
(user_id, provider, provider_id, created_at)
VALUES ($1, $2, $3, NOW())
ON CONFLICT (provider, provider_id) DO UPDATE SET user_id = $1`,
[userId, 'telegram', ctx.from.id.toString()]
);
logger.info(`User ${userId} successfully linked Telegram account ${ctx.from.id}`);
// Обновляем сессию
if (verification?.session) {
logger.info('Creating session with data:', verification.session);
// Обновляем данные сессии напрямую
verification.session.userId = userId;
verification.session.authenticated = true;
verification.session.authType = 'telegram';
verification.session.telegramId = ctx.from.id.toString(); // Добавляем идентификатор Telegram в сессию
// Проверяем роль пользователя
const userRole = await authService.checkUserRole(userId);
verification.session.userRole = userRole;
await new Promise((resolve, reject) => {
verification.session.save(err => {
if (err) reject(err);
else resolve();
});
});
logger.info('Session created successfully');
}
// Отправляем последнее сообщение пользователя
if (verification.session.guestId) {
logger.info('Fetching last guest message for guestId:', verification.session.guestId);
const messageResult = await db.query(`
SELECT content FROM guest_messages
WHERE guest_id = $1
ORDER BY created_at DESC
LIMIT 1
`, [verification.session.guestId]);
const lastMessage = messageResult.rows[0]?.content;
logger.info('Found last message:', lastMessage);
if (lastMessage) {
await ctx.reply(`Ваше последнее сообщение: "${lastMessage}"`);
}
}
// Отправляем сообщение об успешной аутентификации
await ctx.reply('Аутентификация успешна! Можете вернуться в приложение.');
// Удаляем сообщение с кодом
try {
await ctx.deleteMessage(ctx.message.message_id);
} catch (error) {
logger.warn('Could not delete code message:', error);
}
// Удаляем код верификации
verificationCodes.delete(code);
} catch (error) {
logger.error('Error in Telegram auth:', error);
// Более информативные сообщения об ошибках
let errorMessage = 'Произошла ошибка при сохранении. Попробуйте позже.';
if (error.code === '42P01') {
errorMessage = 'Ошибка сессии. Пожалуйста, обновите страницу и попробуйте снова.';
} else if (error.code === '42703') {
errorMessage = 'Ошибка структуры данных. Обратитесь к администратору.';
}
if (error.code) {
logger.error('Database error code:', error.code);
}
if (error.detail) {
logger.error('Error detail:', error.detail);
}
if (error.stack) {
logger.error('Error stack:', error.stack);
}
await ctx.reply(errorMessage);
}
});
// Запускаем бота
await botInstance.launch();
}
return botInstance;
}
// Инициализация процесса аутентификации
async function initTelegramAuth(session) {
const code = Math.random().toString(36).substring(2, 8).toUpperCase();
const botLink = `https://t.me/${process.env.TELEGRAM_BOT_USERNAME}`;
verificationCodes.set(code, {
timestamp: Date.now(),
session: session
});
logger.info(`Generated verification code: ${code} for Telegram auth`);
return { verificationCode: code, botLink };
}
module.exports = {
getBot,
stopBot,
verificationCodes,
initTelegramAuth
};