글 작성자: 모두의 근삼이

이번 연휴에는 코로나로 인해 예약 가능 좌석이 줄어들어서 그런지 유난히 열차 예매가 힘들었다. 사실 모두 매진 되어버려서 구매를 할수가 없었는데, 이번 기회를 틈타서 그동안 만들어 보고 싶었는데 귀찮아서 못만들어 봤던 텔레그램 api를 이용한 코레일 KTX 예매 챗봇을 만들어 보았다.

아래는 만들면서 정리한 내용들이다.

telegram chatbot api 활용하기

텔레그램 챗봇 api를 활용하면 특정 체팅방에서 발생하는 여러 이벤트들을 지정한 서버로 전달하거나, 서버에서 특정 채팅방으로 챗봇이 이벤트를 수행하도록 지시를 내릴 수도 있다. 대화형 챗봇을 제작하기 위해서는 아래와 같은 과정을 수행해야한다.

API 서버에 SSL적용은 필수인데, 텔레그램 봇의 웹훅은 https 프로토콜을 사용하는 사이트에만 전달할 수 있기 때문이다.

  1. BotFather 를 이용해 새로운 봇 생성 및 토큰 발행받기

  2. 챗봇 동작 지시용 서버 준비하기

  3. 서버에 SSL 적용하기

  4. 봇에 웹훅 URL(생성한 서버) 설정하기

  5. 신나게 개발하기!

BotFather 를 이용해 새로운 봇 생성 및 토큰 발행받기

@BotFather 를 텔레그램에서 검색하여 아래의 순서로 대화를 시작하면 봇을 아주 쉽게 생성할 수 있다. 생성이 완료되면 생성된 봇의 토큰이 함께 전달되는데, 이 토큰이 이후 API개발에 아주 중요하게 사용되기 때문에 잘 보관해야 한다.

  1. /start

  2. /newbot

  3. 사용할 봇의 표기이름

  4. 사용할 봇의 username

아래에 빨간색으로 숨긴 부분이 토큰이 위치한 부분이다.

챗봇 동작 지시용 서버 준비하기 + SSL 적용하기

본인은 간단하게 구현하기 위해서 python flask를 활용해서 웹서버를 구축했다.

여기서 구축하는 서버는 이후에 챗봇이 참여한 체팅방에서 발생하는 여러 이벤트들을 웹훅을 통해 수신하게 될 서버이다. 서버는 반드시 SSL이 적용되어 있어야 하는데, 이유는 텔레그램에서 웹훅 수신용 서버로 SSL이 적용된 서버만 허용해 주기 때문이다.

웹훅용 URL로는 다른 임의의 트레픽이 접근하지 않을만한 특별한 path를 지정해 주는것이 안전하다.

  • 예시 : https://teleapi.geunsam2.com/nobodyusethispath-telebot-111222

  • 수신 메서드는 반드시 POST 방식으로 한다.

  • 참고로 웹훅 서버는 80, 88, 443, 8443 포트만을 지원한다.

구축에 대한 자세한 내용은 텔레그램 챗봇 생성 및 생성과는 별개의 내용이므로 이후 다른 포스팅에서 끄적여 보겠다.

💡

간단한 flask 예시가 필요하다면 본 게시물 하단의 테스트 부분을 참고바란다.

봇에 웹훅 URL 설정하기

생성한 봇과 서버가 서로 연결되기 위해서는 봇의 이벤트를 수신할 웹훅서버로, 우리가 생성한 서버를 별도로 지정해 주어야 한다.

텔레그램에서 제공하는 챗봇용 API중 하나인 setWebhook 을 사용할 것이다. 설정은 다음과 같이 api를 하나 호출해 주면 된다.

https://api.telegram.org/bot[봇토큰]/setWebhook?url=[웹훅서버도메인]
#[예시] https://api.telegram.org/botThisIs-Token-123123/setWebhook?url=https://example.com/path

GET 방식으로 쿼리파라미터만 전달해주면 되기 때문에 일반 웹브라우저에 위 형식으로 URL을 입력해 주는것 만으로 설정을 완료할 수 있다.

💡

예시 이미지에 사용된 프로그램은 postman이라는 api 테스트용 툴이다.

API 호출 결과가 아래와 같이 true로 출력되면 정상적으로 세팅이 된 것이다.

{ "ok": true, "result": true, "description": "Webhook was set" }

테스트

아래는 flask 서버를 활용해서 간단한 웹훅 서버를 구축한 예제이다.

아래의 코드대로 서버를 작성하여 기동시키고, SSL 적용, 웹훅설정까지 완료한다면 사용자가 입력한 체팅을 그대로 챗봇이 따라치는 간단한 기능을 확인할 수 있다. 아래 예제는 텔레그램 챗봇 API가 기본적으로 제공하는 sendMessage 를 활용한 기능이다.

from flask import Flask, request, jsonify, make_response
from flask_restful import marshal_with, Resource, reqparse, fields
from flask_restful import Api
import requests

application = Flask(__name__)
api = Api(application)

botToken = "봇 토큰" ##반드시 본인 챗봇의 토큰을 입력하시오

class Telebot(Resource):
    s = requests.session()
    sendUrl = "https://api.telegram.org/bot{}".format(botToken)

    #https://example.com/telebot 경로로 들어온 트레픽중 post메서드를 수신하는 부분
    def post(self):
        getText = request.json['message']['text'].strip() #사용자가 입력한 체팅
        chatId = request.json['message']['chat']['id'] #체팅방 id
        self.sendMessage(chatId, getText)

    #sendMessage API로 체팅방에 메시지 보내는 함수
    def sendMessage(self, chatId, getText):
            sendUrl = "{}/sendMessage".format(self.sendUrl)
            params = {
                "chat_id" : chatId,
                "text" : getText
            }
            self.s.get(sendUrl, params=params)
            return None

#https://example.com/telebot 경로로 들어오면 Telebot 클래스로 전달
api.add_resource(Telebot, '/telebot')

if __name__ == '__main__':    
    context = ('./certs/fullchain.pem', './certs/privkey.pem') ##반드시 본인 도메인의 인증서를...
    application.run(debug = True, host='0.0.0.0', port=8080, threaded=True, ssl_context=context)
  • 동작 확인

만약 그룹에 챗봇을 초대하여 사용하는 경우, 읽기 권한을 부여해야 사용자의 체팅을 서버로 전달한다.
(/ 로 시작하는 명령어로 인식할만한 문구들은 읽기 권한이 없어도 전달된다.) 간단하게 체팅방의 관리자로 봇을 등록하면 해결할 수 있다.

반응형