/** * Скрипт для проверки и исправления проблем с обработчиками уведомлений в боте */ const { Client } = require('pg'); const fs = require('fs'); // Конфигурация базы данных const dbConfig = { host: 'localhost', port: 5432, database: 'telegram_tinder', user: 'postgres', password: 'postgres' }; // Подключение к базе данных const client = new Client(dbConfig); async function main() { try { console.log('Подключение к базе данных...'); await client.connect(); console.log('Успешно подключено к базе данных'); // Шаг 1: Проверка существования необходимых таблиц для уведомлений console.log('\n=== Проверка таблиц для уведомлений ==='); // Проверяем таблицу notifications let notificationsTableExists = await checkTableExists('notifications'); if (!notificationsTableExists) { console.log('Таблица notifications не найдена. Создаем...'); await createNotificationsTable(); console.log('Таблица notifications успешно создана'); } else { console.log('Таблица notifications уже существует'); } // Проверяем таблицу scheduled_notifications let scheduledNotificationsTableExists = await checkTableExists('scheduled_notifications'); if (!scheduledNotificationsTableExists) { console.log('Таблица scheduled_notifications не найдена. Создаем...'); await createScheduledNotificationsTable(); console.log('Таблица scheduled_notifications успешно создана'); } else { console.log('Таблица scheduled_notifications уже существует'); } // Проверяем таблицу notification_templates let notificationTemplatesTableExists = await checkTableExists('notification_templates'); if (!notificationTemplatesTableExists) { console.log('Таблица notification_templates не найдена. Создаем...'); await createNotificationTemplatesTable(); console.log('Таблица notification_templates успешно создана'); console.log('Заполняем таблицу базовыми шаблонами...'); await populateDefaultTemplates(); console.log('Шаблоны успешно добавлены'); } else { console.log('Таблица notification_templates уже существует'); } // Шаг 2: Проверка существования столбца notification_settings в таблице users console.log('\n=== Проверка столбца notification_settings в таблице users ==='); const notificationSettingsColumnExists = await checkColumnExists('users', 'notification_settings'); if (!notificationSettingsColumnExists) { console.log('Столбец notification_settings не найден. Добавляем...'); await addNotificationSettingsColumn(); console.log('Столбец notification_settings успешно добавлен'); } else { console.log('Столбец notification_settings уже существует'); } // Шаг 3: Проверка существования столбцов state и state_data в таблице users console.log('\n=== Проверка столбцов state и state_data в таблице users ==='); const stateColumnExists = await checkColumnExists('users', 'state'); if (!stateColumnExists) { console.log('Столбец state не найден. Добавляем...'); await addStateColumn(); console.log('Столбец state успешно добавлен'); } else { console.log('Столбец state уже существует'); } const stateDataColumnExists = await checkColumnExists('users', 'state_data'); if (!stateDataColumnExists) { console.log('Столбец state_data не найден. Добавляем...'); await addStateDataColumn(); console.log('Столбец state_data успешно добавлен'); } else { console.log('Столбец state_data уже существует'); } console.log('\nВсе таблицы и столбцы успешно проверены и созданы при необходимости.'); console.log('Механизм уведомлений должен работать корректно.'); console.log('\n=== Проверка регистрации обработчиков уведомлений ==='); console.log('Подсказка: убедитесь, что в файле bot.ts создается экземпляр NotificationHandlers и регистрируются его обработчики:'); console.log(` // Настройка обработчиков уведомлений const notificationHandlers = new NotificationHandlers(bot); notificationHandlers.register(); // Запуск обработчика запланированных уведомлений setInterval(() => { const notificationService = new NotificationService(bot); notificationService.processScheduledNotifications(); }, 60000); // Проверяем каждую минуту `); } catch (error) { console.error('Ошибка выполнения скрипта:', error); } finally { await client.end(); console.log('\nСоединение с базой данных закрыто.'); } } async function checkTableExists(tableName) { const query = ` SELECT EXISTS ( SELECT FROM information_schema.tables WHERE table_name = $1 ) as exists `; const result = await client.query(query, [tableName]); return result.rows[0].exists; } async function checkColumnExists(tableName, columnName) { const query = ` SELECT EXISTS ( SELECT FROM information_schema.columns WHERE table_name = $1 AND column_name = $2 ) as exists `; const result = await client.query(query, [tableName, columnName]); return result.rows[0].exists; } async function createNotificationsTable() { await client.query(` CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE TABLE notifications ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, type VARCHAR(50) NOT NULL, data JSONB, is_read BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT NOW() ) `); } async function createScheduledNotificationsTable() { await client.query(` CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE TABLE scheduled_notifications ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, type VARCHAR(50) NOT NULL, data JSONB, scheduled_at TIMESTAMP NOT NULL, processed BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT NOW() ) `); } async function createNotificationTemplatesTable() { await client.query(` CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE TABLE notification_templates ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), type VARCHAR(50) NOT NULL UNIQUE, title TEXT NOT NULL, message_template TEXT NOT NULL, button_template JSONB, created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ) `); } async function addNotificationSettingsColumn() { await client.query(` ALTER TABLE users ADD COLUMN notification_settings JSONB DEFAULT '{ "newMatches": true, "newMessages": true, "newLikes": true, "reminders": true, "dailySummary": true, "timePreference": "evening", "doNotDisturb": false }'::jsonb `); } async function addStateColumn() { await client.query(` ALTER TABLE users ADD COLUMN state VARCHAR(255) NULL `); } async function addStateDataColumn() { await client.query(` ALTER TABLE users ADD COLUMN state_data JSONB DEFAULT '{}'::jsonb `); } async function populateDefaultTemplates() { const templates = [ { type: 'new_like', title: 'Новый лайк!', message_template: '❤️ *{{name}}* поставил(а) вам лайк!\n\nВозраст: {{age}}\n{{city}}\n\nОтветьте взаимностью или посмотрите профиль.', button_template: { inline_keyboard: [ [{ text: '👀 Посмотреть профиль', callback_data: 'view_profile:{{userId}}' }], [ { text: '❤️ Лайк в ответ', callback_data: 'like_back:{{userId}}' }, { text: '⛔️ Пропустить', callback_data: 'dislike_profile:{{userId}}' } ], [{ text: '💕 Открыть все лайки', callback_data: 'view_likes' }] ] } }, { type: 'super_like', title: 'Супер-лайк!', message_template: '⭐️ *{{name}}* отправил(а) вам супер-лайк!\n\nВозраст: {{age}}\n{{city}}\n\nВы произвели особое впечатление! Ответьте взаимностью или посмотрите профиль.', button_template: { inline_keyboard: [ [{ text: '👀 Посмотреть профиль', callback_data: 'view_profile:{{userId}}' }], [ { text: '❤️ Лайк в ответ', callback_data: 'like_back:{{userId}}' }, { text: '⛔️ Пропустить', callback_data: 'dislike_profile:{{userId}}' } ], [{ text: '💕 Открыть все лайки', callback_data: 'view_likes' }] ] } }, { type: 'new_match', title: 'Новый матч!', message_template: '🎊 *Ура! Это взаимно!* 🎊\n\nВы и *{{name}}* понравились друг другу!\nВозраст: {{age}}\n{{city}}\n\nСделайте первый шаг - напишите сообщение!', button_template: { inline_keyboard: [ [{ text: '💬 Начать общение', callback_data: 'open_chat:{{matchId}}' }], [ { text: '👀 Посмотреть профиль', callback_data: 'view_profile:{{userId}}' }, { text: '📋 Все матчи', callback_data: 'view_matches' } ] ] } }, { type: 'new_message', title: 'Новое сообщение!', message_template: '💌 *Новое сообщение!*\n\nОт: *{{name}}*\n\n"{{message}}"\n\nОтветьте на сообщение прямо сейчас!', button_template: { inline_keyboard: [ [{ text: '📩 Ответить', callback_data: 'open_chat:{{matchId}}' }], [ { text: '👤 Профиль', callback_data: 'view_profile:{{userId}}' }, { text: '📋 Все чаты', callback_data: 'view_matches' } ] ] } }, { type: 'match_reminder', title: 'Напоминание о матче', message_template: '💕 У вас есть матч с *{{name}}*, но вы еще не начали общение!\n\nНе упустите шанс познакомиться поближе!', button_template: { inline_keyboard: [ [{ text: '💬 Начать общение', callback_data: 'open_chat:{{matchId}}' }], [{ text: '👀 Посмотреть профиль', callback_data: 'view_profile:{{userId}}' }] ] } }, { type: 'inactive_matches', title: 'Неактивные матчи', message_template: '⏰ У вас {{count}} неактивных матчей!\n\nПродолжите общение, чтобы не упустить интересные знакомства!', button_template: { inline_keyboard: [ [{ text: '📋 Открыть матчи', callback_data: 'view_matches' }], [{ text: '💕 Смотреть новые анкеты', callback_data: 'start_browsing' }] ] } }, { type: 'like_summary', title: 'Сводка лайков', message_template: '💖 У вас {{count}} новых лайков!\n\nПосмотрите, кто проявил к вам интерес сегодня!', button_template: { inline_keyboard: [ [{ text: '👀 Посмотреть лайки', callback_data: 'view_likes' }], [{ text: '💕 Начать знакомиться', callback_data: 'start_browsing' }] ] } } ]; for (const template of templates) { await client.query(` INSERT INTO notification_templates (type, title, message_template, button_template) VALUES ($1, $2, $3, $4) ON CONFLICT (type) DO UPDATE SET title = EXCLUDED.title, message_template = EXCLUDED.message_template, button_template = EXCLUDED.button_template, updated_at = NOW() `, [ template.type, template.title, template.message_template, JSON.stringify(template.button_template) ]); } } // Запуск скрипта main();