Перейти к основному содержимому

🧩 Типы узлов (блоков)

Полный справочник всех доступных узлов в конструкторе Telegram Bot Builder.


📨 Триггеры

Триггеры — это точки входа в сценарий. Они определяют, когда бот начинает выполнять цепочку действий.

🔔 Триггер команды (command_trigger)

Срабатывает когда пользователь вводит команду (/start, /help, любая своя).

НастройкаОписание
КомандаТекст команды (например /start)
ОписаниеОтображается в меню команд Telegram
Показать в менюДобавить команду в список меню бота
АвтопереходУзел, на который перейти после срабатывания

💬 Триггер текста (text_trigger)

Срабатывает когда пользователь отправляет определённое текстовое сообщение.

НастройкаОписание
Тип совпаденияexact — точное совпадение, contains — содержит подстроку
СинонимыСписок слов/фраз для срабатывания
АвтопереходУзел для перехода

📩 Триггер входящего сообщения (incoming_message_trigger)

Срабатывает на каждое входящее сообщение от пользователя (любой тип контента). Работает через middleware aiogram 3 — перехватывает сообщение до стандартных обработчиков и передаёт управление целевому узлу.

НастройкаПолеОписание
Тип чатаimtChatTypeFilterany — любой чат, private — только личные, group — группы и супергруппы
ID группыimtGroupChatIdФильтр по конкретной группе (без префикса -100). Активен при imtChatTypeFilter: "group"
Источник ID группыimtGroupChatIdSourcemanual — значение из imtGroupChatId, variable — из переменной groupChatVariableName
Остановка цепочкиimtStopOnFlagПо умолчанию true. Если у пользователя установлен флаг _stop_processing (узел stop_processing), middleware не вызывает следующий handler и сбрасывает флаг
АвтопереходautoTransitionToУзел, на который перейти после срабатывания

💡 Паттерн «охрана группы». Связка incoming_message_trigger (фильтр group + конкретный imtGroupChatId) → stop_processing → дальнейшая логика позволяет перехватывать сообщения в группе и блокировать стандартную обработку команд/текста для этого пользователя в текущем апдейте.

⚙️ Catch-all обработчики и предохранитель. Настройка «Catch-all обработчики» (тумблер в карточке бота, env CATCH_ALL_HANDLERS=0|1, по умолчанию включена) управляет генерацией универсальных обработчиков handle_unhandled_message, handle_unhandled_photo, fallback_callback_handler. Их можно отключить для лёгких ботов, чтобы убрать лишний код. Однако при наличии incoming_message_trigger, incoming_callback_trigger или динамических кнопок эти обработчики генерируются принудительно независимо от тумблера — без подходящего хендлера middleware этих триггеров в aiogram 3 не запускается. Это предохранитель-автодетект: формула generateCatchAll = (флаг ≠ 0) || есть incoming-триггеры/динамические кнопки.

🔒 Защита контента. Настройка «Защита контента» (тумблер в карточке бота, env PROTECT_CONTENT=0|1, по умолчанию выключена) управляет генерацией обёртки, которая добавляет protect_content=True ко всем исходящим сообщениям бота (запрет копирования/пересылки). Код защиты генерируется только при включённом флаге — при выключенной защите этот блок в сгенерированный код не попадает вовсе.

🔄 Живое обновление контента. Настройка «Живое обновление контента» (тумблер в карточке бота, env CONTENT_CACHE=0|1, по умолчанию выключена) управляет генерацией машинерии live-reload контента из таблицы _content: функций load_content/reload_content, фоновой перезагрузки кэша каждые 60 сек и мгновенного обновления через Redis pub/sub. При выключении (CONTENT_CACHE=0) эта машинерия не генерируется, но аксессор get_content(...) и кэш _content_cache остаются всегда — тексты нод берутся из вшитых в код fallback-значений, а живое обновление из БД отключается. Включение повышает расход памяти.


� Триггер исходящего сообщения (outgoing_message_trigger)

Срабатывает когда бот отправляет сообщение. Позволяет реагировать на собственные действия бота.


�🔘 Триггер inline-кнопки (incoming_callback_trigger)

Срабатывает при нажатии inline-кнопки с определённым callback_data.

НастройкаОписание
Паттерн callback_dataСтрока для фильтрации (например work_)
Тип совпаденияstartsWith / equals / contains
Удалить префиксУбрать часть строки перед сохранением
Сохранить в переменнуюИмя переменной для значения callback_data

🔔 Триггер callback (callback_trigger)

