Оповещения в Telegram из DonationAlerts (NodeJS) – Mikulski
Наложение сайта

Оповещения в Telegram из DonationAlerts (NodeJS)

ДИСКЛЕЙМЕР:
Я не программист, а лишь энтузиаст-копипастер, который делится тем, в чем смог разобраться. Не исключено, что знающие специалисты некоторые моменты или формулировки могут счесть ошибочными или нелепыми.
Данный материал служит исключительно для ознакомительных целей.

Кулстори

Несколько лет назад я уже публиковал материал на точно такую же тематику. Но с тех пор насиделось много ж*почасов: появилось лучшее понимание происходящего, стали видны ошибки и недочеты старого скрипта. Так что я решил полностью переработать статью, дополнив ее деталями и описав более корректную установку с актуальными библиотеками.
Я постараюсь доступно объяснить все процессы, однако, данная публикация все же не рассчитана на нулевой опыт в программировании: какие-то моменты вам придется изучить самостоятельно (например, установку nodejs), вероятно, методом проб и ошибок.

Что умеет бот

Бот способен получать все события, которые регистрирует DonationAlerts в виджете “Оповещения” и отправлять в Telegram: лично пользователю, в публичный канал/чат, в определенную ветку супер-группы (но с нюансами).
В гайде будет разобран пример только с донатными событиями. Прочие (рейды, фоллоу и т.д.) вам придется изучить самостоятельно, но про их специфику я тоже немного расскажу.

Что понадобится

Так как это Common Javascript, то понадобятся установленные в системе nodejs и npm.
Также, рекомендуется использовать pm2 manager, если предполагается размещение на виртуальном сервере с режимом работы 24/7: в скрипте не предусмотрено корректного восстановления соединения в случае его отвала. На disconnect или ошибку соединения с веб-сокетом приложение закончит свою работу и в этом случае pm2 автоматически перезапустит скрипт.

Нужно будет создать Telegram-бота через BotFather и получить его API-токен.
На эту тему очень много гайдов в интернете, но чтобы далеко не ходить: https://mikulski.rocks/ru/avtopost-v-telegram/ – здесь есть пошаговое описание этого процесса (раздел “Создание Телеграм-бота”).
Стоит отметить, что если у вас уже есть бот в Telegram и он привязан к какому-либо приложению, то лучше создать нового, либо встроить код в это приложение. Использование одного токена из “разных мест” приведет к ошибке.

И еще понадобится токен виджетов DonationAlerts (настройки аккаунта -> Показать токен).

Установка

Создайте папку и в ней два файла config.json и da_telegram.js
В первом будут храниться настройки, а во втором исполняемый скрипт.
Находясь внутри созданной папки, с помощью npm установите необходимые библиотеки.

Telegraf для быстрого и простого создания Telegram-ботов:

npm i telegraf

Socket.io-client для подключения к сокету DA. Обратите внимание, что сокет-клиент должен быть версии 2.x.x. – другие версии не поддерживаются DA:

npm i socket.io-client@2.5.0

Откройте файл config.json и наполните его следующим содержимым:

{
"telegramToken": "Telegram-токен, полученный у BotFather",
"daToken": "токен виджета из настроек DonationAlerts"
}

Скрипт

Теперь можно открыть файл da_telegram.js и начать сборку скрипта.
Будем действовать пошагово для лучшей наглядности. Вставляйте части кода друг за другом.

Внедряем токены из config.json:

///Токены
const  { telegramToken, daToken } = require("./config.json");

Еще сразу добавим переменную eventId, которая пригодится в дальнейшем, чтобы избежать задваивания оповещений (иногда сокет глючит на отдельных событиях и отправляет одно и то же событие два раза подряд):

//eventId
let eventId = null;

Добавляем модуль Telegraf и создаем инстанцию Telegram-бота с подключением:

///TELEGRAM
const { Telegraf } = require('telegraf');
const bot = new Telegraf(telegramToken);
//--Запуск бота
bot.launch(
{dropPendingUpdates: true,},
console.log("Telegram bot started"));

На всякий случай создадим для бота команду /id, чтобы легко получить свой user_id. Это пригодится, если вы планируете отправлять оповещения себе лично, а не в публичный канал/чат (подробнее про адресаты к отправке будет чуть дальше):

//--команда для получения user id
bot.hears('/id', (ctx) => ctx.reply(`Ваш id: ${ctx.message.from.id}`));

