無伺服器 - Telegram 回聲機器人



這是官方無伺服器專案列表中提供的另一個有趣的專案。我們基本上在 Telegram 上建立一個新機器人,然後使用 set_webhook 方法將其連線到我們的 Lambda 函式,並在 Lambda 函式中編寫程式碼,使機器人回顯它接收到的任何訊息。

先決條件

您需要在您的手機或電腦上安裝 Telegram 應用。下載選項可以在這裡找到 here。Telegram 是一款訊息應用,類似於 WhatsApp 或 Messenger。安裝應用程式後,您需要在應用程式中建立一個新的機器人。為此,點選“新訊息”圖示(右下角的圓形鉛筆圖示),搜尋 BotFather。點選已驗證的帳戶。

Telegram

一旦您開始與 BotFather 聊天,建立新機器人就非常簡單明瞭了。您傳送 \newbot 命令,輸入機器人的名稱和使用者名稱,然後您會獲得一個訪問令牌,需要記下它。

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

此外,請注意 webhookset_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 上開啟您的機器人並與其聊天。它將按預期回顯訊息。

Set WebHook

恭喜您建立了第一個 Telegram 機器人!

廣告