Slack Bot
Slack Bot
Python과 Slack API를 사용하여, 특정 채널에 자동으로 글을 올리거나 댓글을 달아주는 슬랙봇을 만들어보겠습니다.
두 개의 과정으로 진행되는데,
첫 번째는 Slack API에 bot을 등록하는 것이고
두 번째는 등록된 bot을 Python으로 활용하는 것입니다.
Slack API에 bot을 등록하는 것
Slack API에 접속하여 Create An App
을 클릭합니다.
From scratch
를 클릭합니다.
앱 이름을 작성하고, 슬랙 작업 환경을 선택한 후에 Create App
을 클릭합니다.
Bots
를 클릭합니다.
왼쪽 상단에는 입력한 앱 이름이 나오는 것을 확인할 수 있습니다.
Review Scopes to Add
를 클릭하여 앱 관련 권한을 설정할 수 있습니다.
Install App to Workspace
버튼이 비활성화 되어있는데 적어도 하나의 권한(Scope)를 설정해야 활성화되는 것을 확인할 수 있습니다.
스크롤을 내리면 Scopes
를 설정하는 부분이 나타납니다. Bot Token Scopes
부분에 있는 Add an OAuth Scope
버튼을 클릭하여 관련 권한을 설정하면 됩니다.
Slack API Methods에 가면 다양한 메소드를 확인하실 수 있습니다.
예를 들어, conversations.history라는 메소드를 클릭한 사진을 가져왔습니다.
이 메소드를 호출할 때 필요한 권한들이나 1분 동안 몇 번정도 호출할 수 있는지, Arguments, 사용법 등이 자세하게 설명되어 있는 것을 알 수 있습니다. 이 메소드의 경우 Rate limits
가 Tier 3인데 클릭하면 자세한 정보가 나오고 50+ per minute
정도로 제한이 되는 것을 확인하실 수 있습니다.
이처럼 용도에 맞게 메소드를 선택하시고, 권한을 설정해주시면 될 것 같습니다.
권한을 설정하면 Install App to Workspace
버튼이 활성화되고, 클릭하여 허용
버튼을 누릅니다.
Bot User OAuth Token
이 나오고, 나중에 Slack API를 호출할 때 사용되니 잘 저장해둡니다.
그리고 Slack Bot 앱을 원하는 채널에 추가해주면 됩니다.
등록된 bot을 Python으로 활용하는 것
slack_sdk
라이브러리를 사용할 것이기 때문에 터미널에서 아래 명령어로 설치합니다.
pip install slack_sdk
__init__
에서 아까 저장했던 token id를 WebClient
파라미터로 넣어줍니다.
get_channel_id
메소드는 channel 이름을 파라미터로 넘겨주면 channel id를 리턴해주는 메소드입니다.
여기서 conversations_list
메소드를 사용하는데, types로 “public_channel”을 넘겨주면 public 채널만 검색이 가능하고,
“private_channel”을 넘겨주면 bot이 추가되어있는 private 채널만 검색이 가능합니다.
from slack_sdk import WebClient
class SlackAPI:
def __init__(self, token, channel_name):
self.client = WebClient(token)
self.channel_type = "public_channel" # or "private_channel"
self.channel_id = get_channel_id(channel_name)
def get_channel_id(self, channel_name):
result = self.client.conversations_list(types=[self.channel_type])
channels = result['channels']
channel = list(filter(lambda c: c["name"] == channel_name, channels))[0]
channel_id = channel["id"]
return channel_id
get_message_ts
메소드는 conversations_history
메소드를 사용하여 메시지의 timestamp(ts)와 text 내용을 파싱하여 리턴해주는 함수입니다.
파라미터 oldest
는 메시지 검색을 처음부터 하지말고 해당 시간부터 해달라고하는 파라미터입니다.
이 oldest
값을 계속 수정해주면 봇이 채널의 정보를 계속 가져올 때, 중복되지 않고 새로운 정보만 가져올 수 있도록 할 수 있습니다.
def get_message_ts(self, end_ts):
message_info = list()
result = self.client.conversations_history(channel=self.channel_id, oldest=end_ts)
messages = result['messages']
for message in messages:
message_ts = message["ts"]
message_text = message["text"]
message_info.append({"ts": message_ts, "text": message_text})
return message_info
post_thread_message
메소드는 chat_postMessage
메소드를 사용하여 원하는 채널, 원하는 스레드(메시지)에 댓글을 달아주는 함수입니다.
파라미터로 thread_ts
를 빼면, 원하는 채널에 스레드(메시지)를 남길 수 있습니다.
def post_thread_message(self, message_ts, text):
self.client.chat_postMessage(
channel=self.channel_id,
text=text,
thread_ts=message_ts
)
post_emoji
메소드는 reactions_add
메소드를 사용하여 원하는 채널, 원하는 스레드(메시지)에 이모지를 달아주는 함수입니다.
위의 post_thread_message
메소드와 같이 보통 여기서는 스레드(메시지)를 timestamp로 구분합니다.
여기서는 이모지 "smile"
을 사용하였는데, 직접 만든 이모지 뿐만 아니라 등록되어 있는 이모지의 이름을 적어주시면 됩니다.
def post_emoji(self, message_ts):
self.client.reactions_add(
channel=self.channel_id,
name="smile",
timestamp=message_ts
)
최종적으로 다 합친 코드입니다.
from slack_sdk import WebClient
class SlackAPI:
def __init__(self, token, channel_name):
self.client = WebClient(token)
self.channel_type = "public_channel" # or "private_channel"
self.channel_id = get_channel_id(channel_name)
def get_channel_id(self, channel_name):
result = self.client.conversations_list(types=[self.channel_type])
channels = result['channels']
channel = list(filter(lambda c: c["name"] == channel_name, channels))[0]
channel_id = channel["id"]
return channel_id
def get_message_ts(self, end_ts):
message_info = list()
result = self.client.conversations_history(channel=self.channel_id, oldest=end_ts)
messages = result['messages']
for message in messages:
message_ts = message["ts"]
message_text = message["text"]
message_info.append({"ts": message_ts, "text": message_text})
return message_info
def post_thread_message(self, message_ts, text):
self.client.chat_postMessage(
channel=self.channel_id,
text=text,
thread_ts=message_ts
)
def post_emoji(self, message_ts):
self.client.reactions_add(
channel=self.channel_id,
name="smile",
timestamp=message_ts
)
Reference
Subscribe to SOOFTWARE
Get the latest posts delivered right to your inbox