Проверим подключение к Telegram_боту и заодно получим id.
Находясь в директории со скриптом, запускаем его:

node da_telegram.js

Если все хорошо и не возникло никаких ошибок, то перейдите в диалог с ботом и запустите его. Теперь введите команду /id и бот вернет ваш user id. Останавливаем скрипт (Ctrl+C).
Добавим теперь переменную channel, в которой укажем куда мы будем отправлять оповещения.
Если вы хотите получать оповещения лично (т.е. бот в диалоге с ним будет отправлять вам сообщение), то подставьте число user id без кавычек:

//--Адресат
const channel = 000000;

Если это публичный канал/чат или супергруппа, то подставьте идентификатор из ссылки на канал/чат, добавив в начале “@” и заключив в кавычки.
Что такое идентификатор? Например, в ссылке на канал https://t.me/mikulski_rocks – идентификатор это mikulski_rocks.
Соответственно, строчка будет выглядеть const channel = "@mikulski_rocks"

//--Адресат
const channel = "@идентификатор";

Для супергрупп здесь также нужно указать только общий идентификатор.
Нужная ветка/топик указывается отдельным аргументом непосредственно в операторе отправки сообщения (об этом будет дальше).
Т.е. если ваша ссылка выглядит так https://t.me/mikulski_rocks/33, то все равно в channel надо указать mikulski_rocks
Добавьте еще одну переменную const threadId = номер ветки/топика.
Номер ветки – это то, что идет в ссылке после /
Т.е. в ссылке https://t.me/mikulski_rocks/33 , threadId – это 33

const threadId = ""; //номер ветки для супергрупп. Напр., threadId = 33;

Теперь создаем подключение для сокета DonationAlerts через socket.io-client:

///SOCKET DA
const socket = require('socket.io-client')
.connect("wss://socket.donationalerts.ru:443", { transports: ["websocket"] },
{reconnection: true,
                    reconnectionDelay: 1000,
                    reconnectionDelayMax: 5000,
                    reconnectionAttempts: Infinity    
});
  socket.emit('add-user', {
  token: daToken,
  type: "minor"
});

И дополняем сокет-подключение техническими событиями (connect, disconnect, error):

//Connect
socket.on('connect', function(data){
    console.log('Connected to Donation Alerts');
});
//Error
socket.on("connect_error", (err) => {
    console.error(`Donation Alerts Connection Error! ${err.message}`);
    process.exit(0);
});
//Disconnect
socket.on('disconnect', () => {
    console.log('Donation Alerts Disconnected!');
    process.exit(0);
});

Вот мы и добрались до самого главного – получение событий из сокета виджета DonationAlerts.
Рассмотрим на примере донатов, пока без отправки в Telegram, а только с выводом в консоль:

///Отлов событий
socket.on('donation', function(msg){
    
let event = JSON.parse(msg);
//console.log(event)

//--DONATION
if (event.alert_type === '1' || event.alert_type === 1) {
    if (eventId === event.id) {return} 
    if (event.username === null){ event.username = 'Аноним'}
    eventId = event.id
    console.log(`${event.username} донатит ${event.amount_formatted} ${event.currency} и говорит: "${event.message}"`)
    }
});

