stage-12: Telegram bot adapter

- New src/adapters/telegram_bot.py: full Telegram adapter with python-telegram-bot v22
  - Commands: /start, /help, /clear, /status, /model, /register
  - Inline keyboards for model selection
  - Message routing through existing router.py
  - Private chat: admin-only access
  - Group chat: responds to @mentions and replies to bot
  - Security logging for unauthorized access attempts
  - Message splitting for 4096 char limit
- Updated main.py: runs Discord + Telegram bots concurrently
  - Telegram is optional (gracefully skipped if no telegram_token)
- Updated requirements.txt: added python-telegram-bot>=21.0
- Updated config.json: added telegram_channels section
- Updated cli.py doctor: telegram token check (optional)
- 37 new tests (410 total, zero failures)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
MoltBot Service
2026-02-13 20:55:04 +00:00
parent d1bb67abc1
commit 2d8e56d44c
6 changed files with 849 additions and 6 deletions

View File

@@ -108,6 +108,16 @@ def main():
"Heartbeat registered (every %d min)", interval_min
)
# Telegram bot (optional — only if telegram_token exists)
telegram_token = get_secret("telegram_token")
telegram_app = None
if telegram_token:
from src.adapters.telegram_bot import create_telegram_bot
telegram_app = create_telegram_bot(config, telegram_token)
logger.info("Telegram bot configured")
else:
logger.info("No telegram_token — Telegram bot disabled")
# PID file
PID_FILE.write_text(str(os.getpid()))
@@ -122,8 +132,27 @@ def main():
signal.signal(signal.SIGTERM, handle_signal)
signal.signal(signal.SIGINT, handle_signal)
async def _run_all():
"""Run Discord + Telegram bots concurrently."""
tasks = [asyncio.create_task(client.start(token))]
if telegram_app:
async def _run_telegram():
await telegram_app.initialize()
await telegram_app.start()
await telegram_app.updater.start_polling()
logger.info("Telegram bot started polling")
try:
while True:
await asyncio.sleep(3600)
except asyncio.CancelledError:
await telegram_app.updater.stop()
await telegram_app.stop()
await telegram_app.shutdown()
tasks.append(asyncio.create_task(_run_telegram()))
await asyncio.gather(*tasks)
try:
loop.run_until_complete(client.start(token))
loop.run_until_complete(_run_all())
except KeyboardInterrupt:
loop.run_until_complete(scheduler.stop())
loop.run_until_complete(client.close())