Срабатывает на конкретный callback_data от inline-кнопки.

НастройкаОписание
callback_dataПаттерн для перехвата
Тип совпаденияexact — точное, startswith — начинается с
Шаблон парсингаИзвлечение переменных из callback_data
АвтопереходУзел для перехода после срабатывания

Паттерн: кросс-пользовательский сценарий (модерация, заявки)

Когда один пользователь (админ) действует в контексте другого (заявитель):

keyboard (кнопка с customCallbackData: "approve_{user_id}")
→ callback_trigger (startsWith "approve_", извлекает ID в _cb_dynamic_id)
→ bot_table READ (загружает данные по {_cb_dynamic_id})
→ edit_message / message (использует {app.*} из таблицы)

Это рекомендуемый способ реализации кросс-пользовательских сценариев. Не нужно менять движок — используй существующие ноды.

Кнопка с customCallbackData вида profile:name:{user_id} на input (или другую ноду без собственного startswith) ловится автоматически: виртуальный триггер слушает префикс profile:name:.


👥 Триггер сообщений в группе (group_message_trigger)

Срабатывает на сообщения в групповых чатах.


👤 Триггер участника (member_trigger)

Срабатывает на сервисные сообщения Telegram о входе или выходе участника из группы/супергруппы (new_chat_members, left_chat_member).

НастройкаПолеОписание
Тип событияmemberEventTypejoin — вход, leave — выход, both — оба события (два обработчика)
ID группыgroupChatIdОпциональный фильтр по чату (без префикса -100)
Источник ID группыgroupChatIdSourcemanual — из groupChatId, variable — из groupChatVariableName
Переменные входаsaveJoinedUserIdTo, saveJoinedUsernameToID и username вошедшего участника (по умолчанию joined_user_id, joined_username)
Переменные выходаsaveLeftUserIdTo, saveLeftUsernameToID и username вышедшего участника (по умолчанию left_user_id, left_username)
АвтопереходautoTransitionToУзел для перехода после срабатывания

Ограничения:

  • Бот должен быть добавлен в группу и видеть сервисные сообщения
  • При memberEventType: "both" генерируются отдельные обработчики для join и leave
  • Контекст сообщения (chat_id, message_*) заполняется через capture_message_context

⏰ Триггер по расписанию (schedule_trigger)

Запускает цепочку автоматически по расписанию.

РежимОписание
ИнтервалКаждые N минут
ЕжедневноВ указанное время каждый день
ЕженедельноПо выбранным дням недели в указанное время
CronПроизвольное cron-выражение

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


🔌 API-триггер (api_trigger)

Принимает HTTP-запрос от внешней системы (платёжка, CRM, backend) и запускает цепочку.

НастройкаОписание
МетодGET, POST, PUT, PATCH, DELETE
Путь/payment, /webhook/order и т.д.
SecretОбязателен; заголовок X-Api-Secret или Authorization: Bearer
Сохранить body/query/headersИмена переменных для данных запроса
Публичный URL{API_BASE_URL}/api/hooks/{projectId}{apiPath}

Ограничения MVP: max body 1 MB; rate limit на Node; бот офлайн → 503 bot_offline.


📤 Ответ API (api_response)

Завершает HTTP-запрос, инициированный api_trigger.

НастройкаОписание
HTTP статусКод ответа (200, 400, …)
Content-Typeapplication/json, text/plain, text/html
ТелоJSON/текст с {переменными}

Без api_response в цепочке клиент получит 200 {"ok":true}; таймаут 30 с → 504.


💬 Сообщения и контент

📝 Текстовое сообщение (message)

Отправляет текстовое сообщение пользователю. Основной узел для коммуникации.

НастройкаОписание
ТекстТекст сообщения (поддерживает {переменные})
ФорматированиеБез формата / HTML / Markdown
КлавиатураБез кнопок / Inline / Reply
Сбор вводаОжидать ответ и сохранить в переменную
Типы вводаТекст, фото, видео, аудио, документ
Условные сообщенияРазный текст в зависимости от условий
Только для админовОграничить доступ

Форматирование текста:

  • none — обычный текст
  • html — поддержка тегов <b>, <i>, <u>, <s>, <code>, <pre>, <a href="">, <tg-spoiler>
  • markdown*жирный*, _курсив_, `код`

