- lib/common.sh: add apt_lock_wait + apt_install + apt_update helpers
* waits up to 300s for dpkg lock held by unattended-upgrades
* uses DPkg::Lock::Timeout=120 native flag
* captures stderr to show real error if install fails
- lib/website.sh: install_nginx/install_certbot use apt_install
(fixes "Could not get lock /var/lib/dpkg/lock-frontend" during Pro setup)
- install.sh: bot_install uses apt_install (removes duplicated lock logic)
- lib/common.sh: ensure_deps uses apt_update + apt_install
- bot_install: wait up to 300s for dpkg/apt lock (unattended-upgrades)
- use apt-get -o DPkg::Lock::Timeout=120 as extra safety
- detect python3 minor version and include python3.X-venv in package list
- stop silencing apt errors with 2>/dev/null — surface them to user
- python3-full is optional; fall back to core packages if unavailable
- venv fallback path also installs versioned package and retries
- templates_catalog.json: skip cp when source==dest (symlink install)
Iteration 3 discovered a race condition: parallel CLI invocations of
change-lite-domain occasionally produced 'no secret in config' because
one process read config.json while another was mid-rewrite (jq -> tmp -> mv).
asyncio.Lock in bot.py only protects bot->bot races; CLI-level races and
bot+CLI mixed races were still possible.
- install.sh: bot_action_dispatch wraps dispatch in flock(1) on
/var/lock/gotelegram-bot-action.lock, 30s timeout, EX_TEMPFAIL on timeout
- common.sh: flock added to critical deps; apt_pkg_for_cmd/dnf_pkg_for_cmd
map flock -> util-linux
- common.sh: check_deps_present includes flock
- version bumped to 2.4.3 (common.sh + bot.py)
- install.sh: new bot_action_dispatch entry point for --action=X --json CLI invocation from the bot/scripts
- install.sh: bot_action_change_template — reuses download_template + deploy_template_to_nginx, updates config.json template_id
- install.sh: bot_action_change_lite_domain — regenerates telemt TOML with new fake-TLS mask domain, restarts telemt
- bot.py: run_bot_action() subprocess wrapper parses JSON result
- bot.py: cb_pro_confirm now performs real change-template when already in pro mode (fresh install still routes to CLI)
- bot.py: cb_lite_domain now performs real change-lite-domain when already in lite mode
- version -> 2.4.2
Two user-reported bugs:
1. Promo spam: daily promo message from /start and the Promo menu
button stayed in chat forever. Now they auto-delete after 30s.
- new helper _delete_message_after()
- cmd_start schedules deletion of the daily promo
- cb_menu_promo sends promo as a SEPARATE ephemeral message
(instead of editing the main menu in place), so the menu stays
intact and only the promo self-destructs in 30s.
2. CRITICAL: 'install/change template from bot' was a stub that
silently corrupted /opt/gotelegram/config.json. cb_lite_domain
and cb_pro_confirm wrote a fake minimal config ({mode,template,
port,installed_at}) without secret/domain/mask_host, and showed
'[OK] installed!' — while never invoking install.sh, never
downloading the template, never touching nginx. Proxy link
generation then broke because secret was gone.
User symptom: 'устанавливал другой шаблон через бота и всё
повисло'.
Fix: both callbacks now refuse cleanly and route the user to the
CLI ('gotelegram' command → menu 1 → 1 or 7). Configuration is
NOT touched. Full non-interactive install/change from the bot is
left as future work.
Tested live on VPS:
- bot.py syntax OK (ast.parse on VPS)
- gotelegram-bot restarted, active
- corrupted config.json on VPS rebuilt from telemt TOML ground
truth (mode=lite, secret, port, mask_host=google.com)
Bug report: 'статистика не работает' — submenu_stats showed the
'stats module missing' fallback even though gotelegram-stats.service
was active. Root cause: bootstrap.sh FILES[] never included
lib/stats.sh, so on every (re)install the file was absent from
/opt/gotelegram/lib/ on disk. The running collector was sourcing it
from an in-memory bash process from a previous install, but
install.sh's `source stats.sh` at menu entry failed silently and
hit the 'stats_module_missing' branch.
Also: stats_collect silently skipped history writes if
stats_history.csv was deleted post-init (only stats_init created it
once). Now stats_collect auto-recreates the file with header.
- bootstrap.sh: add 'lib/stats.sh' to FILES[]
- lib/stats.sh: stats_collect auto-creates HISTORY_FILE if missing
Tested live on VPS: show_traffic_stats now outputs real counters
(23.1 MB proxy, 10 MB site, 394 KB/s peak).