https://cholol.tistory.com/503

 

장고(Django) 이용해서 슬랙(Slack)에 출석체크 챗봇 만들기 [1]

다음 글 - 2020/12/06 - [분류 전체보기] - 장고(Django) 이용해서 슬랙(Slack)에 출석체크 챗봇 만들기 [2] 대기업은 잘 안 쓰기는 하는데 중소기업이나 스타트업, 심지어 요즘 대학교 과제모임에서도 슬

cholol.tistory.com

Django를 이용하여 챗봇을 구성하는데 위의 페이지를 참고하였습니다. 문제가 된다면 알려주세요.

슬랙api에서 구독 설정을 하면, 슬랙api에서는 채팅창에 메시지가 올라올 때마다 그 데이터를 지정된 서버로 전송해줍니다. 받은 서버에서는 이 신호를 받아 받은 메세지를 처리하게 되고, 여기서는 Django 서버가 그 역할을 하게 됩니다. 슬랙 api 에서 보낸 데이터를 Django 서버에서 받아 적절한 반응(여기서는 날씨 정보를 답장해주는 것)을 하게 구성할 예정입니다.

Django 프로젝트 만들기

Django 패키지를 설치해주고, 프로젝트를 하나 생성해줍니다.

>> pip install django
>> django-admin startproject chatbot

그러면 메인 폴더 아래에 manage.py 파일이 있고, chatbot 폴더에 settings.py 를 비롯한 파일들이 생성됩니다. 먼저 settings.py 에서 수정해줄 내용이 있습니다.

먼저 이전에 기상청 api와 슬랙 api의 토큰을 숨긴 것과 같이 django 의 secret key를 secrets.json 파일로 숨겨주었습니다.

SECRET_KEY = "django-..." 대신에 아래와 같이 작성해주었습니다.

# chatbot/settings.py

import os, json
from django.core.exceptions import ImproperlyConfigured

path = os.path.dirname(os.path.abspath(__file__))
secret_file = os.path.join(BASE_DIR, "secrets.json")

with open(secret_file) as f:
    secrets = json.loads(f.read())


def get_secret(setting, secrets=secrets):
    try:
        return secrets[setting]
    except KeyError:
        error_msg = "Set the {0} environment variable".format(setting)
        raise ImproperlyConfigured(error_msg)


SECRET_KEY = get_secret("SECRET_KEY")

그리고 ALLOWED_HOST 항목을 수정해줍니다.

# chatbot/settings.py

ALLOWED_HOSTS = ["0.0.0.0"]

서버를 작동시킬 때, ip가 0.0.0.0 으로 지정되어 있어야 외부에서 접속이 가능합니다.

테스트 삼아 django 서버를 작동시켜 봅니다.

>> python manage.py runserver 0.0.0.0:8520

기본은 8000번 포트를 사용하지만 저는 해당 포트를 쓰는데가 있어 임의로 수정했습니다. 만약 바꾸신다면 이 포트를 기억해두시면 됩니다. ip를 클릭하여 실행하면 익숙한 로켓 화면이 반겨줍니다.

외부에서 접속하기 위해서는 iptime 등의 공유기에서 기본으로 제공하는 DDNS 기능 및 포트포워드 기능을 이용하거나, 외부에서 네트워크를 인식할 수 있는 공인ip 등을 이용해야 합니다. 자세한 내용은 패스하도록 하겠습니다. 공유기를 사용할 경우 포트포워드 작업을 해야하는데, 이때 위에서 정한 8520포트를 열어주면 됩니다.

그리고 외부에서 접속하기 위해서는 해당 DDNS 혹은 ip를 settings.py 의 ALLOWED_HOST 목록에 추가해주는것도 중요합니다. 브라우저에서 ***.iptime.org:8520 으로 접속했을 때, 아까와 동일한 로켓 화면이 뜬다면 외부에서 접속이 성공적으로 이루어진 것입니다.

슬랙 api 에서 채팅창 구독하기

https://api.slack.com/

 

Slack은 미래의 업무가 이루어지는 곳입니다

Slack은 여러분의 팀과 소통할 새로운 방법입니다. 이메일보다 빠르고, 더 조직적이며, 훨씬 안전합니다.

slack.com

slack api 에 방문하여 오른쪽 위 YourApps 에서 이전에 만들었던 bot을 선택해줍니다. 왼쪽 화면에 Event Subscriptions 메뉴로 들어가줍니다. 이 설정 페이지에서 채팅창에 새로운 글이 올라올 때, 지정된 서버로 그 정보를 전송해주게 됩니다.

Enable Events 탭을 On으로 바꾸고, 아까 외부 접속 시 사용했던 ***.iptime.org:8520 형태의 도메인을 입력해줍니다.

그럼 무언가 challenge 가 실패했다고 뜨며, 정상적으로 진행되지 않습니다. 정상입니다. 현재 입력한 주소가 내 서버가 맞는지 테스트하는 신호를 보내고, 그에 맞는 응답을 보내와야 내 서버가 맞다고 verified 되는 것입니다.

Django 콘솔을 보면 슬랙api에서 try를 클릭할 때마다 서버에 무언가 계속 요청이 들어오는 것을 확인하실 수 있습니다.

