
无服务器 - Telegram 回声机器人
这是官方无服务器项目列表中提供的另一个有趣的项目。我们基本上在 Telegram 上创建一个新机器人,然后使用 set_webhook 方法将其连接到我们的 Lambda 函数,并在 Lambda 函数中编写代码,使机器人回显它接收到的任何消息。
先决条件
您需要在您的手机或电脑上安装 Telegram 应用。下载选项可以在这里找到 here。Telegram 是一款消息应用,类似于 WhatsApp 或 Messenger。安装应用程序后,您需要在应用程序中创建一个新的机器人。为此,点击“新消息”图标(右下角的圆形铅笔图标),搜索 BotFather。点击已验证的帐户。

一旦您开始与 BotFather 聊天,创建新机器人就非常简单明了了。您发送 \newbot 命令,输入机器人的名称和用户名,然后您会获得一个访问令牌,需要记下它。

代码演练
代码可以在 GitHub 上找到 - https://github.com/serverless/examples/tree/master/aws-python-telegram-bot
我们将看一下项目结构,然后执行 serverless.yml 文件和 handler.py 文件的演练。
项目结构
我们可以看到,此项目有一个外部依赖项(python telegram bot 库),在 requirements.py 中列出 -
python-telegram-bot==8.1.1
package.json 和 serverless.yml 都显示已使用 serverless-python-requirements 插件来捆绑 python 依赖项(在本例中为 telegram bot 库)。因此,README.md 文件还建议您执行 npm install 以安装必要的插件。我个人建议您删除 package.json,并使用 sls plugin install -n serverless-python-requirements 安装 serverless-python-requirements。这将自动创建 package.json 文件。这还将确保您安装最新版本的 serverless-python-requirements。通过运行 npm install,您将安装现有 package.json 中提到的版本,该版本可能已过时。
如果您阅读 README.md 文件,您会发现一个被引用的文件实际上并不存在于项目中 - serverless.env.yml。您需要创建此文件并在其中输入您的 TELEGRAM_TOKEN。这是出于安全原因考虑。TELEGRAM_TOKEN 应该保密,您不希望公开共享它。因此,此项目的创建者未在 GitHub 上添加 serverless.env.yml 文件。但是您需要在本地机器上创建它。
serverless.yml 演练
serverless.yml 文件以服务的定义开头。
service: serverless-telegram-bot
接下来,定义提供程序。在这里,再次设置了一个环境变量。此变量 (TELEGRAM_TOKEN) 的值从您应该在本地创建的 serverless.env.yml 文件中获取。在这里,我们再次使用 $ 来表示变量。
provider: name: aws runtime: python3.6 profile: ckl environment: TELEGRAM_TOKEN: ${file(./serverless.env.yml):TELEGRAM_TOKEN, ''}
functions 块非常简单。定义了两个函数,都是 HTTP 触发的。但是,http 事件参数在此处在一行中定义。
- http: path: /set_webhook method: post
而不是使用单行执行 - http - POST /set_webhook
此外,请注意 webhook 和 set_webhook 函数位于同一个处理程序文件中。
functions: webhook: handler: handler.webhook events: - http: POST / set_webhook: handler: handler.set_webhook events: - http: POST /set_webhook
最后,定义了 serverless-python-requirements 插件。
plugins: - serverless-python-requirements
handler.py 演练
我们从几个 import 语句开始
import json import telegram import os import logging
接下来,定义一个 logger 对象,它基本上帮助我们输入日志语句。请注意,这对于 python 运行时函数不是必需的。简单的 print 语句也会记录。
唯一的区别是 logger 的输出包括日志级别、时间戳和请求 ID。您可以在此处阅读有关 logging 库的更多信息 here。
# Logging is cool! logger = logging.getLogger() if logger.handlers: for handler in logger.handlers: logger.removeHandler(handler) logging.basicConfig(level=logging.INFO)
接下来,定义 OK_RESPONSE 和 ERROR_RESPONSE 的 JSON。这些用作函数的返回值。
OK_RESPONSE = { 'statusCode': 200, 'headers': {'Content-Type': 'application/json'}, 'body': json.dumps('ok') } ERROR_RESPONSE = { 'statusCode': 400, 'body': json.dumps('Oops, something went wrong!') }
接下来,定义一个由两个 API 函数使用的辅助函数。此函数使用在 serverless.yml 中作为环境变量提供的 Token 返回一个 bot 实例。
def configure_telegram(): """ Conimages the bot with a Telegram Token. Returns a bot instance. """ TELEGRAM_TOKEN = os.environ.get('TELEGRAM_TOKEN') if not TELEGRAM_TOKEN: logger.error('The TELEGRAM_TOKEN must be set') raise NotImplementedError return telegram.Bot(TELEGRAM_TOKEN)
接下来,定义两个 API 的处理程序函数。让我们首先看一下 set_webhook 函数。在这里,从我们之前看到的 configure_telegram 函数获取 bot 实例。接下来,从标头中提取 host 字段,从传入事件的 requestContext 块中提取 stage 字段。使用这些,构造两个字段,即 webhook 的 URL。最后,使用 bot.set_webhook(url) 函数将其应用于机器人。如果 webhook 设置正确,则设置 OK_RESPONSE,否则设置 ERROR_RESPONSE。请注意,此 set_webhook API 必须使用 POSTMAN 等工具手动触发一次。
def set_webhook(event, context): """ Sets the Telegram bot webhook. """ logger.info('Event: {}'.format(event)) bot = configure_telegram() url = 'https://{}/{}/'.format( event.get('headers').get('Host'), event.get('requestContext').get('stage'), ) webhook = bot.set_webhook(url) if webhook: return OK_RESPONSE return ERROR_RESPONSE
让我们了解 set_webhook 函数如何能够获取 webhook 的正确 URL。请注意,set_webhook 和 webhook 函数在其路径中仅存在 '/set_webhook' 的区别。它们共享相同的 host 和 stage。因此,我们可以使用在 set_webhook 函数的事件中接收到的 host 和 dev 推导出 webhook 函数的端点。如果您的端点是 'https://abcdefghijk.execute-api.us-east-1.amazonaws.com/dev',则 host 将为 'https://abcdefghijk.execute-api.us-east-1.amazonaws.com' 且 stage 将为 'dev'。set_webhook 函数由 'https://abcdefghijk.execute-api.us-east-1.amazonaws.com/dev/set_webhook' 触发,webhook 函数由 'https://abcdefghijk.execute-api.us-east-1.amazonaws.com/dev' 触发。因此,set_webhook 事件中的参数可以帮助我们构造 webhook 函数的端点 URL。
最后,让我们看一下 webhook 函数。它非常简单。它从 configure_telegram 辅助函数接收 bot 实例。然后检查事件。如果它是 POST 事件并且包含正文,则从正文中提取 chat ID 和消息。如果文本为 '/start',表示对话的开始,则使用 bot.sendMessage(chat_id=chat_id, text=text) 命令回复标准问候语。否则,它会回复它收到的相同文本。
def webhook(event, context): """ Runs the Telegram webhook. """ bot = configure_telegram() logger.info('Event: {}'.format(event)) if event.get('httpMethod') == 'POST' and event.get('body'): logger.info('Message received') update = telegram.Update.de_json(json.loads(event.get('body')), bot) chat_id = update.message.chat.id text = update.message.text if text == '/start': text = """Hello, human! I am an echo bot, built with Python and the Serverless Framework. You can take a look at my source code here: https://github.com/jonatasbaldin/serverless-telegram-bot. If you have any issues, please drop a tweet to my creator: https://twitter.com/jonatsbaldin. Happy botting!""" bot.sendMessage(chat_id=chat_id, text=text) logger.info('Message sent') return OK_RESPONSE return ERROR_RESPONSE
通过 POSTMAN 等工具触发 set_webhook 函数后,您可以在 Telegram 上打开您的机器人并与其聊天。它将按预期回显消息。

恭喜您创建了第一个 Telegram 机器人!