Хвост №1 из STATE ревью-правок: оформили доказанный в A2 путь пересдачи в
постоянный режим робота mode:'resubmit'. Робот берёт ОТКЛОНЁННУЮ кампанию, входит
в её редактор через «Исправить», вносит исправления и повторно отправляет на
модерацию БЕЗ ОПЛАТЫ (0 ₽ — деньги не списываются).
Что нового:
- parseResubmitTask (task.js): своё задание пересдачи — campaignId + submitMode
(draft|live, без дефолта, чтобы live не случился сам) + правки на выбор
(moderatorFile и/или adText/buttonUrl/ordCategory). Нужна хоть одна правка —
иначе тот же контент снова отклонят. Номера/бюджет не нужны (уже у кампании).
- openResubmitEditor (cabinet.js): нативный клик «Исправить» в строке кампании по
id → ждём редактор /telegram-a2p/{id}/message (в чужую кампанию не лезем).
- submitWithoutPayment (cabinet.js): на /payment жмём ТОЛЬКО «Отправить на
модерацию без оплаты»; денежные кнопки («Списать…»/«Оплатить») — двойная защита
через isForbiddenButtonText, не жмём никогда.
- editResubmitFields + вынос fillAd в хелперы (fillAdText/fillAdLink/
selectOrdCategory/fillAdMedia): пересдача правит только заданные поля тем же
проверенным кодом (DRY, поведение fillAd не изменилось).
- runResubmit (runner.js) + ветка mode:'resubmit' в bin/run.js (до parseTask, как
read-status). draft — предохранитель (до /confirmation, не шлём); live — отправка
без оплаты.
Живая проверка на реальных отклонённых кампаниях (28.07.2026):
- DRAFT (2231132, правка текста + документ): вошёл «Исправить» → правка → загрузка
документа → /confirmation → НЕ отправил (resubmitted:false, stoppedAt:confirmation).
- LIVE (2231134, правка текст+ссылка+ОРД, без документа): полный цикл → «без оплаты»
(0 ₽) → resubmitted:true; read-status подтвердил moderating. Баланс не тронут.
Робот npm test 110/110 (было 94, +16). Приёмочный лист и живые результаты:
docs/superpowers/2026-07-28-robot-resubmit-mode-ACCEPT.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
МТС-бот «Реклама в Telegram по своей базе»
1. Что это
Робот сам заходит в кабинет МТС Маркетолог (marketolog.mts.ru) и создаёт
рекламную кампанию в Telegram по загруженной базе телефонов клиентов. Работает
на Windows-сервере рядом с мостом LiderraMtsBridge (тот же сервер, что для
СМС МТС). У робота два режима: «черновик» (доходит до кнопки запуска,
ничего не тратит) и «боевой» (нажимает кнопку и списывает деньги с баланса
кабинета).
2. ⚠️ Важные предупреждения (прочитать первым)
- Кабинет МТС — это реальные деньги. На балансе кабинета лежат настоящие рубли. Робот в режиме «боевой» их тратит. Пока идёт наладка — запускать только «черновик».
- Живой вход в кабинет = доступ к деньгам. Профиль браузера бота (папка,
указанная в
MTS_BROWSER_PROFILE_DIR) — это как ключ от кассы: хранить на сервере, не копировать, никуда не выкладывать, не отправлять по почте/в чат. - Телефоны клиентов — персональные данные (152-ФЗ). Робот держит их только во временном файле на время прогона и удаляет сразу после — файл не остаётся на диске и не попадает в git. В боевых кампаниях использовать только базу с согласием клиентов на рекламные звонки/сообщения, не старые лиды без согласия.
3. Разовая настройка (один раз)
Установка зависимостей и браузера:
cd bots/mts-telegram-ads
npm install
npx playwright install chromium
Скопировать .env.example в .env и заполнить:
| Переменная | Что это |
|---|---|
MTS_BROWSER_PROFILE_DIR |
папка на диске, где браузер бота хранит вход в кабинет (профиль) |
MTS_CABINET_URL |
адрес главной страницы кабинета МТС Маркетолог |
MTS_TELEGRAM_URL |
адрес раздела «Реклама в Telegram» в кабинете |
SMTP_HOST, SMTP_PORT |
адрес и порт почтового сервера для отправки писем (Unisender Go) |
SMTP_USER, SMTP_PASS |
логин и пароль для отправки писем (те же креды, что у портала) |
ALARM_FROM |
с какого адреса приходят письма-алярмы/отчёты |
ALARM_TO |
на какой адрес слать письма-алярмы/отчёты |
BUDGET_CAP_RUB |
потолок бюджета в рублях: боевой запуск дороже этой суммы робот запрещает сам |
HUMAN_DELAY_MS |
пауза между действиями робота в кабинете (мс) — «по-человечески», не чтобы сайт заподозрил робота |
Разовый вход в кабинет. Один раз нужно открыть браузер бота в видимом режиме и вручную залогиниться (телефон/пароль + код по СМС) — после этого вход запомнится в профиле браузера, и робот дальше сможет заходить сам. Команда:
node bin/login.js
(или npm run login). Откроется окно браузера на странице кабинета — войти
руками, как обычно (телефон/пароль + код по СМС). После того как в окне
появится кабинет, вход сохранён в профиле браузера — окно можно закрыть. Это
действие делает владелец (у него доступ к телефону/паролю кабинета).
4. Файл с номерами
- Формат: по одному номеру в строке, вид
79000000000(11 цифр). Робот сам приводит к этому виду номера вида «+7…», «8…», убирает лишние символы и повторы. - Требование кабинета: минимум 367 номеров «не МТС». Реклама в Telegram по своей базе показывается только абонентам НЕ-МТС (по МТС-номерам из той же базы можно отправить СМС — в боте это выключено).
- Куда класть файл: в папку
screenshots/(она в.gitignore— номера не попадут в git). В примере задания путьscreenshots/test-phones.txt. - Где взять тестовую базу: XLSX-экспорт лидов из старого кабинета поставщика crm.bp-gr.ru — эту выгрузку делает владелец.
5. Формат задания (task.json)
| Поле | Обязательное | Что это |
|---|---|---|
mode |
да | draft (черновик, безопасно) или live (боевой, тратит деньги) |
phonesFile |
да | путь к файлу с номерами |
adText |
да | текст объявления (до 160 символов) |
adTitle |
да | заголовок объявления (до 40 символов) |
buttonUrl |
да | ссылка — что рекламируем (канал/бот/сайт) |
budgetRub |
да | бюджет кампании в рублях |
cpmRub |
да | цена за 1000 показов, рубли |
ordCompanyName |
да | название компании/сервиса — для маркировки рекламы (ОРД) |
ordCategory |
нет | категория товара/услуги для ОРД, по умолчанию «Размещение рекламы» |
mediaFile |
нет | путь к картинке/видео объявления |
clientTag |
нет | своя метка для учёта (не используется кабинетом) |
Пример (файл task.example.json):
{
"mode": "draft",
"phonesFile": "screenshots/test-phones.txt",
"adText": "Подключите наш телеграм-бот и получайте заявки быстрее",
"adTitle": "Лидерра — заявки на автопилоте",
"buttonUrl": "https://liderra.ru",
"budgetRub": 1000,
"cpmRub": 400,
"ordCategory": "Размещение рекламы",
"ordCompanyName": "Лидерра"
}
6. Запуск
Черновик (безопасно, ничего не тратит):
node bin/run.js --task task.example.json
Робот дойдёт до кнопки запуска, снимет скриншот шага и не нажмёт её. На
почту (ALARM_TO) придёт отчёт.
Боевой (тратит деньги): то же самое, но в задании "mode": "live". Запускать
только с разрешения владельца и в пределах потолка BUDGET_CAP_RUB — робот
сам сверяет бюджет задания с потолком и отказывается запускать, если бюджет
больше.
Результат прогона печатается в консоль в виде JSON, например
{"ok": true, "matched": 996, "launched": false} — matched это сколько
номеров «не МТС» нашлось, launched — нажал ли робот кнопку запуска.
6.1. Пересдача отклонённой кампании (mode: "resubmit")
Если модерация МТС отклонила кампанию, робот может её починить: войти в редактор через «Исправить», внести исправления и снова отправить на модерацию без оплаты (0 ₽ — деньги не списываются).
Что исправляем — на выбор (в ответ на причину отказа): приложить документ модератору (лицензию/справку) и/или поправить текст/ссылку/категорию ОРД. Нужна хотя бы одна правка — иначе тот же контент снова отклонят. Номера/бюджет не нужны — они у кампании уже есть.
| Поле | Обязательное | Что это |
|---|---|---|
mode |
да | resubmit |
campaignId |
да | номер кампании, которую чиним (из кабинета) |
submitMode |
да | draft (дойти до конца, не отправлять) или live (отправить без оплаты) |
moderatorFile |
нет* | путь к документу для модератора (pdf/картинка) |
adText |
нет* | новый текст объявления |
buttonUrl |
нет* | новая ссылка (канал/бот/сайт) |
ordCategory |
нет* | новая категория ОРД |
* хотя бы одно из полей-правок (moderatorFile/adText/buttonUrl/ordCategory) обязательно.
{
"mode": "resubmit",
"campaignId": "2231134",
"submitMode": "live",
"moderatorFile": "screenshots/licenziya.pdf",
"adText": "Исправленный текст объявления"
}
submitMode: "live" реально отправляет кампанию на повторную модерацию (бесплатно) —
запускать только с разрешения владельца. Результат: {"ok": true, "campaignId": "2231134", "resubmitted": true}.
7. Присмотр за входом (keep-alive)
Команда node bin/keepalive.js тихо проверяет, жив ли вход в кабинет. Если
вход слетел — робот сам отправляет письмо-алярм на ALARM_TO.
Чтобы проверка шла сама каждые 15 минут, добавить задачу в Планировщик заданий Windows (пример команды, путь заменить на реальный на сервере):
schtasks /create /tn "LiderraMtsTgKeepAlive" /tr "node C:\путь\bots\mts-telegram-ads\bin\keepalive.js" /sc minute /mo 15 /ru СИСТЕМА
8. Что делать при алярме на почте
Письмо приходит с темой вида «[МТС-бот] АЛЯРМ на шаге «...»» и приложенным скриншотом. Частые причины:
- «Вход слетел — нужен повторный логин» — повторить разовый вход из раздела 3.
- «недостаточно номеров не-МТС» (меньше 367) — нужна база побольше.
- «Шаг «Стоимость» ещё не размечен» — это ожидаемо на сегодня, см. раздел 9.
9. Текущее состояние / что ещё не готово (честно)
Реализованы и проверены (юнит-тесты ядра — все зелёные, см. npm test) шаги:
- вход в визард кампании;
- выбор «Своя база клиентов»;
- загрузка базы и подсчёт «не МТС»;
- проверка порога 367 «не МТС» (ниже — честный алярм «недостаточно номеров не-МТС», кампанию не создаём) и переход со шага «Аудитория» на «Объявление» (кнопка «Продолжить», с само-проверкой, что попали на нужный шаг, а не заполняем объявление вслепую на чужой странице);
- заполнение объявления (текст, заголовок, ссылка, блок ОРД);
- финал: черновик — стоп перед кнопкой, боевой — нажатие кнопки.
Не готово:
- Шаг «Стоимость» (бюджет/CPM) в кабинете пока не размечен — точные места на экране, куда робот должен кликать, ещё не сняты вживую. До этого робот на этом шаге штатно останавливается и шлёт алярм — это ожидаемо, не поломка.
- Часть полей объявления (точное место поля «Заголовок», «Название компании» для ОРД, поле для картинки/видео) помечены в коде как требующие подтверждения — они снимаются на первом реальном черновике.
- Приёмка «боевого» режима (один контрольный запуск на минимальном бюджете) — только с явного разрешения владельца.
10. Устройство (кратко)
| Файл | Назначение |
|---|---|
src/config.js |
читает .env, проверяет, что все нужные настройки заданы |
src/task.js |
читает и проверяет задание (task.json) |
src/phones.js |
приводит номера к формату 79..., убирает мусор и повторы |
src/budget.js |
проверяет, что бюджет боевого запуска не выше потолка |
src/mailer.js |
отправка писем-алярмов и отчётов на почту |
src/browser.js |
открывает браузер с сохранённым профилем (живым входом) |
src/session.js |
проверяет, жив ли вход в кабинет |
src/cabinet.js |
шаги визарда кабинета: вход, загрузка базы, объявление, финал |
src/runner.js |
весь прогон целиком: собирает шаги по порядку, ловит ошибки, шлёт алярм/отчёт, чистит временный файл с номерами |
bin/run.js |
команда запуска одного задания |
bin/keepalive.js |
команда проверки живого входа (для Планировщика Windows) |
docs/cabinet-flow.md |
подробная карта кабинета МТС — какие кнопки/поля где находятся |