본문 바로가기

일::개발

Python으로 Azure에 Serverless Telegram bot 만들기(4)

azure - flask 연결에 이어 이번에는 아주 간단한 telegram bot 을 만들어본다.

 

python-telegram-bot 패키지를 사용하기로 하고, 일단 설치한다.

 

> pip install python-telegram-bot

 

이것은 로컬에 패키지를 설치하는 과정이고, azure function 에 deploy 될 때도 해당 패키지가 설치되어 동작하게 하려면 requirements.txt 에도 추가해줘야 한다.

 

<requirements.txt>

# DO NOT include azure-functions-worker in this file
# The Python Worker is managed by Azure Functions platform
# Manually managing azure-functions-worker may cause unexpected issues

azure-functions
python-telegram-bot
Flask[async]

 

bot.py 파일에 아래 내용을 추가해준다.

 

<bot.py>

from . import app, logging

import telegram
from flask import Flask, request

TOKEN = 'YOUR TELEGRAM TOKEN'
APPNAME = 'YOUR AZURE FUNCTION APP NAME'

bot = telegram.Bot(TOKEN)

@app.route('/')
def home():
	return 'Hello, World!'

@app.route('/setWebhook')
async def setWebhook():
    url = 'https://{}.azurewebsites.net/botHook'.format(APPNAME)
    botWebhookResult = await bot.set_webhook(url=url)
    return str(botWebhookResult) + url

@app.route('/botHook', methods=['POST'])
async def botHook():
    update = telegram.Update.de_json(request.json, bot)
    await bot.sendMessage(chat_id=update.message.chat_id, text=update.message.text)
    return 'OK'

 

telegram에서 메시지를 받는 방법은 두 가지가 있는데, 하나는 getUpdates 를 사용해서 그 동안 수신된 메시지를 Update 객체로 받아오는 방법이고, 다른 하나는 setWebhook 을 사용해서 메시지가 수신될 때 호출되는 콜백을 등록하는 것이다.

 

첫번째 방법을 사용하면 polling 하면서 계속 수신된 메시지가 없는지 확인해야 하고, 두번째 방법을 사용하면 메시지가 수신될 때만 서버가 호출에 응답하면 된다.

 

첫번째 방법을 구현하기 위해서는 

python-telegram-bot 패키지에서 telegram.ext.ApplicationBuilder 를 이용해서 application을 생성하고,

application.run_polling() 해서 주기적으로 폴링한다. 

이렇게 하면 간단하고 예시 코드도 많지만, serverless 로 구현하기에는 적당하지 않다.

 

Azure functions 에서 돌아가게 하려면 두번째 방법 - 웹훅을 등록하는 방법 - 을 이용하는 것이 좋겠다.

 

코드를 보면 telegram app token 을 이용해서 Bot 객체를 만들고, setWebhook, botHook 두 개의 async 함수를 추가한 것이 전부다.

 

setWebhook() 에서는 Bot.set_webhook() 를 이용해서 메시지가 도착했을 때 호출할 콜백 URL을 등록해주고,

botHook() 는 호출되는 콜백 URL이 echo 로 동작하도록 구현한 것이다.

 

두 함수 모두 async 함수 (set_webhook, sendMessage) 를 호출해야 하기 때문에 flask 설치할 때 async 를 추가해줘야 한다. 

(맥 zsh에서 설치할 때 문제는 https://uaremine.tistory.com/72 참조)

 

이렇게 해주고, https://APPNAME.azurewebsites.net/setWebhook 을 한번 브라우저에서 호출해주면 https://APPNAME.azurewebsites.net/botHook 이 콜백 URL로 등록되고, 그 이후부터는 텔레그램 봇이 메시지를 받을 때마다 botHook() 이 실행된다.

 

 

webhook을 이용하는 방법은 polling 하는 방법에 비해 serverless 환경에 적용하기는 적합하지만, 로컬에서 테스트하기 어려운 단점이 있다. (개발 PC가 퍼블릭 IP를 가지고 있다면 문제 없겠지만)

 

polling 방식으로 로컬에서 개발하고 webhook 으로 변경해서 deploy 하는 효과적인 방법은 다음에 다뤄보겠다.