ℹ️ Форматирование в режиме hot-reload (projectId / contentCache). Когда бот сгенерирован с горячей перезагрузкой контента, parse_mode вычисляется в рантайме в переменную _parse_mode. Статичный formatMode ноды имеет приоритет: markdownMarkdown, htmlHTML. При formatMode: "none" (или отсутствии поля) работает автодетект — HTML подставляется только если в тексте есть HTML-теги (<b>, <i>, <u>, <s>, <code>, <pre>, <a , <tg-spoiler>), иначе форматирование отключено. Ограничение: режим formatMode статичен (известен на генерации) и не перечитывается из таблицы контента — меняется только при перегенерации бота; динамически из текста определяется лишь HTML-fallback при none.


📸 Медиа-узлы

УзелЧто отправляетКлючевое поле
photoФотографиюimageUrl
videoВидеоvideoUrl
audioАудиофайлaudioUrl
documentДокументdocumentUrl, documentName
stickerСтикер
animationGIF-анимацию
locationГеолокацию
contactКонтакт

Все медиа-узлы поддерживают подпись (mediaCaption) и автопереход.


💾 Сохранить ответ (save_answer)

Сохраняет ответ пользователя (текст, фото, видео и т.д.) в переменную для дальнейшего использования в сценарии.

НастройкаОписание
ПеременнаяИмя переменной для сохранения
Типы вводаКакой контент принимать (текст, фото, видео, аудио, документ)

⌨️ Клавиатура (keyboard)

Отдельный узел клавиатуры — набор кнопок, который можно привязать к любому сообщению. Позволяет переиспользовать одну клавиатуру в нескольких местах и динамически менять кнопки по нажатию.

При нажатии кнопки с переходом на keyboard-ноду — кнопки текущего сообщения обновляются через editMessageReplyMarkup без отправки нового сообщения.

🔧 Авто-нормализация при записи через API/MCP. Если у message-ноды заданы инлайн/reply-кнопки прямо внутри неё (непустой buttons и keyboardType = inline/reply), при сохранении через API или MCP-инструменты они автоматически выносятся в отдельную keyboard-ноду (каноничная модель). В самой message при этом проставляется keyboardType: "none", buttons: [] и keyboardNodeId со ссылкой на созданную keyboard-ноду; рядом появляется keyboard-нода со смещением +360 по X. Операция идемпотентна — повторная запись не создаёт дублей. Валидация выдаёт неблокирующее предупреждение inline_keyboard_will_hoist для таких message-нод.


✏️ Редактировать сообщение (edit_message)

Редактирует текст или кнопки уже отправленного сообщения.

НастройкаОписание
editKeyboardMode: 'node'Берёт клавиатуру из привязанного keyboard-узла
keyboardLayoutЕсли задан в keyboard-узле и autoLayout: false — кнопки группируются по рядам согласно layout

Динамический callback (customCallbackData)

Кнопки, ведущие к edit_message, могут содержать customCallbackData с переменными (например "approve_{user_id}"). При нажатии динамическая часть извлекается в переменную {_cb_dynamic_id}, доступную в тексте редактирования и последующих узлах.


↗️ Переслать сообщение (forward_message)

Пересылает сообщение в другой чат.


⌨️ Кнопки

Кнопки добавляются к узлу сообщения. Тип клавиатуры:

  • Inline — кнопки под сообщением
  • Reply — кнопки под полем ввода

Действия кнопок

ДействиеЧто происходит
Перейти на узелПереход к другому блоку сценария
Открыть URLОткрывает ссылку в браузере
Mini AppОткрывает Telegram Mini App
Скопировать текстКопирует текст в буфер обмена
Запросить контактЗапрашивает номер телефона
Запросить геолокациюЗапрашивает местоположение
Создать ботаЗапрос на создание управляемого бота

Дополнительно: перемешивание кнопок (shuffleButtons) для квизов и капч.


📋 Создать тему форума (create_forum_topic)

Создаёт новый топик в форум-группе Telegram.


🔌 Интеграции и логика

🌐 HTTP-запрос (http_request)

Отправляет запрос к любому внешнему API.

НастройкаОписание
URLАдрес API (поддерживает {переменные} и ключи env бота)
МетодGET, POST, PUT, DELETE, PATCH
ЗаголовкиJSON с заголовками запроса ({имя} = сценарий + env)
ТелоJSON тело запроса
Authnone / bearer / basic / header / query — поля токена поддерживают {VAR} из env бота
ТаймаутВремя ожидания ответа (сек)
Сохранить ответИмя переменной для результата
Формат ответаJSON (по умолчанию) или файл (base64)

