333 lines
13 KiB
JavaScript
333 lines
13 KiB
JavaScript
/**
|
||
* Скрипт для проверки и исправления проблем с обработчиками уведомлений в боте
|
||
*/
|
||
|
||
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();
|