声明:本文是篇翻译文,翻译原文。翻译不是很好,如有阅读不顺畅的地方,请阅读原文。
介绍
telegram.ext
子模块是通过纯API的基础上实现的。它提供了简单的交互,并让程序员从一些工作中解脱出来,让你不必重复你自己(黑人问号??)
它包含了多个类,但是有两个最重要的是telegram.ext.Updater
和telegram.bot.Dospatcher
。
Updater
类持续从telegram接收新信息,以及转发给Dispatcher
类。如果你创建了一个Updater
目标,它将创建一个Dispatcher
给你,并且通过一个Queue
连接起来。你可以通过注册一个通过Dispatcher
注册不同类型的handlers,Dispatcher
将会使用注册过的handlers,对从Updater
接收的信息进行分类,以及分发给你定义的不同的响应程序(callback function)。
每个handler都是通过telegram.ext.Handler
类创建的实例。这个包提供几乎所有会用到的事件提供handler,但是如果你需要一些非常特殊的东西,你可以自己定义议程Handler
。
开始,你需要一个Token。如果你已经阅读了第一篇文章,你可以使用之前生成的token。要生成一个token,你必须和@BotFather交互,并且跟从一些简单步骤。
一步一步创建你的第一个机器人
现在,让我们开始吧!再说一次,如果你想跟随教程,请打开一个Python命令行。
第一步,你必须创建一个Updater
。将TOKEN
替换为你的机器人的token。
>>> from telegram.ext import Updater
>>> updater = Updater(token='TOKEN')
相关阅读文档:telegram.ext.Updarer
为了让你的Updater
更快的使用到Dispatcher
,你可以在本地输入:
>>> dispatcher = updater.dispatcher
现在是设置logging
模块的好时候,这会让你知道什么时候(为什么)程序没有和你预想的一样工作:
>>> import logging
>>> logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
注意:如果你想学习更多内容,请阅读Exception Handling
现在,你可以定义一个处理特定类型信息的函数:
>>> def start(bot, update):
... bot.sendMessage(chat_id=update.message.chat_id, text='I\'am a bot,please talk to me !')
相关阅读文档:sendMessage
我们的目标就是希望当机器人接收到包含/start
命令的telegram信息时,这个函数会被触发!为了完成这个目标,你可以使用一个CommandHandler
(Handler
类提供的其中一个),并且通过dispatcher注册:
>>> from telegram.ext import CommandHandler
>>> start_handler = CommandHandler('start',start)
>>> dispatcher.add_handler(start_handler)
相关阅读文档: telegram.ext.CommandHandler, telegram.ext.Dispatcher.add_handler
接下来,你所需要做的,就是运行这个机器人,运行:
>>> updater.start_polling()
相关阅读:telegram.ext.Updater.start_polling
尝试一下!和你的机器人聊天,假如没有问题,给你的机器人发送/start
命令后,机器人将会回复。
译者发话:每次定义一个函数都需要先定义一个
handler
,然后通过dispatcher.add_handler
注册,这一点都不Pythonic!这里译者将定义一个装饰器,省去重复工作!
# decorater:不用每定义一个函数都要用handler以及add_handler
def command(handler,cmd=None,**kw):
def decorater(func):
def wrapper(*args,**kw):
return func(*args,**kw)
if cmd==None:
func_hander=handler(func,**kw)
else:
func_hander=handler(cmd,func,**kw)
dispatcher.add_handler(func_hander)
return wrapper
return decorater
这个装饰器就不介绍了。不懂装饰器的可以google之,或者直接用吧!
使用方法:
# 命令:/start ,回复一句话
@command(CommandHandler,'start')
def start(bot, update):
bot.sendMessage(chat_id=update.message.chat_id, text="I'm a bot, please talk to me!")
其实很简单,就是定义每个callback函数时,先在前面加一个@command(handler,cmd)
,handler
就是像CommandHandler
这样的handler。cmd
就是给机器人定义的命令,比如/start
,cmd
就是start
,cmd
默认是None值。
但是现在我们的机器人只能回答/start
命令。让我们添加另外一个handler,让它接收常规消息并回复同一句话(复读机)吧!使用MessageHandler
,这个Handler
子类,可以回应所有的文字信息:
>>> @command(MessageHandler,Filters.text)
... def echo(bot,update):
... print update.message.chat_id
... #print dir(update.message)
... bot.sendMessage(chat_id=update.message.chat_id,text=update.message.text)
原文代码:
>>> def echo(bot, update):
... bot.sendMessage(chat_id=update.message.chat_id, text=update.message.text)
...
>>> from telegram.ext import MessageHandler, Filters
>>> echo_handler = MessageHandler(Filters.text, echo)
>>> dispatcher.add_handler(echo_handler)
下面的代码将直接使用装饰器,不再贴原代码!
相关阅读:telegram.ext.MessageHandler
从现在开始,你的机器人将会回复所有的非命令信息!
注意:每次当你向dispatcher
添加handlers的时候,他们会立刻生效!
注意:Filters
类包含一系列的函数来过滤接收到的文字、图片、状态等信息。其中任何一个返回True
的过滤器将会把信息传给MessageHandler
。如果你想要使用一个单一参数类型的telegram.Message
,你可以使用你自己的过滤函数。
让我们给你的机器人添加一个真正的功能吧。我们希望实现一个/caps
命令,它将接受一些信息作为参数,然后返回大写的信息。为了让事情更简单,你将接受到的参数(作为空格间隔的list
)传给下面的响应函数:
>>> # 命令:/caps args,接收一段英文,返回大写的同一段英文
... @command(CommandHandler,'caps',pass_args=True)
... def caps(bot,update,args):
... text_caps=' '.join(args).upper()
... bot.sendMessage(chat_id=update.message.chat_id,text=text_caps)
注意:观察一下CommandHandler
初始化时接受的pass_args=True
。如果你想要将命令参数传给回调函数,这个是必须的。所以的handler类都有类似的关键词参数。有一些关键词参数适用于所以的handlers,有一些则只适用于特定的handler类。如果你第一次使用新类型的handler,请查阅文档,看是否对你有用。
Bot API另外一个很酷的特性,就是inline mode。如果你希望给你的机器人添加inline功能,请先和 @BotFather发送/setinline
开通inline。使用客户端给你的机器人开通inline将会花费一些时间。使用telegram APP可能会加快速度(或者有时候,你只需要等待一会就开通好了)。
当你的机器人显然太吵的时候,让我们继续inline这个主题。你也许已经知道添加响应函数的过程了,但是还有一些新类型的函数将会用到,所以请注意:
>>> # inline query,不是太懂
... @command(InlineQueryHandler)
... def inline_caps(bot, update):
... query = update.inline_query.query
... if not query:
... return
... results = list()
... results.append(
... InlineQueryResultArticle(
... id=query.upper(),
... title='Caps',
... input_message_content=InputTextMessageContent(query.upper())
... )
... )
... bot.answerInlineQuery(update.inline_query.id, results)
相关阅读:telegram.ext.InlineQueryHandler, answerInlineQuery
还不错!你的机器人已经可以通过inline mode回应你的命令了!
译者话:其实这个inline mode就跟微信里面差不多,当你跟别人聊天时,写了
哈哈
但是还没有发送时,微信是不是会自动弹出一个贴切的表情?在telegram中,利用上面的命令,以及给你的机器人开通inline mode之后,跟你的机器人聊天时,@它,就能看到这个
QQ截图20170325131757.png
QQ截图20170325132014.png
但是具体的,译者还没有具体去研究,可能后续还需继续看一下。
有一些困惑的用户可能会给你的机器人发送它(机器人)不明白的命令,所以这个时候我们可以使用MessageHandler
结合command
过滤器,来回应那些没有被之前的handlers识别的命令:
>>> # 当收到一个未知命令时,回复一句话 | 必须放在最后
... @command(MessageHandler,Filters.command)
... def unknown(update,bot):
... bot.sendMessage(chat_id=update.message.chat_id,text="Sorry, I didn't understand that command.")
注意:这个handler必须在最后添加(add_handler)!如果你提前添加,它将会在CommandHandler
有机会回应命令之前被触发。一旦信息被掌控(handled),所有之后的handlers都会被忽略。
如果你已经玩了一圈了,可以使用下面的命令停止机器人:
>>> updater.stop()
注意:就像你之前看的一样,Updater
在不同的线程运行。在这篇教程里这是很好的,但是如果你在写脚本,你也许希望通过按Ctrl + C 或者给机器人发送一条命令来停止机器人。想要实现这种情况,可以使用updater.idle()
。它将阻止运行程序知道上面两件事其中一件发生,然后运行updater.stop()
,然后继续运行脚本。
下一步该阅读什么?
学习有关库异常以及最佳实践,请阅读Exception Handling.(下一步翻译)
如果想要学习更多特性,请查阅Extensions – JobQueue!
或者,如果你想通过我们的机器人实例获取灵感,请查看examples folder.
网友评论