如何为Telegram Bot异步函数编写消息拆分装饰器?
为Telegram Bot异步命令函数实现消息拆分装饰器
需求说明
我正在调整一个Telegram Bot,它有多个执行特定操作的异步函数。由于用处理器和命令调用机器人,每个函数都需要拆分用户消息(至少拆分第一个单词)。想写一个装饰器函数来完成这项工作,避免在主函数中重复编写拆分代码。
比如发送/wiki stackoverflow时,需要拆分出/wiki,把stackoverflow作为参数用于后续操作,希望通过装饰器自动完成消息拆分。
原函数示例:
async def wiki(update: Update, context: ContextTypes.DEFAULT_TYPE): text_input = str(update.message.text.split(' ', 1)[1]) wiki_text = wikipedia.page(f'{text_input}') await context.bot.send_message(chat_id=update.effective_chat.id, text=wiki_text.summary)
装饰器实现
可以编写一个支持异步函数的装饰器,自动拆分消息并将提取后的内容存入context的自定义属性中,方便后续使用:
import functools from telegram import Update from telegram.ext import ContextTypes def split_message(func): @functools.wraps(func) async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE): # 拆分消息:按空格分割一次,分离命令与参数 if update.message and update.message.text: parts = update.message.text.split(' ', 1) context.args_text = parts[1].strip() if len(parts) > 1 else "" else: context.args_text = "" # 调用原函数 return await func(update, context) return wrapper
使用装饰器修改原函数
给目标函数加上装饰器后,直接通过context.args_text获取拆分后的参数,无需重复编写拆分代码:
@split_message async def wiki(update: Update, context: ContextTypes.DEFAULT_TYPE): text_input = context.args_text if not text_input: await context.bot.send_message(chat_id=update.effective_chat.id, text="请输入要查询的关键词") return try: wiki_text = wikipedia.page(text_input) await context.bot.send_message(chat_id=update.effective_chat.id, text=wiki_text.summary) except wikipedia.exceptions.PageError: await context.bot.send_message(chat_id=update.effective_chat.id, text="未找到相关页面")
扩展说明
- 装饰器中通过
functools.wraps(func)保留原函数的名称、文档字符串等元信息,方便调试和维护 - 内置了无参数场景的处理,避免出现索引越界错误
- 也可以调整装饰器逻辑,直接将拆分后的参数作为额外参数传入原函数,但需要同步修改原函数的签名
内容的提问来源于stack exchange,提问作者anaconda1337
相关产品推荐
相关产品推荐

