ДИСКЛЕЙМЕР:
Я не программист, а лишь энтузиаст-копипастер, который делится тем, в чем смог разобраться. Не исключено, что знающие специалисты некоторые моменты или формулировки могут счесть ошибочными или нелепыми.
Данный материал служит исключительно для ознакомительных целей.
Кулстори
Несколько лет назад я уже публиковал материал на точно такую же тематику. Но с тех пор насиделось много ж*почасов: появилось лучшее понимание происходящего, стали видны ошибки и недочеты старого скрипта. Так что я решил полностью переработать статью, дополнив ее деталями и описав более корректную установку с актуальными библиотеками.
Я постараюсь доступно объяснить все процессы, однако, данная публикация все же не рассчитана на нулевой опыт в программировании: какие-то моменты вам придется изучить самостоятельно (например, установку 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}"`);
}
});
Если этот материал вам пригодился и у вас есть возможность,
то поддержите автора и сайт небольшим донатом:
Спасибо💛