{имя} подставляется из переменных сценария и env бота (вкладка Бот → env у токена). При конфликте имён побеждают переменные сценария/FSM. Пример Bearer: httpRequestAuthBearerToken: "{API_TOKEN}".

🗄️ Таблица данных (bot_table)

Работа с внутренними таблицами проекта — без SQL, через визуальный интерфейс.

Операции

ОперацияОписание
ЧтениеПолучить строку(и) по условию
ВставкаДобавить новую строку (таблица создаётся автоматически)
ОбновлениеИзменить поля (атомарный increment/decrement)
UpsertВставить или обновить если существует
УдалениеУдалить строку(и) по условию
ПодсчётКоличество строк
Сумма / Макс / Мин / СреднееАгрегация по числовой колонке
УникальныеСписок уникальных значений колонки
Удалить всёОчистить таблицу

Операторы условий: равно, не равно, больше, меньше, содержит, пусто, не пусто.

Операции обновления: установить, увеличить, уменьшить, минимум, максимум — все атомарные.

Формат результата: первая строка (объект), все строки (массив), одно значение, количество, случайная строка.

Поддерживает сортировку, лимит, смещение (пагинация) и динамические имена таблиц через переменные.


🐘 PostgreSQL запрос (psql_query)

Выполняет произвольный SQL-запрос к базе данных.

НастройкаОписание
SQL-запросЛюбой SQL (поддерживает {переменные})
Сохранить результатИмя переменной
Формат результатаПервая строка / Все строки / Одно значение
Источник подключенияВстроенная БД / Переменная окружения / Строка подключения

Когда использовать: сложные JOIN, аналитика, кросс-таблицы. Для простого CRUD лучше bot_table.


Преобразование файлов между форматами (например PDF → изображение, аудио → другой формат).


Ветвление логики: «если... то... иначе...»

НастройкаОписание
ПеременнаяКакую переменную проверять
ВеткиСписок условий с целевыми узлами

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

Значения в условиях поддерживают переменные: {user.balance}, {item.price}.


📝 Установить переменную (set_variable)

Задаёт, изменяет или вычисляет переменные.

РежимЧто делаетПример
ТекстПростая подстановка"Привет, {first_name}"
ВыражениеАрифметика (+, -, *, /, %)"{balance} - 50"
Случайное числоЧисло в диапазонеот 500 до 900
Случайный элементИз списка через запятую"🔧,💥,💡,⚡"
Элемент массиваПо индексу или ключуdata.users.0.name
TimestampТекущее время ± смещение"90" = сейчас + 90 сек
Форматирование времениСекунды → MM:SS"{expires} - {now}"
Поиск в таблицеLookup по условию
Замена подстрокиstr_replace"старое""новое"
Добавить в массивjson_pushJSON-объект в массив
Форматировать массивjson_formatМассив → строка
Regex извлечениеИзвлечь по регулярке"(\d+)\s*руб" группа 1 → "7216970"
Число из строкиextract_number"{text}" → первое число
Разделить и взятьsplit_get"{email}" sep=@ idx=1 → домен
JSON по ключуjson_get"{api}" path=data.user.name
Подстрокаsubstring"{id}" start=0 end=8
Условие (если/иначе)conditionalесли {balance} > 1000 → "💰", иначе → "💸"
Нижний регистрlowercase"{text}" → все строчные
Верхний регистрuppercase"{text}" → все заглавные
Убрать пробелыtrim" текст ""текст"
Длинаlength"[1,2,3]""3"
Объединение массивовarray_concatvalue: "{arr1}", concatWith: "{arr2}" → склеенный массив

Сохранение в PostgreSQL (persistToDb)

У каждого присваивания в массиве assignments можно включить флаг persistToDb: true. После записи значения в user_data оно дополнительно сохраняется в PostgreSQL через set_user_var — переменная переживает перезапуск бота (при включённой пользовательской БД).

{ "id": "a1", "variable": "reputation", "value": "{reputation} + 10", "mode": "expression", "persistToDb": true }

ℹ️ Работает только при включённой пользовательской БД бота. Без неё флаг игнорируется.


🛑 Стоп обработки (stop_processing)

Устанавливает user_data[user_id]['_stop_processing'] = True для текущего пользователя. Используется вместе с incoming_message_trigger и включённым imtStopOnFlag: middleware триггера увидит флаг и не вызовет следующий handler в цепочке aiogram для этого апдейта.

НастройкаОписание
АвтопереходСледующий узел после установки флага (enableAutoTransition: true)

