feat(tg): forum-first adapter complete — handlers, bot.py, 46 tests pass
This commit is contained in:
parent
82dc840544
commit
24c61468d7
9 changed files with 675 additions and 0 deletions
75
adapter/telegram/handlers/start.py
Normal file
75
adapter/telegram/handlers/start.py
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import structlog
|
||||
from aiogram import Router
|
||||
from aiogram.exceptions import TelegramBadRequest
|
||||
from aiogram.filters import CommandStart
|
||||
from aiogram.types import Message
|
||||
|
||||
from adapter.telegram import db
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
router = Router(name="start")
|
||||
|
||||
|
||||
@router.message(CommandStart())
|
||||
async def cmd_start(message: Message) -> None:
|
||||
"""
|
||||
Bootstrap the user's forum.
|
||||
|
||||
First visit: create Чат #1, hide General topic.
|
||||
Returning visit: health-check all active topics, archive stale ones.
|
||||
"""
|
||||
user_id = message.from_user.id
|
||||
chat_id = message.chat.id
|
||||
|
||||
await _check_and_prune_stale_topics(message, user_id, chat_id)
|
||||
|
||||
active = db.get_active_chats(user_id)
|
||||
|
||||
if not active:
|
||||
try:
|
||||
topic = await message.bot.create_forum_topic(chat_id=chat_id, name="Чат #1")
|
||||
thread_id = topic.message_thread_id
|
||||
db.create_chat(user_id=user_id, thread_id=thread_id, chat_name="Чат #1")
|
||||
logger.info("start_created_first_topic", user_id=user_id, thread_id=thread_id)
|
||||
except TelegramBadRequest as e:
|
||||
logger.warning("start_create_topic_failed", error=str(e))
|
||||
await message.answer(
|
||||
"Не удалось создать топик. Убедись, что в @BotFather включён "
|
||||
"Threaded Mode для этого бота."
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
await message.bot.hide_general_forum_topic(chat_id=chat_id)
|
||||
except TelegramBadRequest:
|
||||
pass # Not critical
|
||||
|
||||
await message.answer(
|
||||
"Привет! Это твоё личное пространство с AI-агентом Lambda. "
|
||||
"Каждый топик — отдельный контекст. Напиши что-нибудь."
|
||||
)
|
||||
else:
|
||||
await message.answer(
|
||||
f"Снова привет! У тебя {len(active)} активных чатов. "
|
||||
"Напиши /new чтобы создать новый."
|
||||
)
|
||||
|
||||
|
||||
async def _check_and_prune_stale_topics(
|
||||
message: Message, user_id: int, chat_id: int
|
||||
) -> None:
|
||||
"""Send typing action to each active topic; archive any that no longer exist."""
|
||||
for chat in db.get_active_chats(user_id):
|
||||
thread_id = chat["thread_id"]
|
||||
try:
|
||||
await message.bot.send_chat_action(
|
||||
chat_id=chat_id,
|
||||
action="typing",
|
||||
message_thread_id=thread_id,
|
||||
)
|
||||
except TelegramBadRequest:
|
||||
db.archive_chat(user_id=user_id, thread_id=thread_id)
|
||||
logger.info("pruned_stale_topic", user_id=user_id, thread_id=thread_id)
|
||||
Loading…
Add table
Add a link
Reference in a new issue