I have two handlers in my bot's code:
- my_conversation - catches '/start' message and starts new conversation, where wait message from user
- digits - catches messages by pattern - only digits
import asyncio
import logging
import re
from telethon import TelegramClient
from telethon.events import StopPropagation, NewMessage
me = TelegramClient('bot', 'API_ID_BOT', 'API_HASH_BOT').start(bot_token='BOT_TOKEN')
async def my_conversation(event):
async with me.conversation(event.sender_id) as conv:
await conv.send_message('I\'m waiting for message')
response = conv.get_response()
response = await response
await conv.send_message(f'conversation: {response.text}')
raise StopPropagation
async def digits(event):
await me.send_message(event.sender_id, f'catches digits: {event.text}')
raise StopPropagation
async def main():
me.add_event_handler(my_conversation, NewMessage(incoming=True, pattern=r'^\/start$'))
me.add_event_handler(digits, NewMessage(incoming=True, pattern=re.compile(r'[0-9]+')))
await me.run_until_disconnected()
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
What I expect:
- I send '/start'
- Bot start conversation and replyes "I'm waiting for message"
- I send "123"
- Bot send message "conversation: 123" because the conversation has started. Other handlers must ignore message because the conversation has started.
What I have got:
- Bot send message "catches digits: 123"
- Bot send message "conversation: 123"
So Bot also catched message by handler outside the conversation, so unexpected. What I must change in script to make it work properly?
I plan to remove the
conversation
method in future versions of the library because, as you can see, one runs into big limitations very quickly because mixing the callbacks-based approach of events with the imperative style of a conversation is difficult. I recommend you use a FSM-style conversation instead. You should be able to adapt that answer's code to "wait for digits" easily:You can easily add more abstractions to this (build your own decorators for other functions depending on the state, or just separate the code of each state to another function, using their return values as the next state, etc.).