Флаг сбрасывается автоматически при следующем проходе middleware incoming_message_trigger.


📊 Счётчик частоты (rate_counter)

In-memory счётчик событий в скользящем временном окне (deque по ключу). Каждый вызов узла добавляет метку времени и удаляет устаревшие записи за пределами окна.

НастройкаПолеОписание
Ключ счётчикаcounterKeyУникальный ключ (поддерживает {переменные}, напр. {user_id})
ОкноwindowSecondsРазмер окна в секундах (по умолчанию 60)
РезультатsaveResultToИмя переменной для количества событий в окне (по умолчанию rate_count)
АвтопереходautoTransitionToСледующий узел (enableAutoTransition: true)

Ограничения:

  • Данные хранятся только в памяти процесса — при перезапуске бота счётчики обнуляются
  • Типичное применение: антиспам, лимиты действий, детекция флуда

🧮 Inline-выражения ({=...})

Вычисление формул прямо в тексте сообщения без отдельной ноды set_variable.

СинтаксисРезультатОписание
{=credits - price}3800Арифметика
{=thousands(credits)}5 000Форматирование числа
{=round(score / games, 2)}70.58Округление
{=max(hp - damage, 0)}0Функции min/max

Поддерживается в любом текстовом поле: messageText, mediaCaption, button text, httpRequestUrl и т.д.

Доступные функции: round, abs, int, float, min, max, str, reversed, thousands.

Доступные методы строк: replace, strip, lstrip, rstrip, lower, upper, startswith, endswith, split, join, count, find, format и проверки isdigit, isnumeric, isdecimal, isalpha, isalnum, isspace.

Генераторы и comprehension не поддерживаются — такое выражение вернётся как текст, не вычислившись. Чтобы отсечь нечисловой ввод, применяйте isdigit, а не comprehension.

При ошибке или невалидном выражении текст {=...} остаётся без изменений (бот не падает).


🔄 Цикл (loop)

Итерация по массиву данных.

НастройкаОписание
ИсточникПеременная с массивом
Переменная элементаИмя для текущего элемента (доступ: {item.field})
Переменная индексаИмя для номера итерации (0, 1, 2...)
ПараллельноВыполнять все итерации одновременно
ЗадержкаПауза между итерациями (сек)
ЛимитМаксимум итераций (0 = без лимита)
Тело циклаПервый узел внутри цикла
После циклаУзел после завершения

⚡ Параллельная группа (parallel_split)

Одновременный запуск нескольких независимых веток сценария (fan-out). Каждая ветка — отдельная asyncio-задача; точки сбора (join) нет.

НастройкаОписание
ВеткиСписок веток: подпись + стартовая нода. Каждая ветка — отдельный порт на холсте
При ошибке веткиНеобязательная нода-фоллбек (обычно setv-инкремент, чтобы сбор не завис)
Максимум одновременныхЛимит веток через Semaphore (0 = без лимита, по умолчанию 5) — защита от FloodWait
Не запускать повторноВключено по умолчанию — повторное нажатие блокируется, пока прогон не завершён
Ждать завершения всехПо умолчанию выключено (fire-and-forget)

Сбор результатов (join без join-ноды): каждая ветка в конце инкрементит счётчик (set_variable, mode=expression — инкремент атомарный), а condition проверяет «все ли финишировали» — последняя завершившаяся ветка запускает итог.

Ограничения:

  • Внутри веток нельзя использовать input — FSM один на пользователя
  • Триггеры внутри веток не имеют смысла (это точки входа)
  • Сброс счётчика сбора ставить до ноды, не внутри веток

Подробная концепция и сценарии: docs/futures/nodes/parallel-split-node.md.


⏱️ Задержка (delay)

Пауза перед следующим действием.

НастройкаОписание
ВремяЗначение (поддерживает {переменные}; для секунд — дробные, напр. 0.1)
ЕдиницаСекунды / минуты / часы / дни / недели
РежимБлокирующий — ждёт, потом продолжает. Фоновый — текущая цепочка завершается, переход через N времени

💻 Python-код (code)

Выполняет произвольный Python как тело async-функции. Позволяет заменить длинную цепочку userbot-нод одним узлом.

НастройкаОписание
СкриптAsync-тело с await (не оборачивать в async def самому)
Следующий узелautoTransitionTo + enableAutoTransition: true

Пространство имён

