如何仅在 Telethon 对话中处理 NewMessage
How to handle NewMessage only in Telethon conversation
我的机器人代码中有两个处理程序:
- my_conversation - 捕获“/start”消息并开始新对话,等待来自用户的消息
- 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())
我的期望:
- 我发送'/start'
- 机器人开始对话并回复“我正在等待消息”
- 我发“123”
- Bot 发送消息“对话:123”,因为对话已经开始。其他处理程序必须忽略消息,因为对话已经开始。
我得到的:
- Bot 发送消息“捕获数字:123”
- Bot 发送消息“对话:123”
所以 Bot 也在对话之外通过处理程序捕获了消息,太出乎意料了。
我必须在脚本中更改什么才能使其正常工作?
我计划在库的未来版本中删除 conversation
方法,因为如您所见,由于将事件的 callbacks-based 方法与命令式混合在一起,很快就会遇到很大的限制谈话风格很难。我建议您改用 。您应该能够轻松调整该答案的代码以“等待数字”:
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')
您可以轻松地为此添加更多抽象(根据状态为其他函数构建自己的装饰器,或者只是将每个状态的代码分离到另一个函数,使用它们的 return 值作为下一个状态等)。
我的机器人代码中有两个处理程序:
- my_conversation - 捕获“/start”消息并开始新对话,等待来自用户的消息
- 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())
我的期望:
- 我发送'/start'
- 机器人开始对话并回复“我正在等待消息”
- 我发“123”
- Bot 发送消息“对话:123”,因为对话已经开始。其他处理程序必须忽略消息,因为对话已经开始。
我得到的:
- Bot 发送消息“捕获数字:123”
- Bot 发送消息“对话:123”
所以 Bot 也在对话之外通过处理程序捕获了消息,太出乎意料了。 我必须在脚本中更改什么才能使其正常工作?
我计划在库的未来版本中删除 conversation
方法,因为如您所见,由于将事件的 callbacks-based 方法与命令式混合在一起,很快就会遇到很大的限制谈话风格很难。我建议您改用
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')
您可以轻松地为此添加更多抽象(根据状态为其他函数构建自己的装饰器,或者只是将每个状态的代码分离到另一个函数,使用它们的 return 值作为下一个状态等)。