猿问

如何仅在 Telethon 对话中处理 NewMessage

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

  1. my_conversation - 捕获“/start”消息并开始新对话,其中等待来自用户的消息

  2. 数字 - 按模式捕获消息 - 仅数字

    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. 机器人发送消息“对话:123”,因为对话已开始。其他处理程序必须忽略消息,因为对话已经开始。

我有什么:

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

  2. 机器人发送消息“对话:123”

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



临摹微笑
浏览 129回答 1
1回答

慕标5832272

我计划conversation在该库的未来版本中删除该方法,因为正如您所看到的,很快就会遇到很大的限制,因为将基于回调的事件方法与命令式对话风格混合起来很困难。我建议您改用FSM 风格的对话。您应该能够轻松地调整该答案的代码以“等待数字”:from enum import Enum, autoclass 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')您可以轻松地为此添加更多抽象(根据状态为其他函数构建自己的装饰器,或者只是将每个状态的代码分离到另一个函数,使用它们的返回值作为下一个状态等)。
随时随地看视频慕课网APP

相关分类

Python
我要回答