ИмяЧто это
переменные пользователяДоступны просто по имени, без user_data[...]
client, userbot_clientTelethon-клиент юзербота (тот же, что у userbot-узлов)
botЭкземпляр aiogram Bot — правка сообщений самого бота, прогрессбар
user_idID текущего пользователя
user_dataПеременные текущего пользователя
all_user_dataВсе пользователи: all_user_data[user_id]
set_user_varФункция записи переменной пользователя
callback_query, stateОбъекты aiogram текущего апдейта, могут быть None
asyncio, json, re, math, datetime, logging, Button, eventsПредзагруженные модули

Возврат значений

Присваивание на верхнем уровне кода автоматически сохраняется в переменные пользователя:

lucky_payment = 8942

Внутри вложенных функций локальное присваивание наружу не попадёт — пишите напрямую в _ns:

async def _worker():
_ns['lucky_payment'] = 8942

set_user_var во вложенных функциях недоступна, только _ns[...].

Не сохраняются: имена, начинающиеся с _, предзагруженные модули, функции и классы.

Прогрессбар

bot в пространстве имён позволяет обновлять сообщение по ходу работы — полезно, когда узел опрашивает много внешних ботов:

await bot.edit_message_text('Опрашиваю… 3/15', chat_id=chat_id,
message_id=progress_msg_id, parse_mode='HTML')

Ограничения и грабли

  • Таймаут 180 секунд на весь узел; ошибка не рвёт переход дальше.
  • Нужны USERBOT_API_ID, USERBOT_API_HASH, USERBOT_SESSION_STRING, иначе Telethon-вызовы не сработают (остальной Python — сработает).
  • Self-hosted: полный доступ к сессии аккаунта, без RestrictedPython.
  • Одна userbot-сессия на процесс. Не запускайте параллельно внешний скрипт на той же сессии — Telegram может разлогинить одного из клиентов.
  • asyncio.wait_for начинает отсчёт сразу. Если задачи ждут в очереди семафора, таймаут выгорит на ожидании — ставьте wait_for внутри воркера, а не вокруг всей очереди.
  • MessageButton.click() у Telethon ждёт answerCallbackQuery и падает с BotResponseTimeoutError, если бот не отвечает. Оборачивайте в asyncio.wait_for(..., timeout=2..3).

📥 Ожидание ввода (input)

Единственный способ сбора ввода. Message-нода только отправляет вопрос, input-нода ожидает и сохраняет ответ.

⛔ Поля collectUserInput, inputVariable в message-ноде — запрещены. Используйте только отдельную ноду input.

Типичные цепочки:

  • Текстовый ввод: messageinput → следующий узел
  • Кнопочный ввод: messagekeyboardinput (callback) → следующий узел
НастройкаОписание
ПеременнаяКуда сохранить ответ
Тип вводаТекст / фото / видео / аудио / документ / геолокация / контакт / callback
Следующий узелКуда перейти после получения ответа
Режим записиЗаменить / добавить к существующему
Валидацияemail / phone / number / min-max длина
Сохранить метаданныеДополнительные переменные с информацией о файле
Таймаут ожиданияinputTimeout — лимит в секундах (число > 0). По истечении FSM сбрасывается, пользователю отправляется inputTimeoutMessage
Сообщение при таймаутеinputTimeoutMessage — текст при истечении (по умолчанию «Время ожидания истекло.»)

Отмена формы (/cancel)

При активном сборе ввода бот автоматически регистрирует команду /cancel. По ней вызывается _clear_form_session — FSM сбрасывается, пользователь получает ответ «Форма отменена.». Обработчик генерируется только если в проекте есть хотя бы одна input-нода с активным сбором ввода.

Метаданные медиа

При включении "Сохранить метаданные медиа" для медиа-типов (фото, видео, аудио, документ) бот автоматически создаёт дополнительные переменные с суффиксами:

СуффиксОписаниеТипы
_file_idTelegram file_idвсе
_file_unique_idУникальный ID файлавсе
_thumbnailfile_id обложкивидео, аудио, документ
_durationДлительность (сек)видео, аудио
_file_sizeРазмер файла (байт)все
_file_nameИмя файлавидео, аудио, документ
_width / _heightРазмеры (px)фото, видео
_mime_typeMIME типвидео, аудио, документ
_title / _performerНазвание / исполнительаудио
_small_file_idfile_id миниатюрыфото
_all_sizesJSON всех размеровфото

Пользователь может выбрать какие метаданные сохранять и задать кастомные имена переменных.


✏️ Действия с сообщениями

УзелЧто делает
delete_messageУдаляет одно или несколько сообщений
pin_messageЗакрепляет сообщение в чате
unpin_messageОткрепляет сообщение
answer_callback_queryВсплывающее уведомление при нажатии inline-кнопки

