180 lines
6.1 KiB
JavaScript
180 lines
6.1 KiB
JavaScript
const db = require("../config/db");
|
||
const webpush = require('web-push');
|
||
const TelegramBot = require("node-telegram-bot-api");
|
||
|
||
const util = require('util');
|
||
const dbRun = util.promisify(db.run).bind(db);
|
||
|
||
const VAPID_PUBLIC_KEY = process.env.VAPID_PUBLIC_KEY;
|
||
const VAPID_PRIVATE_KEY = process.env.VAPID_PRIVATE_KEY;
|
||
|
||
webpush.setVapidDetails(
|
||
'mailto:rozenrod320@gmail.com',
|
||
VAPID_PUBLIC_KEY,
|
||
VAPID_PRIVATE_KEY
|
||
);
|
||
|
||
const TOKEN = process.env.TELEGRAM_TOKEN;
|
||
const STAND_CHAT_ID = process.env.STAND_CHAT_ID;
|
||
|
||
const bot = new TelegramBot(TOKEN, { polling: false });
|
||
|
||
class Notification {
|
||
async sendSheep({ sheep_id, title, body, page }) {
|
||
const sql = `
|
||
SELECT * FROM subscription
|
||
WHERE sheep_id = ?
|
||
ORDER BY id
|
||
`;
|
||
|
||
db.all(sql, [sheep_id], async (err, rows) => {
|
||
if (err) {
|
||
console.error('DB error:', err.message);
|
||
return;
|
||
}
|
||
|
||
if (!rows.length) {
|
||
console.log(`🐑 No subscriptions found for sheep_id: ${sheep_id}`);
|
||
return;
|
||
}
|
||
|
||
console.log(`📨 Sending notification to ${rows.length} subscriptions...`);
|
||
|
||
const payload = JSON.stringify({
|
||
title: title ?? "Тестове повідомлення",
|
||
body: body ?? "Ви успішно підписалися на отримання push повідомлень!",
|
||
url: `https://${process.env.DOMAIN}${page ?? ""}`
|
||
});
|
||
|
||
const results = await Promise.allSettled(rows.map(row => {
|
||
const subscription = {
|
||
endpoint: row.endpoint,
|
||
keys: JSON.parse(row.keys),
|
||
};
|
||
return webpush.sendNotification(subscription, payload);
|
||
}));
|
||
|
||
const failed = results.filter(r => r.status === 'rejected').length;
|
||
console.log(`✅ Sent: ${rows.length - failed}, ❌ Failed: ${failed}`);
|
||
});
|
||
}
|
||
|
||
async sendGroup({ group_id, title, body, page }) {
|
||
const sql = `
|
||
SELECT
|
||
subscription.*
|
||
FROM
|
||
subscription
|
||
JOIN
|
||
sheeps
|
||
ON
|
||
sheeps.id = subscription.sheep_id
|
||
WHERE
|
||
sheeps.group_id = ?
|
||
ORDER BY
|
||
subscription.id;
|
||
`;
|
||
|
||
db.all(sql, [group_id], async (err, rows) => {
|
||
if (err) {
|
||
console.error('DB error:', err.message);
|
||
return;
|
||
}
|
||
|
||
if (!rows.length) {
|
||
console.log(`🐑 No subscriptions found for sheep_id: ${sheep_id}`);
|
||
return;
|
||
}
|
||
|
||
console.log(`📨 Sending notification to ${rows.length} subscriptions...`);
|
||
|
||
const payload = JSON.stringify({
|
||
title: title ?? "Тестове повідомлення",
|
||
body: body ?? "Ви успішно підписалися на отримання push повідомлень!",
|
||
url: `https://${process.env.DOMAIN}${page ?? ""}`
|
||
});
|
||
|
||
const results = await Promise.allSettled(rows.map(row => {
|
||
const subscription = {
|
||
endpoint: row.endpoint,
|
||
keys: JSON.parse(row.keys),
|
||
};
|
||
return webpush.sendNotification(subscription, payload);
|
||
}));
|
||
|
||
const failed = results.filter(r => r.status === 'rejected').length;
|
||
console.log(`✅ Sent: ${rows.length - failed}, ❌ Failed: ${failed}`);
|
||
});
|
||
}
|
||
|
||
async sendStand({ title, body, page }) {
|
||
const sql = `
|
||
SELECT
|
||
subscription.*
|
||
FROM
|
||
subscription
|
||
JOIN
|
||
sheeps
|
||
ON sheeps.id = subscription.sheep_id
|
||
JOIN
|
||
possibilities
|
||
ON possibilities.sheep_id = sheeps.id
|
||
WHERE
|
||
possibilities.can_view_stand = '1'
|
||
ORDER BY
|
||
subscription.id;
|
||
`;
|
||
|
||
db.all(sql, async (err, rows) => {
|
||
if (err) {
|
||
console.error('DB error:', err.message);
|
||
return;
|
||
}
|
||
|
||
if (!rows.length) {
|
||
console.log(`🐑 No subscriptions`);
|
||
return;
|
||
}
|
||
|
||
console.log(`📨 Sending notification to ${rows.length} subscriptions...`);
|
||
|
||
const payload = JSON.stringify({
|
||
title: title ?? "Тестове повідомлення",
|
||
body: body ?? "Ви успішно підписалися на отримання push повідомлень!",
|
||
url: `https://${process.env.DOMAIN}${page ?? ""}`
|
||
});
|
||
|
||
const results = await Promise.allSettled(rows.map(row => {
|
||
const subscription = {
|
||
endpoint: row.endpoint,
|
||
keys: JSON.parse(row.keys),
|
||
};
|
||
return webpush.sendNotification(subscription, payload);
|
||
}));
|
||
|
||
const failed = results.filter(r => r.status === 'rejected').length;
|
||
console.log(`✅ Sent: ${rows.length - failed}, ❌ Failed: ${failed}`);
|
||
});
|
||
|
||
// Формуємо повне повідомлення
|
||
const fullMessage = `📢 <b>${title}</b>\n\n${body.replace('«', '«<b>').replace('»', '</b>»')}`;
|
||
|
||
try {
|
||
const sentMessage = await bot.sendMessage(STAND_CHAT_ID, fullMessage, {
|
||
parse_mode: 'HTML'
|
||
});
|
||
|
||
// Зберігаємо ID нового повідомлення у базі
|
||
await dbRun(
|
||
`INSERT INTO sent_messages (last_message_id, created_at) VALUES (?, ?)`, [sentMessage.message_id, Date.now()]
|
||
);
|
||
|
||
console.log(`✅ Сповіщення надіслано для стенду: ${stand.title}`);
|
||
} catch (err) {
|
||
console.error('❌ Помилка відправки тексту:', err.message);
|
||
}
|
||
|
||
}
|
||
};
|
||
|
||
module.exports = new Notification(); |