美文网首页Telegram 傳教士Python 运维
Python开发Telegram机器人(3)-- 年轻人的第一个

Python开发Telegram机器人(3)-- 年轻人的第一个

作者: 125b4e5d5f65 | 来源:发表于2017-03-25 13:37 被阅读2185次

声明:本文是篇翻译文,翻译原文。翻译不是很好,如有阅读不顺畅的地方,请阅读原文。

介绍

telegram.ext子模块是通过纯API的基础上实现的。它提供了简单的交互,并让程序员从一些工作中解脱出来,让你不必重复你自己(黑人问号??)
它包含了多个类,但是有两个最重要的是telegram.ext.Updatertelegram.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信息时,这个函数会被触发!为了完成这个目标,你可以使用一个CommandHandlerHandler类提供的其中一个),并且通过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就是给机器人定义的命令,比如/startcmd就是startcmd默认是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.pngQQ截图20170325131757.png
QQ截图20170325132014.pngQQ截图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.

相关文章

网友评论

  • 金十字:python安装的包名是什么?telegram吗?

本文标题:Python开发Telegram机器人(3)-- 年轻人的第一个

本文链接:https://www.haomeiwen.com/subject/iemqottx.html