🗑️ Удалить сообщение (delete_message)

Полноценная action-нода для удаления сообщений. Может стоять в любом месте сценария.

НастройкаОписание
Источник сообщенияcurrent_message — текущее сообщение пользователя
last_bot_message — последнее сообщение бота
reply_message — сообщение, на которое ответили (reply)
range_from_reply — все сообщения от reply до текущего (пург)
last_n — последние N сообщений (по диапазону ID)
custom — указать ID вручную или через {переменную}
Чатcurrent_chat — текущий чат
custom — указать ID чата или {переменную}
Игнорировать ошибкиНе прерывать сценарий если сообщение не найдено (вкл по умолчанию)
Массовое удалениеПеременная с JSON-массивом message_id (до 100 за вызов, автобатчинг)
АвтопереходСледующий узел

Ограничения Telegram:

  • Бот удаляет чужие сообщения только в группах (нужны права can_delete_messages)
  • Сообщения старше 48 часов удалить нельзя
  • В личных чатах бот удаляет только свои сообщения
  • deleteMessages принимает до 100 ID за один вызов (автоматически разбивается на батчи)

👥 Действия с пользователями (группы)

УзелЧто делает
ban_userЗабанить пользователя в группе
unban_userРазбанить
mute_userЗамутить (запретить писать)
unmute_userРазмутить
kick_userИсключить пользователя из группы
promote_userНазначить администратором
demote_userСнять права администратора
admin_rightsУстановить конкретные права

👢 Исключить пользователя (kick_user)

Исключает пользователя из группы через unbanChatMember(only_if_banned=False). Пользователь удаляется из чата, но может вернуться по ссылке-приглашению.

НастройкаОписание
Источник пользователяcurrent_user — отправитель сообщения-триггера
reply_user — автор сообщения, на которое ответили (reply)
custom — указать ID вручную или через {переменную}
Чатcurrent_chat — текущий чат
custom — указать ID чата или {переменную}
Игнорировать ошибкиНе прерывать сценарий если пользователь не в чате или бот не имеет прав (вкл по умолчанию)

Ограничения Telegram:

  • Бот должен быть админом с правом «Блокировка участников» (can_restrict_members)
  • Работает только в группах и супергруппах

🔗 Переменные

Переменные используются в текстах, URL, SQL-запросах и других полях через синтаксис {имя}.

Системные переменные

ПеременнаяОписание
{user_id}Telegram ID пользователя
{username}Username пользователя
{first_name}Имя
{last_name}Фамилия
{chat_id}ID чата (заполняется при входящем сообщении)
{chat_type}Тип чата: private, group, supergroup, channel
{message_text}Текст или подпись последнего сообщения
{message_type}Тип содержимого: text, photo, video, document и т.д.
{callback_data}Данные нажатой кнопки
{reply_to_user_id}ID автора сообщения, на которое ответили
{reply_to_username}Username автора сообщения-ответа
{reply_to_first_name}Имя автора сообщения-ответа
{reply_to_last_name}Фамилия автора сообщения-ответа
{reply_to_message_id}ID сообщения, на которое ответили
{reply_to_text}Текст сообщения, на которое ответили
{message_id}ID текущего сообщения

Переменные chat_id, chat_type, message_* и reply_to_* записываются функцией capture_message_context в обработчиках команд, текста, входящих сообщений и триггера участника (member_trigger). Переменные reply_to_* заполняются только если входящее сообщение является ответом (reply) на другое сообщение; иначе остаются пустыми.

Пользовательские переменные

Создаются через узлы set_variable, bot_table, http_request, psql_query и сбор ввода.

Вложенный доступ: {response.data.user.name}, {profile.balance}.


🔗 Связи между узлами

Способ связиОписание
АвтопереходАвтоматический переход после выполнения узла
Кнопка → узелПереход при нажатии кнопки
Ветка условия → узелПереход по результату проверки
После цикла → узелПереход после завершения всех итераций

💡 Рекомендации

Когда использовать bot_table vs psql_query

ЗадачаРекомендация
Простой CRUD (профиль, баланс)bot_table — проще и безопаснее
Атомарный increment/decrementbot_table — встроено
Сложные JOIN и аналитикаpsql_query
Автосоздание таблицыbot_table

