삽질/개발,엔지니어링

python으로 Slack Bot 만들기

maengis 2023. 5. 10. 18:29
  1. 특정 채널에 특정 단어가 포함된 메시지를 감지
  2. 2에서 감지한 메시지에 특정 리액션이나 스레드에 댓글로 특정 메시지를 남기면 확인
  3. 2에서 특정 메시지를 남겨서 확인 처리 됐으나, 수정 해서 특정 메시지가 없어지거나 메시지 자체를 삭제를 하면 확인 취소

슬랙 앱 설정을 아래처럼 해줌.

 

Settings > Socket Mode

Enable Socket Mode을 켜야 함.

 

Features > Event Subscriptions

필요한 이벤트 추가 (요구 사항에 대한 이해가 부족해서 일단 필요하다 싶은 거 다 넣어버림.)

 

slack-sdk랑 slack-bolt가 필요함.

pip3 install slack-sdk slack-bolt

 

슬랙 앱 토큰이랑 봇 토큰이 필요.

봇 토큰은 xoxb로 시작하고, 앱 토큰은 xapp로 시작함.

 

import random
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler

SLACK_APP_TOKEN = 'xapp-앱토큰'
SLACK_BOT_TOKEN = 'xoxb-봇토큰'

app = App(token=SLACK_BOT_TOKEN)

event_ts = {}

check_ts = {}

channels = [
    '채널1_ID', # 메시지 줍줍할 채널1
    '채널2_ID' # 메시지 줍줍할 채널2
]

@app.event("message")
def handle_message_events(body, say):
    event = body['event']

    if event['channel'] in channels:
        # 특정 앱이 보낸 메시지만 반응 
        if 'bot_id' in event and event['bot_id'] == '특정앱의_봇ID':
            """
            특정 문구가 포함되어 있으면 반응 '메시지반응'
            event_ts에 채널과 ts를 넣어서 체크 되어야 하는 메시지를 넣음.
            실제 체크시에는 특정 시간 이후에도 체크 안 된 걸 확인해야 하니까 별도 저장 필요(DB든 Redis든)
            """
            if '메시지반응' in event['text']:
                rand_num = random.randrange(1, 100)
                say(f"{event['channel']} {event['ts']} : {rand_num}")
                event_ts[f"{event['channel']}_{event['ts']}"] = rand_num

        # 위에 특정 문구로 저장해놓은 거에 리플로 '확인완료'이 달리면 완료 처리
        if 'thread_ts' in event:
            ts_key = f"{event['channel']}_{event['thread_ts']}"
            if ts_key in event_ts and ts_key not in check_ts and event['text'].replace(' ', '') == '확인완료':
                say(f"{event_ts[ts_key]} 완료 체크(리플) - {event['user']}")
                check_ts[ts_key] = True

        # 리플에 메시지 수정, 삭제 이벤트 감지
        if 'subtype' in event and 'thread_ts' in event['previous_message']:
            ts_key = f"{event['channel']}_{event['previous_message']['thread_ts']}"

            # 체크 대상 문구의 리플 수정, 삭제인지 확인
            if ts_key in event_ts:
                prev_msg = event['previous_message']['text'].replace(' ', '')

                """
                수정 전 메시지는 '확인완료'인데, 수정 후에 '확인완료'가 사라졌으면 해제
                삭제한 메시지가 '확인확료'면 해제
                """
                if (event['subtype'] == 'message_changed' \
                    and prev_msg == '확인완료' \
                    and event['message']['text'].replace(' ', '') != '확인완료') \
                    or (event['subtype'] == 'message_deleted' \
                        and prev_msg == '확인완료'):

                        user = event['previous_message']['user'] if event['subtype'] == 'message_deleted' else event['message']['user']

                        if ts_key in check_ts:
                            say(f"{event_ts[ts_key]} 완료 해제(리플) - {user}")
                            del check_ts[ts_key]

@app.event("reaction_added")
def handle_reaction_added_events(body, say):
    event = body['event']

    if event['item']['channel'] in channels:
        if event['reaction'] == 'white_check_mark':
            ts_key = f"{event['item']['channel']}_{event['item']['ts']}"
            if ts_key in event_ts and ts_key not in check_ts:
                say(f"{event_ts[ts_key]} 완료 체크(액션) - {event['user']}")
                check_ts[ts_key] = True

@app.event("reaction_removed")
def handle_reaction_removed_events(body, say):
    event = body['event']

    if event['item']['channel'] in channels:
        if event['reaction'] == 'white_check_mark':
            ts_key = f"{event['item']['channel']}_{event['item']['ts']}"
            if ts_key in event_ts and ts_key in check_ts:
                say(f"{event_ts[ts_key]} 완료 해제(액션) - {event['user']}")
                del check_ts[ts_key]

if __name__ == "__main__":
    SocketModeHandler(app, SLACK_APP_TOKEN).start()

 

위 코드를 저장 후 파이썬으로 실행하고 테스트 하면 됨.

python3 confirm_bot.py

 

 

반응형