Telegram Agent можно расширять своими скриптами на Python. Скрипт — обычный файл рядом с настройками, который подключается к конвейеру продукта и берёт на себя то, чего не хватает готовым средствам. Достаточно положить файл — пересобирать и перезапускать приложение не нужно. Так подключают сервис, для которого нет готового источника, относят сообщения к категориям и тегам по своим правилам, чистят и дополняют текст перед публикацией или отправляют комментарий своим способом.
Это возможность для тех, кто готов писать код; остальные разделы продукта в скриптах не нуждаются, и часто скрипт — это десяток строк.
Где лежат скрипты
Все определения живут в папке настроек /project/apps/telegram/scripts/ — в том же постоянном томе, что остальные настройки. Один скрипт — один файл настроек с числовым именем (например, 1.yml):
id: 1
name: Разбор по ключевым словам
description: Зачем этот скрипт — видно в разделе «Скрипты»
isActive: true
timeoutSec: 30
passEnv: [HTTP_PROXY]
env:
API_TOKEN: секрет
code: |
import json, sys
ctx = json.load(sys.stdin)
print(json.dumps({"categoryIds": []}))
- название и описание — чтобы через полгода было понятно, что это и зачем;
- включение — выключенный скрипт не обслуживает подключённые к нему места: конвейер ведёт себя так, будто подключения нет, а в журнале остаётся отметка «пропущено»;
- предельное время — сколько секунд ждать ответа (по умолчанию 60, потолок — 10 минут); по истечении процесс останавливается;
- переменные окружения — постоянные значения для запуска: адреса, ключи доступа. Можно также перечислить, какие переменные окружения сервера передавать скрипту;
- код — либо прямо в файле настроек, либо отдельным файлом
.pyрядом с ним: как удобнее. Отдельный файл читается с диска на каждом запуске, поэтому правка в нём видна сразу.
Библиотеки, которые нужны скриптам, перечисляются в одном общем файле scripts/requirements.txt. Рабочее окружение Python приложение готовит само при первом запуске — отдельно его настраивать не нужно. Правка файлов применяется на лету, без перезапуска приложения. Удалить скрипт, на который что-то ссылается, продукт не даст: сначала отключите его от места подключения.
Правила выполнения
Общие правила задаются в отдельном файле script-runner.yml рядом с папкой скриптов и применяются на лету. Если файла нет, действуют значения по умолчанию:
- общий выключатель — одно переключение запрещает все запуски; каждое подключённое место честно сообщит, что выполнение отключено, а не сделает вид, что всё в порядке;
- программа Python — какой именно python запускать (по умолчанию
python3); - предельное время — 60 секунд на запуск, потолок — 10 минут;
- одновременные запуски — по умолчанию не больше двух процессов сразу, чтобы скрипты не перегружали сервер;
- предел вывода — 1 МиБ на запуск; данные большего размера остаются в рабочей папке, а скрипт возвращает ссылку на файл.
Семь точек подключения
Скрипт может быть классификатором, сборщиком или преобразователем текста — всего семь мест в конвейере:
Классификация — сообщения сами получают категории и теги:
- Роутер — скрипт получает сообщение и список ваших категорий, а возвращает те, что подходят:
{"categoryIds": [...]}. Это тип роутера «Скрипт» в разделе Маршрутизация. Идентификаторы, которых больше нет в справочнике, просто отбрасываются; - Теггер — то же самое, но для тегов: скрипт возвращает
{"tagIds": [...]}.
Сбор контента — сообщения приходят из вашего источника:
- Источник — скрипт сам забирает сообщения из любого сервиса: получает настройки источника и возвращает найденное списком, не больше 500 записей за один запуск. Позиции чтения скрипт хранит в своей рабочей папке. Подробнее — Источники.
Преобразование текста — текст правится по дороге:
- Приём сообщения — скрипт правит текст собранного сообщения до сохранения: убрать лишнее, привести к единому виду;
- Элемент очереди — скрипт правит будущую публикацию в момент, когда она попадает в очередь: дополнить текст или сразу перевести её в нужное состояние;
- Черновик публикации — скрипт получает готовый текст перед отправкой и заменяет его своим. Так подставляются подпись канала, хэштеги или ссылки. Работает и для предпросмотра, и для самой публикации — текст везде одинаковый;
- Генерация комментария — скрипт получает готовый текст комментария перед отправкой и заменяет его своим. Подробнее — Комментарии с ИИ.
Обращения со скриптами щадящие и строгие. Классификация и правки на приёме и в очереди щадящие: если скрипт сломался, сообщение (или элемент очереди) сохраняется как есть, а сбой остаётся в журнале — один сбой не должен терять контент. Публикация и комментарий строгие: если скрипт сломался или не вернул текст, отправка не происходит, и попытку можно повторить. Так непереработанный текст никогда не уходит в канал. Сбор контента — отдельный случай: если скрипт не смог собрать сообщения, ошибка записывается в источник, а следующая подкачка повторяет попытку — уже собранное не теряется.
Как проходит запуск
- каждый запуск — отдельный процесс Python: он запускается, отдаёт ответ и завершается;
- на вход приходит один документ JSON: точка подключения, имя скрипта, откуда запуск, данные и аргументы. Читается привычным
json.load(sys.stdin); - ответ — тоже JSON: последний цельный объект, который скрипт напечатал. Сообщения о ходе работы печатать можно, они не мешают;
- у каждого скрипта своя рабочая папка, которая сохраняется между запусками: там удобно держать файлы, позиции чтения и промежуточные результаты;
- размер данных ограничен: если данных много, передавайте не сами данные, а ссылку или файл в рабочей папке;
- процесс не получает секретов приложения: ему доступны только служебные значения и те переменные, которые вы сами перечислили в его настройках.
Раздел «Скрипты»
В боковой панели есть раздел «Скрипты» — страница наблюдения за запусками. Определения здесь читаются, а не правятся: правка файла и есть изменение, а создание и тестовый запуск идут через API.
- состояние среды сверху: есть ли Python, собран ли набор библиотек, сколько запусков и сбоев было за сутки, что случилось в прошлый раз;
- список скриптов: включён или выключен, откуда берётся код, к чему подключён, когда запускался в последний раз;
- история запусков: время, точка подключения, откуда запуск, объект, длительность, код выхода и результат — или понятная причина сбоя. Фильтры — по состоянию и точке подключения;
- сбой назван по-русски и понятен без расшифровки: «Среда недоступна» (нет рабочего Python или не собрались библиотеки), «Таймаут», «Неверный вывод» (скрипт не напечатал цельный JSON), «Вывод слишком велик», «Отменён», «Отключён», «Скрипт не найден»;
- журнал хранится 30 дней и чистится сам.
Сбой скрипта никогда не подменяет данные молчанием: у классификации это просто отсутствие совпадения, у правки текста — запись как есть, у строгих точек — отказ отправки с причиной. Во всех случаях запуск остаётся в журнале с точным временем и ошибкой.
Внешний API
Тем же набором команд можно управлять извне — через внешний API с ключом из настроек: посмотреть список скриптов и состояние среды, прочитать определение и историю запусков, создать или изменить скрипт, удалить его и выполнить тестовый запуск. Роутеры и теггеры типа «Скрипт» тоже настраиваются через внешний API; источники и преобразования текста задаются в файлах настроек. Подробнее — Агент.
Граница доверия
Скрипты — это ваш собственный код, и запускаются они с правами приложения: отдельной изоляции между скриптом и сервером нет. Поэтому держите их в системе контроля версий вместе с папкой настроек и не запускайте чужие файлы. Если нужна полная изоляция — разворачивайте всё приложение в отдельном контейнере, что и делает стандартная установка. Секретным переменным скрипта стоит уделять то же внимание, что и паролям подключения.
Читайте также: Маршрутизация, Источники, Очередь контента, Публикации, Комментарии с ИИ.