[Инструкция]Пишем простого бота для dtf.ru

Меня вчера попросили объяснить как работать с API dtf.ru.
Напишем простого бота на NodeJS

Если Вы не знакомы с NodeJS, то ничего страшного - сейчас изучим.

Скачиваем дистрибутив и устанавливаем

Создаём папку для проекта.

В папке создаём файл "test.js". В нём пишем любым текстовым редактором следующий код:

console.log('HELLO WORLD!');

Создаем файл "test.bat" с кодом:

node test.js pause

Запускаем test.bat.

Получаем:

[Инструкция]Пишем простого бота для dtf.ru

Поздравляю. Теперь Вы официально junior программист. Вам положена зарплата в 300К рублей в месяц. Не соглашайтесь на меньшее!

Знакомитесь, это Гарольд, он только что закончил курс по NodeJS у Нехорошей русской и стал junior программистом. Какой он крутой! Похлопайте ему.
Знакомитесь, это Гарольд, он только что закончил курс по NodeJS у Нехорошей русской и стал junior программистом. Какой он крутой! Похлопайте ему.

Вы решаете что 300К в месяц - это конечно хорошо, но пора повышать квалификацию и стать наконец middle программистом!

Давайте не вставая с дивана повысим нашу квалификацию. Для этого немножечко усложним наш код и напишем бота для dtf.ru
Берегись, Паймон.

Создание бота для dtf.ru

Для начала Вам потребуется зарегистрировать нового пользователя под Вашего бота. Можете конечно использовать Вашу учётку как это делает Трактирщик. Ваше право.

Вы должны знать логин, пароль и числовой идентификатор бота.

Наш бот будет максимально простым: будет отвечать тем что мы ему отправили.

Что такое бот? Если коротко, то это программа, которая получает какие-то данные и что-то делает: например создаёт посты или комментарии. А может и не получает никакие данные или ничего не делает. Боты разные.
Единственный цивилизованный способ получать данные с dtf.ru - это веб-сокет, на котором можно сделать подписку на события сайта: о новых постах, комментариях, лайках и т.п.
Создание постов, комментов происходит отправкой запросов по API.

Код бота желательно оформить в отдельном файле, т.е. в модуле, который мы сможем вызвать из другого более главного файла.

Скачайте и разархивируйте архив:

Обязательно напишите в комментах что в архиве вирус или майнер и Вы сейчас пишите с телефона.

Вот умора =)

Код бота представлен в файле "simple_bot/simple_bot.js":

