장고(Django) 이용해서 슬랙(Slack)에 출석체크 챗봇 만들기 [2]
- Study/서버
- 2020. 12. 6. 23:14
이전 글 - 2020/11/22 - [Study/서버] - 장고(Django) 이용해서 슬랙(Slack)에 출석체크 챗봇 만들기 [1]
들어가기 전에
지난 포스팅에서 슬랙 채널에서 메시지가 발생했을 때 Slack API를 통해서 장고 서버로 사용자 ID와 메시지가 들어오는 것을 확인했습니다.
이제 특정 메시지가 왔을 때 사용자를 구분하여 출석을 체크해주는 로직을 넣고, 다시 슬랙 채널로 메시지를 보내는 작업을 진행해볼 예정입니다. 출석체크 로직은 여러분이 재미있게 만드실 수 있습니다. 저는 간단히~ 출석 체크하면 점수가 1점이 오르고, 연속으로 출석을 할 경우 연속(combo)만큼 점수가 오르는 로직을 넣어보겠습니다. ㅎㅎ
일단 슬랙 채널로 메시지를 보내보자
python에서 slack으로 메시지를 보내는 방법은 간단합니다. slacker라는 패키지를 받으면 코드 몇줄로 슬랙으로 메시지를 전달할 수 있습니다. (오픈소스 만세)
slacker를 설치하고 나서 슬랙에서 넘어온 메시지를 처리하는 부분에 슬랙 채널로 응답하는 내용을 적어줍니다. 딱 3줄만 추가하면 됩니다.
# ~/slackbot/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from slacker import Slacker
# 봇 토큰 추가
bot_token = 'xoxb-'
# Create your views here.
class Attend(APIView):
def post(self, request):
"""
슬랙에서 채팅 이벤트가 있을 때 호출하는 API
:param request:
:return:
"""
# 요청이 어떻게 들어오나 찍어보기
print(request.body)
# body에서 challenge 필드만 빼오기
challenge = request.data.get('challenge')
user = request.data.get('event').get('user')
text = request.data.get('event').get('text')
print("사용자 :", user, "| 메시지 :", text)
# 토큰으로 slacker를 만들어줍니다.
slack = Slacker(bot_token)
# 요기가 메시지 보내는 부분
slack.chat.post_message('#일반', f'너가 쓴 메시지:{text}', as_user=True)
# 응답 데이터로 { challenge : challenge } 주기
return Response(status=200, data=dict(challenge=challenge))
Slacker를 import하고 bot_token값을 넣어줍니다. 여기서 bot_token은 여러분의 slack-bot에 대한 토큰이기 때문에 슬랙 API페이지에서 확인할 수 있습니다.
slack.chat.post_message에서는 보내는 채널과 메시지, 그리고 as_user 옵션을 넣었는데 이 옵션을 as_user=None으로 넣으면 봇 프로필 사진이 안 나옵니다. 한번 바꿔해 보세요 ㅎㅎ
이제 서버를 다시 기동시키고 슬랙에 메시지를 써봅시다.
오 바로 응답 오죠?
그런데,,,
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
봇이 자기가 쓴 메시지에 반응해서 응답을 보내줍니다.
혼자서 무한 루프,,,,
얼른 서버를 끕니다.
이 문제를 해결하기 위해 로그를 봅니다.
사용자가 입력한 메시지는 client_msg_id를 달고 옵니다. 근데 봇이 혼자 입력한 메시지는 bot_id를 달고 오네요. 그럼 event에 bot_id가 있고 없고로 봇인지 사람인지를 구분할 수 있겠죠!!?!?!?
아니면 사용자가 U01C9LJS1PF일경우 무시하도록 할 수 있습니다. 이 사용자 id 값이 아마 안 바뀔 거니까 이걸로 해볼게요~
# ~/slackbot/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from slacker import Slacker
# 봇 토큰 추가
bot_token = 'xoxb-'
# Create your views here.
class Attend(APIView):
def post(self, request):
"""
슬랙에서 채팅 이벤트가 있을 때 호출하는 API
:param request:
:return:
"""
# 요청이 어떻게 들어오나 찍어보기
print(request.body)
# body에서 challenge 필드만 빼오기
challenge = request.data.get('challenge')
user = request.data.get('event').get('user')
text = request.data.get('event').get('text')
print("사용자 :", user, "| 메시지 :", text)
if user == 'U01C9LJS1PF':
print("봇 메시지")
else:
# 토큰으로 slacker를 만들어줍니다.
slack = Slacker(bot_token)
# 요기가 메시지 보내는 부분
slack.chat.post_message('#일반', f'너가 쓴 메시지:{text}', as_user=None)
# 응답 데이터로 { challenge : challenge } 주기
return Response(status=200, data=dict(challenge=challenge))
중간에 if문으로 user가 봇이 아닐 경우에만 post_message로 메시지를 보내주게 만들었습니다. 다시 한번 슬랙에 메시지를 날려볼까요?
자 이제 사람과 봇을 구분할 수 있게 되었습니다~!!!!!
사용자별로 출석체크 하기
채널에서 "ㅊㅊ"이라는 단어를 쓰면 출석 count를 +1해 주도록 하겠습니다. 일단 출석한 데이터를 저장할 수 있는 모델을 만들어야겠죠? models.py에서 간단하게 사용자의 id와 count를 저장할 수 있는 모델을 만들어줍니다.
# ~/slackbot/models.py
from django.db import models
# Create your models here.
class Attention(models.Model):
user_id = models.CharField(max_length=20, unique=True)
attend_count = models.IntegerField(default=0)
class Meta:
db_table = 'attention'
verbose_name = '출석체크'
모델을 만들었으면 makemigrations -> migrate를 해주어야 합니다. (Django에 대해서 아신다고 생각하고 자세한 설명은 생략하겠습니다.)
만약 모델을 추가했는데도 makemigrations시 변경된 점을 찾을 수 없다고 나온다면, settings.py에 있는 INSTALLED_APP에 우리가 새로 만든 app인 slackbot을 추가해주었는지 확인합니다.
이제 DB까지 만들어졌습니다. 이제 사용자가 'ㅊㅊ'라고 입력했을 때 로직을 만들어 봅시다.
from rest_framework.views import APIView
from rest_framework.response import Response
from slacker import Slacker
from .models import Attention
# 봇 토큰 추가
bot_token = 'xoxb-'
# Create your views here.
class Attend(APIView):
def post(self, request):
"""
슬랙에서 채팅 이벤트가 있을 때 호출하는 API
:param request:
:return:
"""
# 요청이 어떻게 들어오나 찍어보기
# print(request.body)
# body에서 challenge 필드만 빼오기
challenge = request.data.get('challenge')
user = request.data.get('event').get('user')
text = request.data.get('event').get('text')
print("사용자 :", user, "| 메시지 :", text)
# 메시지가 봇인지 체크
if user == 'U01C9LJS1PF':
print("봇 메시지")
else:
# 토큰으로 slacker를 만들어줍니다.
slack = Slacker(bot_token)
# 요기가 메시지 보내는 부분
# slack.chat.post_message('#일반', f'너가 쓴 메시지:{text}', as_user=None)
# 출석체크 인지 확인
if text == 'ㅊㅊ':
attention = Attention.objects.filter(user_id=user).first()
if attention is None:
Attention.objects.create(user_id=user, attend_count=1)
else:
attention.attend_count = attention.attend_count + 1
attention.save()
slack.chat.post_message('#일반', f'출석체크!: {attention.attend_count}회', as_user=None)
# 응답 데이터로 { challenge : challenge } 주기
return Response(status=200, data=dict(challenge=challenge))
사용자의 메시지를 그대로 슬랙으로 보내주던 곳에 메시지가 'ㅊㅊ'이면 출석 횟수를 +1해 주는 코드를 추가했습니다.
1. Attention 모델에서 채팅을 입력한 사용자의 id를 검색
2. 사용자의 id가 있으면 attend_count를 1 증가
3. 없으면 attend_count=1로 해서 신규 생성 (최초 출첵인 경우)
이제 슬랙에서 ㅊㅊ를 입력해 봅시다.
정상적으로 출석체크가 작동하는 모습이군요.
추가적인 기능 넣기
출석체크 기능을 만들기는 했는데 뭔가 부족해 보이죠? ㅊㅊ을 입력할 때마다 횟수가 1회씩 올라가니,, ㅊㅊ을 막 입력하면 엄청 늘어날 겁니다. 이러면 출석체크가 아무 의미 없죠? 하루에 한 번씩만 체크가 되도록 조금 수정해봅시다.
어떻게 수정하면 될까요?
.
.
.
.
.
가장 마지막 출석체크 날짜를 기록하고, 오늘 출석체크를 했으면 패스, 오늘이 아니면 출석체크를 시켜주게 만들면 됩니다!! 물론 다른 방법도 있겠지만~~~ 저는 이걸로!
날짜를 기록하기 위해 models.py에서 datetime필드를 하나 추가해줍니다.
# ~/slackbot/models.py
from django.db import models
from django.utils import timezone
# Create your models here.
class Attention(models.Model):
user_id = models.CharField(max_length=20, unique=True)
attend_count = models.IntegerField(default=0)
last_attend = models.DateTimeField(default=timezone.now())
class Meta:
db_table = 'attention'
verbose_name = '출석체크'
default에 timezone.now()를 넣어놓으면 create 할 때 자동으로 오늘 날짜를 넣습니다. (입력을 안 할 경우)
테이블을 까 보면 위처럼 날짜가 저장되는 걸 볼 수 있습니다.
이제 ㅊㅊ을 할 때, last_attend가 오늘인지 체크해서 오늘이면 이미 출석체크를 한 것이니 PASS, 아니면 count +1을 해주면 됩니다.
# ~/slackbot/views.py
...
# 출석체크 인지 확인
if text == 'ㅊㅊ':
attention = Attention.objects.filter(user_id=user).first()
if attention is None:
Attention.objects.create(user_id=user, attend_count=1)
else:
# 마지막 로그인 날짜가 오늘인지 체크
if attention.last_attend.date() == timezone.now().date():
slack.chat.post_message('#일반', f'오늘은 이미 출석체크를 했습니다.', as_user=None)
else:
attention.attend_count = attention.attend_count + 1
attention.save()
slack.chat.post_message('#일반', f'출석체크!: {attention.attend_count}회', as_user=None)
...
자 이제 여러분의 아이디어를 더해서 추가적인 기능들을 넣으면 됩니다.
저는 연속적으로 출석체크를 할 경우 combo시스템을 넣어서 점수를 더 높게 주도록 구현했고, ㅊㅊ말고도 ㅊㅋ(체크)를 입력할 경우 전체 사용자의 점수를 출력하게 만들었습니다.
마치며
슬랙 API를 이용해서 간단하게 출석체크 챗봇을 만들었는데요, 요즘 슬랙으로 업무를 하는 팀이 많이 늘어서 출석체크처럼 재미를 위한 챗봇 말고도 업무의 효율성을 높여주는 챗봇을 만들면 좋을 것 같습니다. 가령 특정 데이터를 뽑아준다던지, 문서를 쉽게 찾아서 다운로드할 수 있다던지 무궁무진할 것 같네요.
슬랙으로 출석체크 챗봇을 만드는 건 이것으로 마치겠습니다.
'Study > 서버' 카테고리의 다른 글
데이터그립(datagrip)에서 알티베이스(altibase)연동하기. datagrip for altibase (0) | 2021.06.28 |
---|---|
insomnia로 만든거 postman에 import 하기, insomnia to postman (0) | 2021.06.25 |
장고(Django) 이용해서 슬랙(Slack)에 출석체크 챗봇 만들기 [1] (0) | 2020.11.22 |
graphene에서 GraphQL-SDL 출력하기, postman graphql 자동완성 (0) | 2020.08.23 |
Django에서 GraphQL 사용해보기 (1) | 2020.07.26 |