mirror of
https://github.com/anten-ka/gotelegram_pro.git
synced 2026-05-19 18:36:18 +00:00
docs(v2.4.3): changelog + bot action bridge + flock race fix
- Header version bumped 2.4.1 -> 2.4.3 in both docs - DOCS_HUMAN.md changelog: 2.4.2 (bot can change template/domain) + 2.4.3 (flock race fix) - DOCS_AI.md section 11.1 (new): non-interactive action bridge contract - action list, JSON format, error codes, flock serialization semantics - DOCS_AI.md section 10: bugs #24-28 (safe_edit_message TypeError, template_id field name, jq 1.5 compat, validation, flock race) - DOCS_AI.md changelog: 2.4.2 + 2.4.3 entries
This commit is contained in:
44
DOCS_AI.md
44
DOCS_AI.md
@@ -1,6 +1,6 @@
|
|||||||
# GoTelegram Pro — техническая документация для ИИ-агентов
|
# GoTelegram Pro — техническая документация для ИИ-агентов
|
||||||
|
|
||||||
**Версия:** 2.4.1
|
**Версия:** 2.4.3
|
||||||
**Репозиторий:** `anten-ka/gotelegram_pro`
|
**Репозиторий:** `anten-ka/gotelegram_pro`
|
||||||
**Активная ветка:** `alfa-test` (ветка `test` заморожена и содержит stable для конечных пользователей)
|
**Активная ветка:** `alfa-test` (ветка `test` заморожена и содержит stable для конечных пользователей)
|
||||||
**Целевая ОС:** Ubuntu 20.04+, Debian 11+
|
**Целевая ОС:** Ubuntu 20.04+, Debian 11+
|
||||||
@@ -349,6 +349,11 @@ Fallback: если по известным правилам index.html не на
|
|||||||
21. **КРИТИЧЕСКИЙ StartBootstrap dist/** — sb_* шаблоны хранят production в `dist/`. Фикс: клонируем в `$sb_tmp`, проверяем `dist/index.html`, копируем `dist/*` в `$clone_dir`, + universal fallback через `find`.
|
21. **КРИТИЧЕСКИЙ StartBootstrap dist/** — sb_* шаблоны хранят production в `dist/`. Фикс: клонируем в `$sb_tmp`, проверяем `dist/index.html`, копируем `dist/*` в `$clone_dir`, + universal fallback через `find`.
|
||||||
22. **templates_catalog.sh ls stdout leak** — `ls -la` в блоке ошибки `download_template` шёл в stdout. Фикс: `>&2`.
|
22. **templates_catalog.sh ls stdout leak** — `ls -la` в блоке ошибки `download_template` шёл в stdout. Фикс: `>&2`.
|
||||||
23. **КРИТИЧЕСКИЙ start_telemt stale config (v2.4.1)** — `systemctl start` это no-op для уже активного сервиса. После переустановки Lite поверх Pro конфиг на диске менялся, но telemt держал в памяти старый `tls_domain=anten-ka.com` и дропал клиентов с SNI=google.com. Фикс: `start_telemt` теперь делает `restart` если сервис уже активен. См. `lib/telemt.sh:189-213`.
|
23. **КРИТИЧЕСКИЙ start_telemt stale config (v2.4.1)** — `systemctl start` это no-op для уже активного сервиса. После переустановки Lite поверх Pro конфиг на диске менялся, но telemt держал в памяти старый `tls_domain=anten-ka.com` и дропал клиентов с SNI=google.com. Фикс: `start_telemt` теперь делает `restart` если сервис уже активен. См. `lib/telemt.sh:189-213`.
|
||||||
|
24. **КРИТИЧЕСКИЙ safe_edit_message TypeError (v2.4.2)** — в iter2 аудите субагент нашёл: `cb_pro_confirm` в success-пути вызывал `safe_edit_message(query, text, ..., disable_web_page_preview=True)`, но сигнатура обёртки этот kwarg не принимала. Runtime TypeError прямо в хэппи-пути смены шаблона из бота. Фикс: добавлен `disable_web_page_preview: Optional[bool] = None` + условный форвард через `**kwargs`.
|
||||||
|
25. **template_id field name mismatch (v2.4.2)** — `save_gotelegram_config` всегда писал ключ `template_id`, но `bot.py` читал `config.get('template')` и писал `config['template']` в `handle_text_message`. Результат: статус шаблона в боте никогда не отображался, а поле в JSON появлялось фантомно и не использовалось. Фикс: везде только `template_id`. Исторические чтения совместимы через `config.get("template_id") or config.get("template")` для legacy конфигов.
|
||||||
|
26. **jq 1.5 compat в bot_update_config_field (v2.4.2)** — использовалось `jq '... | .updated_at = (now | todate)'`, но фильтр `now|todate` только с jq 1.6. На Debian 10 jq 1.5 падал с syntax error, config не обновлялся. Фикс: генерим timestamp через `date -Iseconds` в shell и передаём через `jq --arg t`.
|
||||||
|
27. **Отсутствующая валидация tpl_id/domain (v2.4.2)** — `tpl_id` из `callback_data` и `domain` из текстового ввода передавались напрямую в subprocess как `--template=$x`. Defense-in-depth: в bot.py добавлены `_TPL_ID_RE = ^[A-Za-z0-9_-]{1,64}$` и `_DOMAIN_RE`, в install.sh — `validate_domain` перед `generate_telemt_toml`. Малформный ввод отвергается early.
|
||||||
|
28. **КРИТИЧЕСКИЙ race в bot_action_dispatch (v2.4.3)** — iter3-тест с 3 параллельными `change-lite-domain` дал `{"status":"error","code":"no_secret"}` на одном из вызовов. Причина: `bot_update_config_field` делает `jq ... > tmp && mv tmp config.json`; когда параллельный процесс заходил в `get_config_value secret` в момент между `>` и `mv`, он видел пустой/частичный файл. `asyncio.Lock` в боте ловил только внутри-процессные гонки, но не CLI-level. Фикс: `flock -w 30 9 < /var/lock/gotelegram-bot-action.lock` вокруг всего диспатчера. Новый error code: `lock_timeout` (`EX_TEMPFAIL`=75).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -358,13 +363,42 @@ Fallback: если по известным правилам index.html не на
|
|||||||
|
|
||||||
Ключевые моменты:
|
Ключевые моменты:
|
||||||
- **Admin ID** — бот отвечает только пользователю с `ADMIN_TG_ID` из `.env`. Всё остальное игнорируется.
|
- **Admin ID** — бот отвечает только пользователю с `ADMIN_TG_ID` из `.env`. Всё остальное игнорируется.
|
||||||
- **safe_edit_message** — обёртка над `query.edit_message_text` + `query.edit_message_caption`, глотает `BadRequest: message is not modified`. Используй её всегда вместо прямого вызова.
|
- **safe_edit_message** — обёртка над `query.edit_message_text` + `query.edit_message_caption`, глотает `BadRequest: message is not modified`. Начиная с v2.4.2 принимает опциональный `disable_web_page_preview` — не забудь прокинуть его если показываешь ссылку-превью (раньше вызов с этим kwarg ловил TypeError в runtime). Используй её всегда вместо прямого вызова.
|
||||||
- **Language per-user** — файл `locales/users.json` хранит `{user_id: "ru"/"en"}`. При каждом сообщении бот читает язык пользователя и подставляет строку через `t(key, lang)`.
|
- **Language per-user** — файл `locales/users.json` хранит `{user_id: "ru"/"en"}`. При каждом сообщении бот читает язык пользователя и подставляет строку через `t(key, lang)`.
|
||||||
- **QR-коды** — генерятся в `/tmp/gotelegram_qr_*.png`, отправляются как `InputFile`, удаляются в `finally`.
|
- **QR-коды** — генерятся в `/tmp/gotelegram_qr_*.png`, отправляются как `InputFile`, удаляются в `finally`.
|
||||||
- **Шаблон preview в HTML** — URL экранируется через `html.escape(url, quote=True)` (баг #11).
|
- **Шаблон preview в HTML** — URL экранируется через `html.escape(url, quote=True)` (баг #11).
|
||||||
- **Системные действия** — бот вызывает тот же `install.sh` через `subprocess.run(["bash", "/opt/gotelegram/install.sh", "--action=...", "--json"])` (флаги add как задача на будущее).
|
- **Системные действия (v2.4.2+)** — бот реально умеет менять шаблон и домен маскировки. Хелпер `run_bot_action(action, **kwargs)` вызывает `subprocess.run(["/opt/gotelegram/install.sh", "--action=X", "--json", ...])` и парсит JSON. Два коллбэка: `cb_pro_confirm` (change-template) и `cb_lite_domain` (change-lite-domain). Оба обёрнуты в `async with _BOT_ACTION_LOCK` (глобальный `asyncio.Lock()`) — сериализуют параллельные callback'и внутри процесса бота. Входы валидируются ДО subprocess: `_TPL_ID_RE = r"^[A-Za-z0-9_-]{1,64}$"`, `_DOMAIN_RE` (RFC-like). Малформный ввод отвергается с понятным сообщением, не доходя до shell.
|
||||||
|
- **Поле `template_id` в config.json** — канонический ключ для текущего шаблона. Раньше (до v2.4.2) бот читал `config['template']` и писал в него же в `handle_text_message`, но `save_gotelegram_config` всегда писал `template_id` → поле статуса никогда не отображалось. Используй только `template_id`.
|
||||||
- **Устанавливается** из меню `install.sh → 12) Telegram-бот → Установить`. Пользователь вводит BotFather token + свой Telegram ID, `.env` пишется в `/opt/gotelegram-bot/.env`.
|
- **Устанавливается** из меню `install.sh → 12) Telegram-бот → Установить`. Пользователь вводит BotFather token + свой Telegram ID, `.env` пишется в `/opt/gotelegram-bot/.env`.
|
||||||
|
|
||||||
|
### 11.1 Non-interactive action bridge (install.sh ↔ bot)
|
||||||
|
|
||||||
|
Бот общается с CLI через жёсткий JSON-протокол. Единая точка входа — `bot_action_dispatch` в `install.sh`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/opt/gotelegram/install.sh --action=<name> [--template=ID|--domain=HOST] --json
|
||||||
|
```
|
||||||
|
|
||||||
|
**Доступные action'ы:**
|
||||||
|
- `change-template --template=<tpl_id>` — только в Pro режиме. Скачивает шаблон, деплоит в nginx, обновляет `config.json.template_id`.
|
||||||
|
- `change-lite-domain --domain=<host>` — только в Lite режиме. Регенерит telemt TOML с новым `tls_domain`, валидирует, рестартит telemt, обновляет `config.json.{domain,mask_host}`.
|
||||||
|
|
||||||
|
**Формат ответа (stdout, последняя строка):**
|
||||||
|
```json
|
||||||
|
{"status":"success","message":"...","<extra>":"..."}
|
||||||
|
{"status":"error","message":"...","code":"<machine_code>"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Коды ошибок: `missing_arg`, `invalid_domain`, `wrong_mode`, `unknown_template`, `download_failed`, `deploy_failed`, `no_secret`, `gen_failed`, `validate_failed`, `restart_failed`, `unknown_action`, `lock_timeout`.
|
||||||
|
|
||||||
|
**Сериализация (v2.4.3):** `bot_action_dispatch` оборачивает вызов в `flock -w 30 9 < /var/lock/gotelegram-bot-action.lock`. Это защищает от гонок при:
|
||||||
|
1. Одновременных callback'ах внутри бота (asyncio.Lock уже ловит это, но flock — defense-in-depth).
|
||||||
|
2. Параллельных CLI-вызовах (бот + ручной SSH, или два бот-процесса — теоретически).
|
||||||
|
|
||||||
|
Если таймаут лока (30 с), диспетчер возвращает `exit 75` (`EX_TEMPFAIL`) и JSON `{"status":"error","code":"lock_timeout"}`. `flock` идёт из `util-linux` — добавлен в `critical` зависимости в `ensure_deps`.
|
||||||
|
|
||||||
|
**История:** до v2.4.2 коллбэки были stub'ами («сделай через CLI»). В v2.4.2 подключили реальные action'ы. В iter3-тестировании на VPS обнаружилась гонка: `bot_update_config_field` делает `jq ... > tmp && mv tmp config.json`, и параллельный процесс мог прочитать `config.json` в промежутке, увидев пустоту → ошибка `no_secret`. v2.4.3 починил flock'ом.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 12. i18n (bash CLI)
|
## 12. i18n (bash CLI)
|
||||||
@@ -556,12 +590,14 @@ with socket.create_connection(("95.163.176.222", 443), timeout=5) as s:
|
|||||||
0) exit
|
0) exit
|
||||||
```
|
```
|
||||||
|
|
||||||
Диспатчер в `install.sh` принимает `--action=` для автоматизации из бота (будущая работа).
|
Диспатчер в `install.sh` (`bot_action_dispatch`) принимает `--action=` для автоматизации из бота. Полный контракт описан в разделе 11.1.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 17. Changelog
|
## 17. Changelog
|
||||||
|
|
||||||
|
- **2.4.3 (2026-04-10)** — iter3-фикс: `bot_action_dispatch` оборачивается во `flock -w 30` на `/var/lock/gotelegram-bot-action.lock`. Обнаружена гонка: параллельные `change-lite-domain` получали `"no secret in config"`, потому что один процесс читал `config.json`, пока другой делал `jq ... > tmp && mv`. `util-linux` (содержит `flock`) добавлен в `critical` deps, `check_deps_present` и маппинги `apt_pkg_for_cmd`/`dnf_pkg_for_cmd`.
|
||||||
|
- **2.4.2 (2026-04-10)** — реализация non-interactive `bot_action_*` в install.sh (change-template + change-lite-domain с JSON-ответом). bot.py подключает `run_bot_action()` и делает реальную работу вместо stub'ов. Критфиксы: (a) `safe_edit_message` принимает `disable_web_page_preview` (иначе TypeError в success-пути cb_pro_confirm); (b) чтение/запись `config['template_id']` вместо `config['template']` (save_gotelegram_config всегда писал `template_id`, бот смотрел не туда); (c) `bot_update_config_field` использует shell `date -Iseconds` вместо `jq now|todate` (jq 1.5 совместимость для Debian 10); (d) `asyncio.Lock _BOT_ACTION_LOCK` сериализует callback'и в процессе бота; (e) валидация `_TPL_ID_RE`/`_DOMAIN_RE` до subprocess. Полный аудит и автоустановка зависимостей: `ensure_deps` разделяет critical/optional, дедуплицирует пакеты, re-verify после install; `apt_pkg_for_cmd` и `dnf_pkg_for_cmd` мапят команды на пакеты (dig→dnsutils/bind-utils, xxd→xxd/vim-common, flock→util-linux). `check_deps_present` — быстрый чек без `apt-get update`.
|
||||||
- **2.4.1 (2026-04-10)** — баг #23: `start_telemt` делает `restart` если сервис активен (иначе stale in-memory config после переустановки Lite поверх Pro). Полная документация проекта — `DOCS_HUMAN.md` и `DOCS_AI.md` (этот файл).
|
- **2.4.1 (2026-04-10)** — баг #23: `start_telemt` делает `restart` если сервис активен (иначе stale in-memory config после переустановки Lite поверх Pro). Полная документация проекта — `DOCS_HUMAN.md` и `DOCS_AI.md` (этот файл).
|
||||||
- **2.4.0** — i18n EN/RU для CLI (328 ключей) и бота (99 ключей JSON с per-user persistence). Возможность загрузить свой шаблон сайта из произвольного git-репозитория (валидация URL, таймауты, лимит размера клона).
|
- **2.4.0** — i18n EN/RU для CLI (328 ключей) и бота (99 ключей JSON с per-user persistence). Возможность загрузить свой шаблон сайта из произвольного git-репозитория (валидация URL, таймауты, лимит размера клона).
|
||||||
- **2.3.x** — каталог шаблонов расширен до 1801, 4 источника, 18 категорий. Поддержка StartBootstrap `dist/` структуры.
|
- **2.3.x** — каталог шаблонов расширен до 1801, 4 источника, 18 категорий. Поддержка StartBootstrap `dist/` структуры.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# GoTelegram Pro — руководство пользователя
|
# GoTelegram Pro — руководство пользователя
|
||||||
|
|
||||||
**Версия:** 2.4.1
|
**Версия:** 2.4.3
|
||||||
**Репозиторий:** `anten-ka/gotelegram_pro`
|
**Репозиторий:** `anten-ka/gotelegram_pro`
|
||||||
**Для кого:** владельцы VPS, которым нужен надёжный MTProxy для Telegram с маскировкой под обычный HTTPS-сайт.
|
**Для кого:** владельцы VPS, которым нужен надёжный MTProxy для Telegram с маскировкой под обычный HTTPS-сайт.
|
||||||
|
|
||||||
@@ -214,6 +214,8 @@ A: Сам MTProxy — да, это публичная технология из
|
|||||||
|
|
||||||
## Changelog (коротко)
|
## Changelog (коротко)
|
||||||
|
|
||||||
|
- **2.4.3** — фикс гонки в `bot_action_dispatch`: параллельные вызовы `change-lite-domain`/`change-template` (например, два пользователя бота одновременно) могли получить ошибку «no secret in config», если один процесс читал `config.json` в момент, когда другой его перезаписывал через `jq`. Теперь диспетчер оборачивается в `flock(1)` с таймаутом 30 с; `util-linux` (содержит `flock`) добавлен в критические зависимости.
|
||||||
|
- **2.4.2** — смена шаблона и домена маскировки **прямо из Telegram-бота** без SSH. Раньше эти пункты меню показывали сообщение «сделай через CLI», теперь бот вызывает `install.sh --action=change-template --json` / `--action=change-lite-domain --json` и разбирает ответ. Плюс: безопасный `safe_edit_message` принимает `disable_web_page_preview`; поле статуса шаблона наконец-то отображается (раньше читалось не из того ключа JSON); полный аудит и автоустановка системных зависимостей при первом запуске (`curl jq openssl git xxd tar dig flock` + опциональные `qrencode bc`); `asyncio.Lock` в боте сериализует параллельные callback'и; валидация tpl\_id (`[A-Za-z0-9_-]{1,64}`) и домена до subprocess.
|
||||||
- **2.4.1** — фикс: `start_telemt` теперь делает `restart` если сервис уже запущен. Раньше переустановка Lite поверх Pro оставляла в памяти старый конфиг, и клиенты получали «Unknown TLS SNI drop». Плюс полная документация проекта (этот файл и `DOCS_AI.md`).
|
- **2.4.1** — фикс: `start_telemt` теперь делает `restart` если сервис уже запущен. Раньше переустановка Lite поверх Pro оставляла в памяти старый конфиг, и клиенты получали «Unknown TLS SNI drop». Плюс полная документация проекта (этот файл и `DOCS_AI.md`).
|
||||||
- **2.4.0** — i18n EN/RU для CLI (328 ключей) и бота (99 ключей JSON с per-user persistence). Возможность загрузить свой шаблон сайта из произвольного git-репо (с валидацией URL, таймаутами, лимитом размера клона).
|
- **2.4.0** — i18n EN/RU для CLI (328 ключей) и бота (99 ключей JSON с per-user persistence). Возможность загрузить свой шаблон сайта из произвольного git-репо (с валидацией URL, таймаутами, лимитом размера клона).
|
||||||
- **2.3.x** — каталог шаблонов расширен до 1801, 4 источника, 18 категорий. Поддержка StartBootstrap `dist/` структуры.
|
- **2.3.x** — каталог шаблонов расширен до 1801, 4 источника, 18 категорий. Поддержка StartBootstrap `dist/` структуры.
|
||||||
|
|||||||
Reference in New Issue
Block a user