【问题标题】:How to handle NewMessage only in Telethon conversation如何仅在 Telethon 对话中处理 NewMessage
【发布时间】:2020-10-06 02:07:22
【问题描述】:

我的机器人代码中有两个处理程序:

  1. my_conversation - 捕获“/start”消息并开始新的对话,等待来自用户的消息
  2. 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())

我的期望:

  1. 我发送'/start'
  2. 机器人开始对话并回复“我正在等待消息”
  3. 我发送“123”
  4. Bot 发送消息“对话:123”,因为对话已经开始。其他处理程序必须忽略消息,因为对话已经开始。

我得到了什么:

  1. 机器人发送消息“捕获数字:123”
  2. 机器人发送消息“对话:123”

所以 Bot 还在对话之外通过处理程序捕获了消息,这太出乎意料了。 我必须在脚本中进行哪些更改才能使其正常工作?

【问题讨论】:

    标签: python telethon


    【解决方案1】:

    我计划在库的未来版本中删除 conversation 方法,因为如您所见,由于很难将基于回调的事件方法与命令式对话方式混合在一起,因此很快就会遇到很大的限制.我建议您改用FSM-style conversation。您应该能够轻松地调整该答案的代码以“等待数字”:

    from enum import Enum, auto
    
    class State(Enum):
        WAIT_DIGITS = auto()
    
    conversation_state = {}
    
    @client.on(events.NewMessage)
    async def handler(event):
        who = event.sender_id
        state = conversation_state.get(who)
        
        if state is None:
            await event.respond('Please send digits!')
            conversation_state[who] = State.WAIT_DIGITS
    
        elif state == State.WAIT_DIGITS:
            if event.text.isdigit():
                digits = event.text
                await event.respond(f'Thanks for your digits! {digits}')
                del conversation_state[who]
            else:
                await event.respond('Please only send digits, not letters')
    

    您可以轻松地为此添加更多抽象(根据状态为其他函数构建自己的装饰器,或者只是将每个状态的代码分离到另一个函数,使用它们的返回值作为下一个状态等)。

    【讨论】:

    猜你喜欢
    • 2012-07-20
    • 1970-01-01
    • 1970-01-01
    • 2023-02-09
    • 2013-02-18
    • 2021-11-24
    • 1970-01-01
    • 2021-05-25
    • 2013-09-15
    相关资源
    最近更新 更多