Команды и действия: фактический контракт
На этой странице
Источник: опубликованный BFL-content, узлы «Telegram — участники проекта», «Распознать команду или решение», оба Switch, проверки кнопок/замечаний/восстановления. Это контракт кода, а не меню BotFather. Обозначения: DRAFT_ID — идентификатор материала, V — положительный номер версии; в сообщениях ошибки бот подставляет настоящие значения.
Допуск
Внешний Trigger принимает message/callback_query; до бизнес-маршрутов внутренний сервис проверяет настоящий numeric from.id, private chat.id=from.id, is_bot=false и active в реестре. Проверки повторяются перед внешними запросами. Unknown допускается только на безопасный /start. Владелец и редактор имеют одинаковые перечисленные ниже действия с общими материалами; управление правами остаётся у владельца.
Текстовые команды
| Ввод | Фактическая обработка | Аргументы / отказ |
|---|---|---|
/post Тема | Новый собственный пост, версия 1, ключ события u:update_id. | Тема — весь непустой хвост; отдельного ограничения длины темы в парсере нет. Команда нечувствительна к регистру. |
/post | Сообщение «Добавьте тему после команды. Например: /post Что важно знать перед обращением за банкротством». | Пробелы без темы также дают подсказку. |
/post@bflcontentbot Тема | Поддерживается актуальным regex. | Тема непустая; эта строка исправляет ошибку прежнего экспорта. |
/news | Поиск за 7 календарных дней, без тематического фильтра. | Окно включает сегодняшний день в Europe/Moscow. |
/news кредиты | 7 дней, тема «кредиты». | Тема максимум 200 UTF-16 единиц после NFC/trim; управляющие символы запрещены. |
/news 7 [тема] | Явно 7 дней. | Допустимый период. |
/news 30 [тема] | Явно 30 дней. | Например /news 30 МФО. |
/news 14 | news_help, бот перечисляет правильные команды. | Начальный целый числовой токен допускает только 7 или 30; слишком длинная/недопустимая тема тоже даёт подсказку. |
/news@bflcontentbot 30 | Поддерживается, имя бота и команда сравниваются без учёта регистра. | Чужой @username не считается /news. |
/retry DRAFT_ID V | Продолжение известного text_failed без новых редакционных замечаний. | Только последняя версия общего проекта, без preview/approval/published ID и без outcome_unknown. Создаёт новую версию; старую сохраняет. |
/retry DRAFT_ID V замечания | То же с новыми замечаниями. | ID: [A-Za-z0-9_-]{1,40}; V: [1-9]\d{0,8}. Команда регистрозависима; допускается @bflcontentbot. |
/resume DRAFT_ID V | Возобновляет импорт PNG, рендер или подготовку превью той же версии. | Только последняя photo_caption_v1, без approval/published, status из image_upload_failed, render_failed, preview_failed. Не разрешает повтор неопределённой генерации/отправки. Синтаксис ID/V как у /retry, без хвоста замечаний. |
/retry не является универсальным повтором. Для первой собственной темы после text_failed обработчик требует подходящего родителя правки, которого может не быть; сообщение предлагает новый /post. Для первой новости предусмотрено продолжение сохранённого source/fact_pack и пригодного текста. Для неудачной доработки нужны подходящий родитель superseded/awaiting_feedback, сохранённая подпись и тот же исходник изображения.
Неправильный синтаксис /retry//resume не порождает отдельную подсказку. Распознанная команда с неподходящим состоянием заканчивает ветку без новых API и сообщений. Switch.fallbackOutput=none.
/start реализован: разрешённому участнику роль/команды, неизвестному собственный ID и сообщение об отсутствии доступа. /help и /cancel не реализованы. Вне reply-контекста неизвестный текст/команда обычно получает null и остаётся без ответа. Если неизвестный текст, включая строку вида /help, отправлен ответом на сообщение, парсер может передать его как feedback; затем проверяется ID именно ожидаемого force-reply сообщения. Это не реализация команды помощи.
Кнопки
| Надпись | callback_data | Условия и действие |
|---|---|---|
| Подготовить пост | news:BATCH_ID:ITEM_ID | BATCH_ID 1–16, ITEM_ID 1–12 ASCII букв/цифр/_/-. Активный участник, private, зарегистрированная доставленная ему копия карточки, связанная ready-подборка, offered-карточка, срок не истёк. Атомарный claim по статье и выбору до подготовки. |
| Опубликовать | p|DRAFT_ID|V | Последняя awaiting_approval, правильное сообщение согласования, целостный текст/обложка, нет публикации/дубля; CAS переводит в publishing перед sendPhoto. |
| Доработать | r|DRAFT_ID|V | Те же guards готовой версии; перевод в awaiting_feedback и force-reply приглашение. |
| Отклонить | x|DRAFT_ID|V | Те же guards; status=rejected. Данные и картинка остаются; публикации нет. |
Кнопка относится к комплекту конкретной версии. Дополнительно проверяются preview_photo_state=sent, совпадение approval/preview message ID, хеши, размер/шаблон, подпись и источник, отсутствие отправок в канал и повторного event_key. Для новостей нужен news_validation=verified.
Неверные форматы callback отбрасываются. Для корректного старого callback бот показывает всплывающий ответ о неактивной версии либо о текущей работе. Для повторного выбора статьи — отдельный ответ о том, что статья уже выбрана. Удаление кнопок Telegram не служит защитой: защита основана на БД.
Ответ с замечаниями
Нужно отвечать на сообщение «Напишите замечания к версии v{V} ответом на это сообщение.», а не просто писать боту. Проверяются reply_to_message.message_id, сохранённый feedback_prompt_message_id, инициатор закреплённой сессии, его private-чат, awaiting_feedback и последняя версия. update_id защищён от повторного использования.
Точная замена без исходной генерации текста распознаётся для форм вроде Замени «старая фраза» на «новая фраза» или Замени последнее предложение на: «новое предложение». Картинку и остальной текст сохранить. Нужен единственный точный исходный фрагмент; принимаются кавычки «…» или "…". Это узкий regex, не любой свободный пересказ инструкции. Для новости меняется body, ссылка добавляется обратно и сохраняется смысловая проверка.
Изменение заголовка — обычное замечание, отдельной команды нет. Явная смена картинки определяется regex: «измени/поменяй/замени/перерисуй [саму/эту/исходную/только] картинку/иллюстрацию/изображение», «создай/сгенерируй/сделай/нарисуй новую/другую …» и обратный порядок «картинку измени». Перед этим удаляются фразы «не изменяй/меняй/заменяй/трогай картинку…». Произвольные синонимы и отрицания не гарантированы; см. findings.md.
Служебные входы
Основной workflow имеет Execute Workflow Trigger «Внутреннее задание БФЛ». В текущих settings callerIds указаны BFLNewsInitial04, BFLNewsInitial041, BFLNewsRouteResume, BFLEditorPostResume339. Наличие имени в allowlist не доказывает его активность; новый экспорт включает только последний из этих служебных workflow, и он неактивен.
technical_retry использует сохранённый материал и обычный маршрут восстановления; это не команда Telegram. Одноразовое продолжение execution 339 дополнительно требует серверного доказательства остановки до внешнего запроса, действующей роли и успешного атомарного захвата. Доказательство уже использовано.
В экспортированных схемах нет Schedule Trigger/Cron. Wait относятся к ограниченному повтору уведомления после подтверждённого 429. Публикация по расписанию не настроена.
Доставка и согласование двух участников
Новые карточки и готовые версии получают оба. Callback форматы прежние, но проверяется своя зарегистрированная копия. Старая owner-копия может использоваться владельцем по прежним полям; редактор не получает автоматического доступа к недоставленной истории. Одновременные действия проходят общий захват версии/статьи. Одобрения одного участника достаточно, расписаний нет.
Уточнение /post после исправления
/post тема — самостоятельная команда владельца или редактора. Роль проверяется по numeric ID и active; подборка /news заранее не нужна. Создаётся одна общая версия, статус получает инициатор до платной генерации, превью — оба. Служебный мост BFLEditorPostResume339 не является командой пользователя и не создаёт Telegram update. Его доказательство восстановления уже использовано; повторный вызов блокируется.
Стандартные /retry и /resume не были расширены для слепого повтора. Подтверждённая оператором остановка до запроса — отдельная исключительная процедура с доказательством и одноразовым захватом; неизвестный исход внешнего запроса её не допускает.