Типичные паттерны

  • Регистрация: /start → upsert профиля → приветствие
  • Профиль: /profile → чтение из таблицы → вывод данных
  • Магазин: меню с кнопками → проверка баланса → списание → подтверждение
  • Расписание: триггер по времени → SQL-обновление → отчёт в админ-чат

🟣 Юзербот (Telethon)

Узлы для работы через аккаунт пользователя (Telethon MTProto). Работают параллельно с основным ботом.

📤 Сообщение юзербота (userbot_message)

Отправляет сообщение от аккаунта пользователя через Telethon. Поддерживает текст, медиа, переменные, несколько получателей.

НастройкаОписание
ПолучателиСписок entity: @username, числовой ID, {переменная}, 'me'
Текст сообщенияПоддерживает {переменные} и HTML/Markdown форматирование
МедиафайлыЛокальные файлы (/uploads/) или URL
Режим форматированияhtml, markdown, none
Отключить превью ссылокНе показывать превью URL в сообщении
Сохранить ID сообщенияПеременная для message_id отправленного сообщения
Сохранить ID ответаПеременная для ID ответного сообщения от получателя (saveResponseIdTo)
Сохранить текст ответаПеременная для текста ответного сообщения (saveResponseTextTo)
Сохранить кнопки ответаПеременная для кнопок ответа как JSON-массив [{text, type, data?, url?}] (saveButtonsTo)
АвтопереходУзел для перехода после отправки

Ограничения:

  • Кнопки (inline/reply) НЕ поддерживаются — ограничение Telegram для user-аккаунтов
  • File_id от Bot API нельзя использовать в Telethon (разные сессии)
  • Лимит: ~50 сообщений/день разным пользователям, 1 сообщение/секунду в один чат
  • Встроенная защита от FloodWait с автоматическим retry

Требования:

  • В настройках бота должен быть включён и авторизован Telethon Userbot
  • Переменные USERBOT_API_ID, USERBOT_API_HASH, USERBOT_SESSION_STRING в .env

👆 Нажать кнопку (userbot_click_button)

Нажимает inline-кнопку в сообщении через Telethon. Поддерживает поиск по тексту, callback_data или индексу.

НастройкаОписание
Entity (чат)Чат где находится сообщение с кнопками
Источник сообщенияПоследнее сообщение / Конкретный ID
Message IDID сообщения (если конкретный)
Способ поискаПо тексту кнопки / По callback_data / По индексу (row, col)
ЗначениеТекст кнопки / callback_data / "0, 1"
Сохранить alertПеременная для текста alert от бота
Сохранить текстПеременная для текста обновлённого сообщения
Сохранить кнопкиПеременная для JSON массива кнопок (с типами)
Сохранить медиаПеременная для медиа-объекта
АвтопереходУзел для перехода после нажатия

Формат JSON кнопок:

[
{"text": "Купить", "data": "buy_btc", "type": "callback"},
{"text": "Сайт", "url": "https://...", "type": "url"},
{"text": "Меню", "type": "text"}
]

Типы кнопок: callback, url, text, switch_inline, web_app, request_phone, request_location, buy, game


🔍 Inline-запрос (userbot_inline_query)

Выполняет inline-запрос к боту (@bot query) и отправляет выбранный результат в чат.

НастройкаОписание
Bot usernameUsername бота для inline-запроса
QueryТекст запроса (поддерживает {переменные})
Отправить в тот же чатРезультат отправляется в чат с ботом
Целевой чатКуда отправить (если не в тот же)
Индекс результатаКакой результат выбрать (0 = первый)
Сохранить titleПеременная для заголовка результата
Сохранить descriptionПеременная для описания результата
Сохранить ID сообщенияПеременная для ID отправленного
АвтопереходУзел для перехода после отправки

🧰 Утилиты

📝 Комментарий (comment)

Текстовая заметка-стикер на холсте. Не влияет на логику бота — игнорируется при генерации Python-кода. Не имеет портов, связей и автоперехода.

Используется для пояснений к сценарию: помечать воронки, ветки, TODO, описывать назначение групп нод.

НастройкаОписание
Текст заметкиПроизвольный текст (поддерживает многострочный ввод)
Цвет заметкиyellow, blue, green, pink, gray — для визуального разделения зон

Содержит только два поля — messageText и commentColor. Служебных полей сообщения (buttons, keyboardType и т.п.) у ноды нет.

Ограничения:

  • Не генерирует кода и не участвует в потоке выполнения
  • Соединить с другими нодами нельзя (нет портов)
  • При авто-раскладке остаётся отдельным свободным блоком
  • В превью на холсте отображается до 200 символов