module.exports = { init: function () { const DTF_API = require("../common_libs/my_dtf_api"); //библиотека для работы с API dtf.ru const Socket = require("../common_libs/my_socket"); //библиотека для работы с веб-сокетом const DTF_USER__LOGIN = '*********@********'; //логин бота, для авторизации const DTF_USER__PASSWORD = '***********'; //пароль бота, для авторизации const DTF_USER__ID = '***********'; //user id бота class Simple_Bot { constructor() { this.main(); } async main() { this._log = console.log; //авторизируемся this.g_dtf_api = new DTF_API(DTF_USER__LOGIN, DTF_USER__PASSWORD, this._log); await this.g_dtf_api.auth(); //подписываемся на события с dtf по веб-сокету this.g_socket = new Socket(); await this.g_socket.init(this, ['user', 'm']); //события связанные с нашим ботом //await this.g_socket.init(this, ['live']); //новые комменты с текстом(используется для боковой ленты "сейчас говорят") //await this.g_socket.init(this, ['api']); //события сайта: новые посты и комменты(без подробностей, просто айдишники) return true; } async event_handle(event) { this._log(event); if (!event || !event.data) return false; const data = event.data; let $user_id; let $comment_id; let $entry_id; let $event_type; let $channel_id; let $comment_text; // //обработка ивента от комментария // if (data.type === 32 || data.type === 16) { //32 - тэгнули, 16 - ответ на коммент if (!(data.data && data.data.entryId && data.data.commentId)) { this._log(`wrong comment data`); return false; } //получаем id коммента $comment_id = data.data.commentId; //получаем сам коммент по API let $comment__response = await this.g_dtf_api.comment_get($comment_id).catch(function(error){inst._log(error)}); //проверям что он здоровый if ( $comment__response === undefined || $comment__response.data === undefined || $comment__response.data.id === undefined || $comment__response.data.text === undefined || $comment__response.data.authorId === undefined || $comment__response.data.postId === undefined || $comment__response.data.parentCommentId === undefined || $comment__response.data.level === undefined || $comment__response.data.media === undefined ) { this._log('$comment__response not valid!'); return false; } $comment_text = $comment__response.data.text; //текст комментария $user_id = $comment__response.data.authorId; //id юзера $entry_id = $comment__response.data.postId; //id поста $event_type = 'comment'; } // //обработка ивента от мессенжера // if (data.type === 'messenger_event' && data.action === 'addMessage') { if (!(data.message && data.message.text !==undefined && data.message.media !== undefined && data.channelId && data.message.author)) { console.log(`wrong messenger data`); return false; } if (data.message.author.id === DTF_USER__ID) return true; //не реагируем на собственные сообщения, если реагировать - будет бесконечный цикл $channel_id = data.channelId; //id канала $user_id = data.message.author.id; //id юзера $comment_text = data.message.text; //текст комментария $event_type = 'messenger'; } if (!$event_type) { return true; } if ($event_type === 'messenger') { this.g_dtf_api.m_send($channel_id, `Вы написали ${$comment_text}`, []).catch(function(error){inst._log(error)}); } if ($event_type === 'comment') { this.g_dtf_api.comment_add($entry_id, $comment_id, `Вы написали ${$comment_text}`, []).catch(function (error) {inst._log(error)}); } } ///event_handle } const inst = new Simple_Bot(); } }
Это я так имаджинирую Вас, когда Вы это читаете

Как видим ничего сложного.

Ладно, расслабитесь и отдохните. Посмотрите 2 минуты на котика
Ладно, расслабитесь и отдохните. Посмотрите 2 минуты на котика

Пропишем в

const DTF_USER__LOGIN = '*********@********'; //логин бота, для авторизации const DTF_USER__PASSWORD = '***********'; //пароль бота, для авторизации const DTF_USER__ID = '***********'; //user id бота

данные Вашего бота, которого вы регистрировали.

Вы же его регистрировали?

Да?

А кому и зачем я эту портянку пишу?

Всё. Бота можно запускать через run.bat

node main.js pause
[Инструкция]Пишем простого бота для dtf.ru

Он должен отвечать тем что Вы ему написали в ЛС или в комментариях

[Инструкция]Пишем простого бота для dtf.ru

Как это работает?

NodeJS запускает функцию Simple_bot.init в котором создается объект бота.

const inst = new Simple_Bot()

В конструкторе Simple_Bot выполняется код функции main

Мы создаем собственный объект DTF_API, который будет отвечать за работу с API

this.g_dtf_api = new DTF_API(DTF_USER__LOGIN, DTF_USER__PASSWORD, this._log);

Авторизуемся:

await this.g_dtf_api.auth();​

Выполняется функция auth.

//авторизация аккаунта async auth() { return new Promise( async (resolve, reject) => { const this_ = this; let login; while(!login || login.data === undefined || login.data.data === undefined || login.data.data.accessToken === undefined) { login = await this_.auth_email_login(this_.user_login, this_.user_password).catch(function (error) { this_._log(error); }); } this_.access_token = login.data.data.accessToken; resolve(); }); }

При удачной авторизации мы получаем access_token - ключ который необходим для работы с API. Ключ позволит Вам создавать посты, комментарии, получать информацию о пользователях и т.п.

Кстати когда будете это тестировать, Вы будете часто логинится и получать 429 ошибку. \_(ツ)_/¯ Будьте к этому морально готовы.

Идём далее. Нам надо как-то получать данные с сайта.

Подключаем веб-сокеты:

//подписываемся на события с dtf по веб-сокету this.g_socket = new Socket(); await this.g_socket.init(this, ['user', 'm']); //события связанные с нашим ботом

ВАЖНО! Библиотека "socket.io-client" для работы с веб-сокетами должна быть 2.x.x версии. На текущий день - 2.5.0
ws-sio.dtf.ru не работает с 3.x.x !

У кого-то лапки. Просьба отнестись с пониманием
У кого-то лапки. Просьба отнестись с пониманием

Подписываться мы можем на различные события сайта: о новых постах, комментах. Но если нам необходимы события связанные с ботом, например событие когда что-то ему написали, то необходимы специальные юзер-хэши - временные ключи получаемые по API

if (this_.channels.includes('user') || this_.channels.includes('m')) { new_user_hashes = await this_.client.g_dtf_api.get_user_hash().catch(function (error) { this_.client._log(error) }); if (!new_user_hashes) return false; }

Подписываемся на нужные каналы веб-сокета

this_.socket.emit('subscribe', {'channel': 'mobile:' + this_.g_user_hash});

Привязываем все приходящие события веб-сокета к нашей функции которая будет отвечать за логику бота:

this_.socket.on('event', (data) => { this_.client.event_handle(data); });

Собственно начинаем смотреть логику работы бота.

Наконец-то!!!

Веб-сокет присылает объект event. Внимательно изучите что он присылает

this._log(event);

В зависимости от типа события мы получаем либо текст комментария

//получаем сам коммент по API let $comment__response = await this.g_dtf_api.comment_get($comment_id).catch(function(error){inst._log(error)});

Либо текст сообщения в ЛС

$comment_text = data.message.text;

Отвечаем пользователю:

if ($event_type === 'messenger') { this.g_dtf_api.m_send($channel_id, `Вы написали ${$comment_text}`, []).catch(function(error){inst._log(error)}); } if ($event_type === 'comment') { this.g_dtf_api.comment_add($entry_id, $comment_id, `Вы написали ${$comment_text}`, []).catch(function (error) {inst._log(error)}); }

Полное описание API можно найти здесь

Пишите если есть вопросы

19
1
2
1
1
78 комментариев