要说聊天体验,微信还是远比不上 telegram,微信消息一多就卡,而且没法直接引用消息进行回复导致经常找不到上下文。telegram 则始终异常流畅,记录阅读位置,消息多的时候也不会觉得跟不上聊天节奏或卡 … 当然了,这一段都不是今天要写的这篇文章的重点,这篇文章主要还是要介绍一下如何开发 telegram 机器人,telegram 在去年中旬的时候开放了机器人的 API,可以设置 hook,使得所有消息都能被转发到你的服务上,然后作出自动化回复。
机器人可以被邀请入群做很多辅助工作,比如输入 “/google xxx” 就可以得到谷歌查询的结果等等,甚至还有人开发了 /fff 命令,用来烧死异性恋:joy:什么的,只要发送一条 “/fff install someone” 的消息到机器人所在的群聊当中即可。总之,利用 bot API 几乎无所不能,也十分有意思。
俺从几天前开始玩耍 telegram bot API,开发了一个属于自己的机器人, @XiaoaiBot ,可以回声、计算两个日期的间隔时间、以及帮用户在群里找出最近一个 @ 消息,应该说还是非常好玩的。
一开始得在 telegram 中添加一个“机器人之父”的账号,便是 @BotFather 这个账号,然后给它发送 /newbot 命令,逐步建立起一个机器人,包括头像、介绍,以及它可以支持的命令,另外,最重要的就是能够得到这个机器人的 token,通过这个 token 可以调用官方机器人 API 收发消息。
telegram bot API 的官方文档是: https://core.telegram.org/bots/api ,在这里可以看到,所有的接口都是基于 https://api.telegram.org/bot+你的token 这个 base url,比如你的 token 是 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11,那么你调用任何 API 都得基于 https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11/,后面再加上具体 API 名。
telegram 支持两种获得消息的方式,一种是开发中利用 getUpdates 接口主动去查询是否有新消息,另外一种就是推荐的 setWebhook,设置一个 https 的服务地址,完事之后,所有机器人收到的消息都会同时发往这个地址,并携带上 json 数据,使用 python 的时候,可以通过 flask 这个框架的 request.get_json(force=True) 来获取到 json 数据。
设置 hook 的示例 API url 如下:
https://api.telegram.org/bot你的token/setWebhook?url=https://xxx.com
GitHub 上有一个别人已经封装好了的 python-telegram-bot 库,可以帮助开发者更近轻松快速地使用官方 API: https://github.com/python-telegram-bot/python-telegram-bot
将它装载下来后,你可以通过以下代码进行初始化:
import telegram bot = telegram.Bot(token='你的token')
然后就可以通过这个 bot 对象发送各种消息了,更多使用内容可以参看其开源代码的 readme,或者官方文档: http://python-telegram-bot.readthedocs.org/en/latest/py-modindex.html
有了各种准备内容后,我们还需要 flask 框架来提供 http 服务响应,flask 我就不多说了,应该学过 python 的都会懂得使用这个框架。主要说一下我开发小爱 bot 的一些思路和代码。
我写了一个 launcher 和 handle_message 方法用来分发命令到具体到执行代码:
@app.route('/<token>', methods=['POST']) def launcher(token): if request.method == "POST": update = telegram.Update.de_json(request.get_json(force=True)) handle_message(update.message) return 'ok' def handle_message(message): text = message.text if '/echo' in text: echo(message) elif '/milestone' in text: milestone(message) elif '/help' in text: help(message) elif '/getmylastat' in text: get_my_last_at(message) elif '/pic' in text: pic(message) elif '/delpic' in text: delpic(message) if not '/' in text and '@' in text: save_at_message(message)
这个方法应该一目了然,不多说,主要作为分发命令消息到入口。
另外我还写了一个用来分离命令和附着文本的方法:
def parse_cmd_text(text): # Telegram understands UTF-8, so encode text for unicode compatibility text = text.encode('utf-8') cmd = None if '/' in text: try: index = text.index(' ') except ValueError as e: return (text, None) cmd = text[:index] text = text[index + 1:] if not cmd == None and '@' in cmd: cmd = cmd.replace(bot_name, '') return (cmd, text)
其中需要注意到是,有可能用户发送到命令是:/xxx@XiaoaiBot 123这样,就得把@XiaoaiBot 这个无用的内容去掉,我使用 replace 方法将机器人的名字替换为空字符,这样就相当于删掉这个内容了。另外,也可以使用 python 的 re 正则表达式来匹配得到同样的结果,不多说。
整个开发过程还是非常愉快和轻松的,我使用的是 leancloud 美国节点进行部署,其中需要注意的是,其美国节点不支持命令行部署,只能 git 部署,于是我不得不开源我的 token,开源代码是:
https://github.com/drakeet/DrakeetLoveBot
希望大家如果 fork 我的代码使用,不要使用我的 token,因为会造成我的服务有可能出现混乱,我也会伤心以后不敢再开源了之类的,而且,申请一个 token 是非常容易的,完全没必要使用我的,祝玩得开心,也欢迎来玩耍俺的机器人 @XiaoaiBot ,提供的功能如下: