
無伺服器 - 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 機器人!