구독 데이터 처리하기

이 신호를 처리해주기 위해 Django 서버를 수정해주겠습니다.

>> pip install djangorestframework
>> python manage.py startapp slackbot

데이터 처리에 django REST framework를 이용하므로 이를 설치해주고, 데이터를 처리해주기 위한 slackbot 앱을 하나 만들어줍니다. 이 두가지를 settings.py의 INSTALLED_APP 항목에 추가해줍니다.

상세 API는 slackbot 앱의 views.py에서 구현하게 됩니다.

# slackbot/views.py

from rest_framework.views import APIView
from rest_framework.response import Response


class Attend(APIView):
    def post(self, request):
        """
        슬랙에서 채팅 이벤트가 있을 때 호출하는 API
        """

        # 신호 출력
        print(request.body)

        return Response(status=200)
# chatbot/urls.py

from django.contrib import admin
from django.urls import path
from slackbot import views  # 방금 작성한 slackbot 앱의 views를 불러와주고,

urlpatterns = [
    path("admin/", admin.site.urls),
    path("attend", views.Attend.as_view()),  # attend 경로를 추가해줍니다.
]

request URL 창에 있는 주소에 /attend 를 붙여주는 것을 잊지마시고 수정 후 try를 눌러봅니다. 최종 도메인은 http://***.iptime.org:8520/attend 와 같은 모습입니다.

try 버튼을 눌러보면 console에 무언가 출력되게 됩니다. token과 challenge와 type의 정보를 가진 데이터인데, 슬랙 api를 보니 서버에서 이 challenge 를 돌려받아야된다고 합니다. 받은 challenge를 돌려줄 수 있도록 다음과 같이 내용을 수정합니다.

# slackbot/views.py

from rest_framework.views import APIView
from rest_framework.response import Response


class Attend(APIView):
    def post(self, request):
        """
        슬랙에서 채팅 이벤트가 있을 때 호출하는 API
        """

        # 신호 출력
        print(request.body)

        # challenge 데이터 추출하여 Response에 추가
        challenge = request.data.get('challenge')
        return Response(status=200, data=dict(challenge=challenge))

그리고나면 슬랙api에서 URL 인증이 성공하게 되고, 아래에 (Subscribe to events on be half of users) 항목에서 message.channels 권한을 추가, 설정을 저장하면 구독이 완료된 것입니다.

수신된 메세지 데이터 처리하기

구독이 완료된 상태에서 워크스페이스로 접속하여 채팅창에 글을 쓰게되면 django 서버에서 이 데이터를 받게 됩니다. 콘솔에 이 데이터가 출력되게 되며, 이중에서 메시지의 중요한 내용은 'event' 항목 안의 'user' 와 'text'입니다. 데이터를 가공하여 이 두가지 항목만 콘솔에 표기되도록 수정해보겠습니다.

# slackbot/views.py

from rest_framework.views import APIView
from rest_framework.response import Response


class Attend(APIView):
    def post(self, request):
        """
        슬랙에서 채팅 이벤트가 있을 때 호출하는 API
        """

        # 신호 출력
        # print(request.body)

        user = request.data.get("event").get("user")
        text = request.data.get("event").get("text")
        print(user, text)

        # challenge 데이터 추출하여 Response에 추가
        challenge = request.data.get("challenge")
        return Response(status=200, data=dict(challenge=challenge))

다시 메시지를 보내보면 콘솔에는 무언가 알수없는 토큰 같은 것과 메세지의 내용이 표시되게 됩니다. 이 user 항목은 슬랙에서 흔히 볼 수 있는 아이디는 아니고, 내부적으로 저장되는 고유의 값입니다. 아이디는 아직 알 수 없지만, 새로 추가되는 메세지를 Django 서버에서 받기에 성공하였습니다.

정리

슬랙api에서는 채팅창에 메세지가 올라올 때, 이 메세지의 데이터를 구독 신청했고, 이 데이터는 컴퓨터에서 로컬로 돌아가고 있는 Django 서버로 보내지게 됩니다. 현재 이 보내진 데이터를 정리하여 메시지를 보낸 사람과 그 내용을 구분하여 출력하는데까지 진행하였습니다.

제 챗봇의 첫번째 기능은 메신저에 "수원 날씨" 와 같은 채팅이 올라오면 이를 인식하여, 앞서 구현했던 날씨 정보 획득 기능과 슬랙 메시지 기능을 이용하여 weather라는 이름의 채널에 보내는 것입니다. 이러한 기능 구현을 하기 위해 다음과 같이 진행 예정입니다.

  1. 메세지에서 날씨 정보 요청을 받게 된다면, 해당하는 주소를 앞서 만들었던 코드를 이용해 x, y 그리드화 하고, 다시 이 정보를 이용하여 해당 지역의 앞으로 6시간 동안의 날씨 정보를 획득하게 됩니다.
  2. 이 날씨 정보를 다시 채팅창에 메세지로 보내주면 1차적인 구현이 완료되게 됩니다.

내용 관련하여 도움이나 조언 언제든 환영합니다!

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기