Давайте разбираться, что тут происходит, чтобы вам было легче в дальнейшем составлять собственные условия.

  • Любые события (донаты, подписки, рейды и т.д.) объединены под общим ивентом ‘donation‘ (socket.on(‘donation’, …).
  • С каждым таким ивентом приходит сообщение (…, function(msg)), в котором содержится информация о событии.
  • Эту информацию мы “парсим” в удобоваримый формат JSON -> event = JSON.parse(msg), из которого через “ключи” вытаскиваем нужные нам значения.
  • Если alert_type равен событию о донате (а также если донат отправлен анонимно, то юзернейм переписываем с пустого значения в “Аноним”), – выводим в терминал {Никнейм отправителя} донатит {сумма валюта} и говорит: {прикрепленное сообщение}.
  • А также переписываем переменную eventId, сохраняя в нее id последнего оповещения, чтобы не допускать задваивания при отправке. Это случается не всегда и не со всеми событиями, возможно, временный глюк: когда писал этот пост, то отправка именно доната из истории, – приводило к такому эффекту (хотя прежде подобного замечено не было). Это может затруднить тестирование скрипта (в тестовых оповещениях id всегда равно 0), т.к. придется чередовать донаты (тестовые/из истории). Но вы можете закомментировать строчку if (eventId === event.id) {return}, чтобы убрать это условие.
  • Чтобы лучше понимать о чем речь, то раскомментируйте (т.е. удалите “//”) строку console.log(event), запустите скрипт и отправьте любое тестовое оповещение из дашборда DonationAlerts. В терминале вы увидите что-то подобное:
{
   id: 0000000,
   alert_type: '6',
   is_shown: '0',
   additional_data: '{"randomness":530,"event_data":{"user":{"display_name":"user"}}}',
   billing_system: null,
   billing_system_type: null,
   username: 'user',
   amount: '0.00',
   amount_formatted: '0',
   amount_main: 0,
   currency: 'USD',
   message: '',
   header: '',
   date_created: '2023-11-21 14:46:52',
   emotes: null,
   ap_id: null,
   _is_test_alert: false,
   message_type: 'text'
 }

Вид события определяется ключом alert_type и всегда имеет числовое значение. При этом, если число заключено в кавычки (т.е. тип данных string) – то это тестовое оповещение, если без кавычек (т.е. тип данных integer), то это “реальное” событие.
Например, к донатам привязан alert_type: 1, а к отслеживаниям на Twitch alert_type: 6
Соответственно, вы можете вычислить все alert_type и доп. информацию самостоятельно, отправляя тестовые оповещения разных событий и мониторя их через терминал.
Но учтите, что в некоторых случаях ключи JSON оформлены немного по-разному для реальных и тестовых оповещений (как например, с подписками Boosty).

Ладно, с этим, надеюсь, понятно. Осталось только оформить отправку нужному адресату в Telegram. Под строчкой console.log(${event.username} донатит...), пропишите:

bot.telegram.sendMessage(channel,"" + `${event.username} донатит ${event.amount_formatted} ${event.currency} и говорит: "${event.message}"`);

Если вы отправляете в супергруппу, то после сообщения, через запятую нужно добавить аргумент {message_thread_id: threadId}:

bot.telegram.sendMessage(channel, `${event.username} донатит ${event.amount_formatted} ${event.currency} и говорит: "${event.message}"`, {message_thread_id: threadId});

Конечный скрипт будет выглядеть примерно так:

///Токены
const  { telegramToken, daToken } = require("./config.json");
//Event Id
let eventId = null;

///TELEGRAM
const { Telegraf } = require('telegraf');
const bot = new Telegraf(telegramToken);

//--Запуск бота
bot.launch(
{dropPendingUpdates: true,},
console.log("Telegram bot started"));

//--команда для получения user id
bot.hears('/id', (ctx) => ctx.reply(`Ваш id: ${ctx.message.from.id}`));

//--Адресат
const channel = "";
const threadId = "";

///SOCKET DA
const socket = require('socket.io-client')
.connect("wss://socket.donationalerts.ru:443", { transports: ["websocket"] },
{reconnection: true,
                    reconnectionDelay: 1000,
                    reconnectionDelayMax: 5000,
                    reconnectionAttempts: Infinity    
});
  socket.emit('add-user', {
  token: daToken,
  type: "minor"
});

//Connect
socket.on('connect', function(data){
    console.log('Connected to Donation Alerts');
});
//Error
socket.on("connect_error", (err) => {
    console.error(`Donation Alerts Connection Error! ${err.message}`);
    process.exit(0);
});
//Disconnect
socket.on('disconnect', () => {
    console.log('Donation Alerts Disconnected!');
    process.exit(0);
});

///Отлов событий
socket.on('donation', function(msg){
    
let event = JSON.parse(msg);
//console.log(event)

//--DONATION
if (event.alert_type === '1' || event.alert_type === 1) { 
    if (eventId === event.id) {return} 
    if (event.username === null){ event.username = 'Аноним'}
    eventId = event.id
console.log(`${event.username} донатит ${event.amount_formatted} ${event.currency} и говорит: "${event.message}"`);
bot.telegram.sendMessage(channel, `${event.username} донатит ${event.amount_formatted} ${event.currency} и говорит: "${event.message}"`);
    }
});
Пример с отправкой оповещения в диалог с ботом

Если этот материал вам пригодился и у вас есть возможность,
то поддержите автора и сайт небольшим донатом:

Спасибо💛


0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии