[Ликбез]Как делать ботов для DTF. Часть 1: Основы

[Ликбез]Как делать ботов для DTF. Часть 1: Основы

Дисклеймер

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

Примеры с кодом написаны на Bash и PHP. Есть пара строчек из Drupal 10, связанные с работой БД. По возможности максимально подробно описываю каждую строчку чтобы Вы смогли разобраться, если Ваш язык программирования не PHP. Если Вы пишите на Python, Java, Javascript то для Вас не будет проблем найти аналогичные функции для Вашего языка.

Начало

Многие на DTF мечтают создай бота для любимого сайта. На самом DTF вообще нет ни одной статьи как это делать. Поэтому я по просьбам некоторых котанов в нескольких частях проведу ликбез по созданию ботов. В первой части рассмотрим основы и создадим первого простого бота. Во второй будем рассматривать более продвинутые вещи.

Для начала стоит ознакомится с доступной технической документацией для работы с API ОСНОВА:

API позволяет работать со статьями, комментариями, поиском, пользователями, подсайтами, вакансиями, профилем, черным списком, загружать картинки для прикрепления к статьям и комментариям, подписываться на вебхуки от API.
Для отправки комментария на сайт требуется отправить API POST-запрос. Пример на Bash:

curl --request POST \ --url https://api.dtf.ru/v1.9/comment/add \ --header 'X-Device-Token: yourtoken' \ --form id=92502 \ --form reply_to=2299957 \ --form 'text=api comment'

где:

  • header 'X-Device-Token: yourtoken' - Ваш ключ для доступа к API(о нём ниже)
  • form id=92502 - идентификатор темы.
  • form reply_to=2299957 - идентификатор комментария на который отвечаем.
  • form 'text=api comment' - сам текст в комментарии.

В заголовке запроса передается API-токен. В форм-данных - параметры запроса.

Где найти ключ для доступа к API?

Идём в профиль аккаунта от лица которого будет отправлять запросы к API. Там нажимаем "Инструменты разработчика":

[Ликбез]Как делать ботов для DTF. Часть 1: Основы

Проходим каптчу и получаем наш API-токен.

[Ликбез]Как делать ботов для DTF. Часть 1: Основы

Важно понимать что этим API-токеном нельзя ни с кем делится или оставлять где попало. Человек знающий Ваш токен сможет от имени Вашей учётной записи делать всё что угодно!
Для Вашего бота потребуется отдельная учётная запись на DTF. API-токен вы сможете получить после 24 часа после регистрации этого аккаунта.

Как определять идентификаторы тем, комментариев, пользователей, подсайтов и т.п.

Рассмотрим формат URL на DTF на примере:

https://dtf.ru/s/534837-ia-panorama-dtf/1568194-zvezda-venzdey-nazvala-dtf-posredstvennoy-pomoykoy-tak-dzhenna-ortega-obyasnila-hayp-vokrug-ee-tanca

Эта же страница откроется по URL без "декоративного" текста:

https://dtf.ru/s/534837/1568194

где:

  • 534837 - идентификатор подсайта
  • 1568194 - идентификатор темы

Идентификатор пользователя находится аналогично по URL профиля:

https://dtf.ru/u/427106-fanat-meliny-iz-elden-ring

где: 427106 - идентификатор пользователя

Идентификатор комментария быстрее всего можно узнать по его ссылке в теме. Например:

https://dtf.ru/s/534837-ia-panorama-dtf/1568194-zvezda-venzdey-nazvala-dtf-posredstvennoy-pomoykoy-tak-dzhenna-ortega-obyasnila-hayp-vokrug-ee-tanca?comment=21847132

где: 21847132 - идентификатор комментария

Вроде ничего сложного.

Первый запрос к API

Как определять идентификаторы на сайте научились. Попробуйте отправить комментарий в эту тему. Ниже пример функции на PHP, запуск которой оставит комментарий "Тest" в этой теме. Не забудьте прописать Ваш API-токен.

function dtf_api__comments__test() { $url = 'https://api.dtf.ru/v1.9/comment/add'; $post = array( 'id' => 1568111, 'reply_to' => 0, 'text' => 'Тest', ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Accept: application/json', 'Content-Type: multipart/form-data', 'X-Device-Token: '.<ВАШ ТОКЕН> )); $response =curl_exec($ch); curl_close($ch); print_r($response); return true; }

По аналогии с этой функцией можете создавать свои функции для создания статей, чтения комментариев в статьях, добавления в ЧС и т.п.
Можете написать скрипт который каждый час будет изменять фон/аватарку/описание в Вашем профиле. Или каждый час постящий смешной мем из Интернета от Вашего аккаунта. И тому подобное. В общем использование API открывает очень много возможностей для автоматизации Вашей работы с DTF.
Главное не забывайте что у API есть ограничение: не чаще 3-х запросов к API в секунду.

Наконец делаем бота!

Работать с API мы немного научились. Дальше немного посложнее. Давайте сделаем бота, который будет отвечать комментарием в ответ на комментарий с какой-либо фразой. Например будет писать "Паймон" в ответ на комментарий содержащий слово "Паймон". Для этого нам потребуется проверять новые комментарии на наличие определенной фразы. Получать информацию о новых комментариях на сайте возможно через механизм так называемых вебхуков. Можно почитать как этот механизм работает от самих разработчиков ОСНОВА:

Сервер ОСНОВА каждую секунду будет посылать нам информацию о новом комментарии в Ваш скрипт.
Осталось сделать ровно 2 вещи: написать этот скрипт и сделать чтобы ОСНОВА смогла посылать информацию о новых комментариях на этот скрипт.

1.Сервер

Для этого нам потребуется веб-сервер где будет обрабатываться наш будущий бот. Этим веб-сервером может быть обычный веб-хостинг, виртуальный сервер: VPS или VDS, Ваш домашний компьютер с запущенным веб-сервером и т.п. В общем любая железяка способная отвечать по протоколу HTTP/2 и видимая в Интернете. Далее создаем на этом сервере скрипт-заглушку, который будет считывать входящие POST запросы. Поскольку ОСНОВА будет посылать на наш сервер запрос то все функции отвечающие за выходной поток типа "print" будут видны только посылающему. В нашей же функции надо сделать логирование входящих запросов, чтобы видеть что к нам приходит от ОСНОВА.

//"входящее сообщение" от API $request_JSON = file_get_contents("php://input"); _log($request_JSON); exit(); function _log($value) { //вначале давайте убедимся, что файл существует и доступен для записи. if (is_writable('/log.txt')) { if (!$handle = fopen('/log.txt', 'a')) { exit; } if (fwrite($handle, print_r($value, true)."\r\n") === FALSE) { exit; } fclose($handle); } }

Запуск этого скрипта должен происходить по обращению по определённому адресу в Интернете - URL. Например: "http://mysite/bots". Главное чтобы этой URL был виден в Интернете и отдавал код ответа 200(ОК) по протоколу HTTP/2. Иначе API сервер не будет Вам ничего посылать. С этим пунктом могут быть проблемы: например технические адреса от хостинга вряд ли будут отдавать код ответа 200(ОК). Проверить код ответа Вашего URL по протоколу HTTP/2 можно через сервисы в Интернете. Например:

!!!Важно ставить для проверки User Agent = httpstatus/2.0<br />
!!!Важно ставить для проверки User Agent = httpstatus/2.0
[Ликбез]Как делать ботов для DTF. Часть 1: Основы

Дальше нам нужно сообщить ОСНОВА что мы хотели бы получать информацию о новых комментариях на сайте. Пишем и запускаем функцию:

//запрос к API //подписка на вебхуки function dtf_api__api__webhook_add() { $url = 'https://api.dtf.ru/v1.9/webhooks/add'; $post = array( 'event' => 'new_comment', //событие на которое подписываемся 'url' => 'http://mysite/bots' //адрес на сайте где будет обработчик ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Accept: application/json', 'Content-Type: multipart/form-data', 'User-agent: '.DTF_API__USER_AGENT, 'X-Device-Token: '.DTF_API__API_KEY )); curl_exec($ch); curl_close($ch); return true; }

где

  • 'event' => 'new_comment', - событие на которое подписываемся
  • 'url' => 'http://mysite/bots' - адрес где будет обработчик бота, желательно чтобы в этом адресе был секретный ключ

Для отписки от вебхуков запускам похожий скрипт:

function dtf_api__api__webhook_del() { $url = 'https://api.dtf.ru/v1.9/webhooks/del'; $post = array( 'event' => 'all' //событие от которого отписываемся ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); //curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Accept: application/json', 'Content-Type: multipart/form-data', 'User-agent: '.DTF_API__USER_AGENT, 'X-Device-Token: '.DTF_API__API_KEY )); curl_exec($ch); curl_close($ch); return true; }

В Ваш скрипт ежесекундно начнут приходить данные о новых комментариях в JSON формате. Ниже приведен пример декодированного JSON выведенный PHP функцией print_r:

stdClass Object ( [type] => new_comment [data] => stdClass Object ( [id] => 21644408 [url] => https://dtf.ru/cinema/1552590-pervyy-treyler-horror-komedii-renfild-v-kotoroy-nikolas-keydzh-sygral-drakulu?comment=21644408 [text] => Ещё в Джо [media] => Array ( ) [date] => 2023-01-05T20:05:55+03:00 [creator] => stdClass Object ( [id] => 20265 [avatar] => https://leonardo.osnova.io/96d6815b-6c42-818a-0086-71f59585b26a/ [name] => Михаил Доброхотов [url] => https://dtf.ru/u/20265-mihail-dobrohotov ) [content] => stdClass Object ( [id] => 1552590 [title] => Первый трейлер хоррор-комедии «Ренфилд», в которой Николас Кейдж сыграл Дракулу [url] => https://dtf.ru/cinema/1552590-pervyy-treyler-horror-komedii-renfild-v-kotoroy-nikolas-keydzh-sygral-drakulu [owner] => stdClass Object ( [id] => 64957 [name] => Кино и сериалы [avatar] => https://leonardo.osnova.io/5d198df0-3ba4-6837-b9c3-ac8c04fb9181/ [url] => https://dtf.ru/cinema ) ) [reply_to] => stdClass Object ( [id] => 21643474 [url] => https://dtf.ru/cinema/1552590-pervyy-treyler-horror-komedii-renfild-v-kotoroy-nikolas-keydzh-sygral-drakulu?comment=21643474 [text] => Ещё в Мэнди [media] => Array ( ) [creator] => stdClass Object ( [id] => 628891 [avatar] => https://leonardo.osnova.io/d678380f-f1c7-58a7-908a-074bcc141978/ [name] => Booba? [url] => https://dtf.ru/u/628891-booba ) ) ) )

Если данные приходят - осталось дописать наш скрипт-заглушку до полноценного обработчика бота.

2.Скрипт

Допишем наш скрипт, чтобы он:

  • Декодировал JSON в объект с которым мы сможем работать
  • Проверял что данные о новом комментарии непровреждены
  • Проверял что комментарий новый, который мы ещё не обрабатывали
  • (Опционально)Проверял что комментарий написан в подсайте Полигон
  • Выполнял логику работы бота: писал "Паймон" в ответ на комментарии содержащие "Паймон"

Ниже пример функции обработки нового комментария:

public function new_comment() { //"входящее сообщение" от API $request_JSON = file_get_contents("php://input"); //декодируем $request = json_decode($request_JSON); //проверяем что оно о новом комментарии if (!isset($request->type) || $request->type != 'new_comment') exit(); //проверяем что оно целое. if (!isset($request->data->id) || //ид коммента !isset($request->data->text) || //текст коммента !isset($request->data->creator->id) || //ид автора коммента !isset($request->data->creator->name) || //имя автора коммента !isset($request->data->creator->avatar) || //путь до аватарки автора коммента !isset($request->data->content->owner->id) || //ид подсайта !isset($request->data->content->id)) //ид топика exit(); //если какого-то поля нет завершаем выполнение скрипта // //!!!!ВАЖНО // //когда мы ответим ботом на новый комментарий. API заново пришлёт этот комментарий в вебхуке //в результате получаем несколько обработчиков на один и тот же новый комментарий //Надо запоминать ид последнего комментария и не обрабатывать старые комментарии //смотрим какой последний комментарий мы обрабатывали //\Drupal::state()->get('dtf_api__request__comment_id__last', 0) возвращает хранимую в БД переменную $comment_id__last = \Drupal::state()->get('dtf_api__request__comment_id__last', 0); //этот коммент мы уже обрабатывали - выходим if ($request->data->id<=$comment_id__last) exit(); //сохраняем номер последнего комментария //\Drupal::state()->get('dtf_api__request__comment_id__last', 0) сохраняет в БД переменную \Drupal::state()->set('dtf_api__request__comment_id__last', $request->data->id); //$request->data->content->owner->id - ид подсайта if ($request->data->content->owner->id != 130721) //тест только на подсайте Полигон exit(); //если не Полигон - выходим //логика работы бота if (preg_match('/паймон/iu', $request->data->text)) { dtf_api__api__comment_add($request->data->content->id, $request->data->id, 'Паймон', array(), DTF_API__API_KEY); exit(); } exit(); }

Ботов крайне желательно сначала тестировать в подсайте Полигон:

//$request->data->content->owner->id - ид подсайта if ($request->data->content->owner->id != 130721) //тест только на подсайте Полигон exit(); //если не Полигон - выходим

Вот и всё! Вы создали своего первого бота! Вы молодец! Можете взять печеньку.

Cсылка на мои модули к Drupal 10. Первый модуль для работы с API, второй - RemindMe бот. Можете поизучать.

8181
38 комментариев

Только не бот, спамящий этой гифкой, пожалуйста

19

С одной стороны полезно
С другой стороны вредно

2

Ну так делайте что полезно, и не делайте что вредно.

7

Ну и смотри, что ты наделал?

4