반응형

이제 Slack App(Bot)에 질의하고 답을 받을 수 있도록 하겠습니다. 간단히 @태그로 Bot에 날짜와 요일을 요청하면 이벤트를 감지하여 답변을 하는 간단한 챗봇을 만들어 보도록 하겠습니다.


1. Event Subscriptions > subscribe to bot events 로 이동하여 [Add Bot User Event] 를 클릭합니다.

2. app_mention  권한을 추가합니다.

3. 이전 글에서 생성했던 flask_server.py 파일을 아래와 같이 수정합니다.

더보기
hello_there 함수는 Slack 과 통신이 잘 되는지 체크하여  event_handler를 호출합니다. 
event_handler에서는 even_type을 확인하여 질의에 대한 답을 Return 합니다.
import json
from datetime import datetime
from flask import Flask, request, make_response
from slack_sdk import WebClient

token = "<< Your token >>"
app = Flask(__name__)
client = WebClient(token)


def get_day_of_week():
    weekday_list = ['월요일', '화요일', '수요일', '목요일', '금요일', '토요일', '일요일']

    weekday = weekday_list[datetime.today().weekday()]
    date = datetime.today().strftime("%Y년 %m월 %d일")
    result = '{}({})'.format(date, weekday)
    return result

def get_time():
    return datetime.today().strftime("%H시 %M분 %S초")


def get_answer(text):
    trim_text = text.replace(" ", "")

    answer_dict = {
        '안녕': '안녕하세요. CheckMate입니다.',
        '요일': ':calendar: 오늘은 {}입니다'.format(get_day_of_week()),
        '시간': ':clock9: 현재 시간은 {}입니다.'.format(get_time()),
    }

    if trim_text == '' or None:
        return "알 수 없는 질의입니다. 답변을 드릴 수 없습니다."
    elif trim_text in answer_dict.keys():
        return answer_dict[trim_text]
    else:
        for key in answer_dict.keys():
            if key.find(trim_text) != -1:
                return "연관 단어 [" + key + "]에 대한 답변입니다.\n" + answer_dict[key]

        for key in answer_dict.keys():
            if answer_dict[key].find(text[1:]) != -1:
                return "질문과 가장 유사한 질문 [" + key + "]에 대한 답변이에요.\n"+ answer_dict[key]

    return text + "은(는) 없는 질문입니다."


def event_handler(event_type, slack_event):
    channel = slack_event["event"]["channel"]
    string_slack_event = str(slack_event)

    if string_slack_event.find("{'type': 'user', 'user_id': ") != -1:
        try:
            if event_type == 'app_mention':
                user_query = slack_event['event']['blocks'][0]['elements'][0]['elements'][1]['text']
                answer = get_answer(user_query)
                result = client.chat_postMessage(channel=channel,
                                                 text=answer)
            return make_response("ok", 200, )
        except IndexError:
            pass

    message = "[%s] cannot find event handler" % event_type

    return make_response(message, 200, {"X-Slack-No-Retry": 1})


@app.route('/', methods=['POST'])
def hello_there():
    slack_event = json.loads(request.data)
    if "challenge" in slack_event:
        return make_response(slack_event["challenge"], 200, {"content_type": "application/json"})

    if "event" in slack_event:
        event_type = slack_event["event"]["type"]
        return event_handler(event_type, slack_event)
    return make_response("There are no slack request events", 404, {"X-Slack-No-Retry": 1})


if __name__ == '__main__':
    app.run(debug=True, port=5002)
 4. flask_server.py 파일이 있는 경로 터미널에서 다음과 같이 실행합니다. 
export FLASK_APP=flask_server.py
flask run --port=5002

5. ngrok가 실행중이고 생성된 URL이 Slack api 에 등록되어 있다고 가정하겠습니다. 이해가 되지 않으시면 이전 글을 참고하시기 바랍니다. Slack에서 @챗봇으로 질문을 입력하시면 질문에 맞는 답을 합니다.

더보기

@태그가 없으면 질의에 대한 답을 하지 않습니다.

@태그를 붙여서 호출하는 것이 불편 할 수 있습니다. 그리고 Channel에 불필요한 내용과 알람도 추가되니 Slack App(Bot)과 1:1로 직접 대화하는 것이 좋습니다. event_handler 함수를 아래와 같이 추가합니다.

def event_handler(event_type, slack_event):
    channel = slack_event["event"]["channel"]
    string_slack_event = str(slack_event)

    print(string_slack_event)

    if string_slack_event.find("{'type': 'user', 'user_id': ") != -1:
        try:
            if event_type == 'app_mention':
                user_query = slack_event['event']['blocks'][0]['elements'][0]['elements'][1]['text']
                answer = get_answer(user_query)
                result = client.chat_postMessage(channel=channel,
                                                 text=answer)
            return make_response("ok", 200, )
        except IndexError:
            pass
    # Direct Call 추가
    elif string_slack_event.find("'channel_type': 'im'") != -1:
        try:
            if slack_event['event']['client_msg_id']:
                user_query = slack_event['event']['text']
                answer = get_answer(user_query)
                result = client.chat_postMessage(channel=channel,
                                                 text=answer)
                return make_response("ok", 200, )
        except IndexError:
            pass
        except KeyError:
            pass

    message = "[%s] cannot find event handler" % event_type

    return make_response(message, 200, {"X-Slack-No-Retry": 1})

권한은 message.im 과 message.mpim 을 추가 하시면 됩니다.

이제 Slack App 에서 DM으로 질의응답이 가능합니다.


다음에는 Slack App(Bot) 을 이용하여 좀 더 의미있는 질의응답이 가능하도록 하겠습니다.

Python으로 Slack App(Bot) 만들기 (4) - Slash Commands

반응형