Message handler routers for user and operator interactions
The bot uses Aiogram’s Router system to organize message handlers. There are two main routers: one for user messages (private chats) and one for operator messages (forum topics).
User sends: /start → Bot logs message → Bot creates/finds topic in operator group → Bot copies /start to topic → Bot replies: "Hello! How can I help you?"
Handles messages sent by operators in forum topics, copying them to the corresponding user.Filters:
F.is_topic_message.is_(True): Only messages in forum topics
Ignores bot messages
Behavior:
Finds the user ID associated with the topic
Builds reply parameters if the operator is replying to a previous message
Copies the operator’s message to the user’s private chat
Logs the message and creates bidirectional link
Handles errors if the user blocked the bot
Example flow:
Operator replies in topic: "Your order will arrive tomorrow" → Bot finds user_id from topic_id → Bot copies message to user's private chat → Bot logs message link for reply threading → User receives: "Your order will arrive tomorrow"
reply_params = Noneif message.reply_to_message is not None: target_message_id = await db.find_linked_message_id( source_chat_id=message.chat.id, source_message_id=message.reply_to_message.message_id, target_chat_id=user_id, ) if target_message_id is not None: reply_params = ReplyParameters( message_id=target_message_id, allow_sending_without_reply=True, )
Error Handling:
try: copy_result = await bot.copy_message( chat_id=user_id, from_chat_id=message.chat.id, message_id=message.message_id, reply_parameters=reply_params, )except TelegramForbiddenError: await message.reply( "The user has blocked the bot or has not opened the chat with the bot." ) return
Message Logging:
async with db.transaction(): # Log operator message in operator group await db.log_message_link( user_id=user_id, source_chat_id=message.chat.id, source_message_id=message.message_id, target_chat_id=user_id, target_message_id=int(copied_message_id), commit=False, ) # Log user's copy of the message await db.log_message_link( user_id=user_id, source_chat_id=user_id, source_message_id=int(copied_message_id), target_chat_id=message.chat.id, target_message_id=message.message_id, commit=False, )if log_messages: await db.log_message( user_id=user_id, direction="operator", chat_id=message.chat.id, message_id=message.message_id, content_type=message.content_type, text=message.text, caption=message.caption, file_id=extract_file_id(message), payload_json=safe_payload_json(message), )
1. User sends message in private chat2. user.py handler catches it3. Handler logs to database4. Handler calls topics.copy_user_message_to_topic()5. Message appears in operator's forum topic
Operator → User:
1. Operator replies in forum topic2. operator.py handler catches it3. Handler looks up user_id from topic_id4. Handler copies message to user's chat5. Handler logs bidirectional link6. User receives message