Slack API の公式 Python クライアント はよくできていると思うのだけど、諸事情あってこれを使わずに Python から Slack API を利用する必要があり、自前で超簡易的に Slack クライアントを書いてみた。
import urllib.request
import json
class SlackAPI:
def __init__(self, token: str, api_base: str = 'https://slack.com/api/'):
self.token = token
self.api_base = api_base
def __call__(self, name: str, charset: str = 'utf-8', **kwargs) -> dict:
req = urllib.request.Request(
url = self.api_base + name,
data = json.dumps(kwargs).encode(charset),
headers = {
'Authorization': f'Bearer {self.token}',
'Content-Type': f'application/json; charset={charset}',
})
with urllib.request.urlopen(req) as res:
return json.load(res)
def __getitem__(self, key: str):
return lambda **kwargs: self(key, **kwargs)
こんなノリで使える。
token = 'xoxb-000000000000-0000000000000-xxxxxxxxxxxxxxxxxxxxxxxx'
slack_api = SlackAPI(token)
# ユーザ一覧を取得する
slack_api['users.list']()
# メッセージを投稿する
slack_api['chat.postMessage'](channel='XXXXXXXXX', text='Yo!', as_user=True)
もちろん RTM API などは使えないが、Web API であればほとんどこれで実行できるのではないか。(そこまでいろいろ試したわけではないので「この API は実行できない」などあればコメントして欲しい)
追記 (2020.05.18)
コメントにて、JSON のリクエストボディに対応していない API もあるとご指摘いただいたので、これに対応してみた。
import urllib.request
import json
class SlackAPI:
def __init__(self, token: str, api_base: str = 'https://slack.com/api/'):
self.token = token
self.api_base = api_base
def __getitem__(self, key: str):
return lambda **kwargs: self.post(key, **kwargs)
def get(self, name: str, **kwargs) -> dict:
req = urllib.request.Request(
url = self.api_base + name + '?' + urllib.parse.urlencode(kwargs),
headers = {
'Authorization': f'Bearer {self.token}',
})
with urllib.request.urlopen(req) as res:
return json.load(res)
def post(self, name: str, charset: str = 'utf-8', **kwargs) -> dict:
req = urllib.request.Request(
url = self.api_base + name,
data = json.dumps(kwargs).encode(charset),
headers = {
'Authorization': f'Bearer {self.token}',
'Content-Type': f'application/json; charset={charset}',
})
with urllib.request.urlopen(req) as res:
return json.load(res)
明示的に get
メソッドを使った場合は application/x-www-form-urlencoded
でデータを送信する。
slack_api.get('conversations.list', limit=20)