Slackのポスト(POST)について
ポスト はSlackの機能の一つで、通常よりも長文のメッセージや、書式付きのメッセージを投稿する場合に利用できます。投稿されたポストは複数人が共有して編集することも可能です。
あるプライベートチャンネルに多数のポストがあり、過去のものを一括ダウンロードしておきたいと思ったのですが、インポート & エクスポートの説明 を見ると、プライベートチャンネルからのエクスポートは「プラスデータエクスポート プラスプラン」が必要なようでした。
料金プランを見るとその価格は¥1,600(アクティブなユーザ1名あたり、年払いの場合の月額費用)。スタンダードの2倍弱となっており、このエクスポートのためだけにアップグレードするのはちょっと難しいので、APIを使用して一括ダウンロードするスクリプトを作ってみました。
処理の流れとスクリプト
API仕様を見たところ、プライベートチャンネルはAPIでは"group"となっており、以下の流れでポストの取得を実現できそうです。
- 投稿したメッセージ一覧の取得にチャンネルのID(group id)が必要なため、まず groups.list メソッドでチャンネル一覧を取得
- 一覧から、取得対象のグループをユーザが選択
- 選択したチャンネルに対して、投稿されたメッセージの履歴を groups.history メソッドで取得
- 各メッセージに対して、ポストがあればローカルファイルとしてダウンロード
- groups.history メソッドでは一度に最大1000件しか取得できないため、続きがある場合(レスポンスに "has_more": true があれば)、 3) と 4)を繰り返す
この中で、4) の「ポストがあれば」の判定ですが、ポストはSlack内部的には「テキスト形式の添付ファイル」で実装されており、mimetype が'text/plain'である添付ファイルを全て取得するようにしました。APIレスポンスからは普通の共有ファイル(テキスト形式のファイルを添付した場合)と区別ができないので、共有ファイルもダウンロードされるようになっています。
作成したスクリプトが以下になります。
# !/usr/bin/env python
# -*- coding: utf-8 -*-
from slackclient import SlackClient
import urllib2
import re
import datetime, time
# Slackのトークン
slack_token = '<ここにトークンを設定>'
# プライベートチャンネル(チャンネルID)のリストを取得
def getPrivateChannelIdList(slack_client):
result = []
group_list = slack_client.api_call(
'groups.list', # プライベートチャンネル取得APIは groups.list
exclude_archived=False, # レスポンスにアーカイブチャンネルを含めるか(含める場合にFalse)
exclude_members=True # レスポンスにユーザ一覧を含めるか(含める場合にFalse)
)
if group_list['ok'] == True: # 正常なレスポンス
groups = group_list['groups']
for i in range(len(groups)):
group_name = groups[i]['name']
print str(i) + ' : ' + group_name # グループ名を標準出力
result.append(groups[i]['id']) # グループIDをリストに追加
else:
print 'Error at groups.list API:',
print group_list
return result
# チャンネルに投稿されたメッセージを取得し、ポスト(テキスト形式の添付ファイル)があればファイル出力
def outputFilesFromChannel(slack_client, channel_id):
latest_time = 9999999999.999999 # 厳密には現在時刻だがこれでもOK
has_more = 1 # チャンネルに1000件を超える投稿があれば1000件ごとに繰り返す
while has_more == 1:
comment_list = slack_client.api_call(
'groups.history', # 投稿取得APIは groups.history
channel=channel_id,
latest=latest_time,
count=1000 # 1度に取得できる件数は最大1000件
)
if comment_list['ok'] == True:
for comment in comment_list['messages']: # 各投稿をチェック
latest_time = comment['ts']
if comment.has_key('subtype') and comment['subtype'] == 'file_share' and \
comment.has_key('file') and comment['file'].has_key('mimetype') and \
comment['file']['mimetype'] == 'text/plain':
# ファイル共有があり、かつそのmimetypeがテキスト形式の場合のみ、添付ファイルを出力
file_title = comment['file']['title']
file_timestamp = datetime.datetime.fromtimestamp(comment['file']['timestamp'])
out_file_name = file_timestamp.strftime('%Y-%m-%d_%H%M%S') + '_' + comment['file']['id'] + '.txt'
# ダウンロードはAPIが無いので、ヘッダにtoken設定してurllib2で取得
req = urllib2.Request(comment['file']['url_private_download'])
req.add_header('Authorization', 'Bearer ' + slack_token)
with open(out_file_name, 'wb') as myfile:
myfile.write(urllib2.urlopen(req).read())
print 'Output : ' + out_file_name + '(' + file_title + ')'
if comment_list['has_more'] == False: # 1000件以下なら終了
has_more = 0
else:
print 'Error at groups.history API:',
print comment_list
break
return
if __name__ == '__main__':
slack_client = SlackClient(slack_token)
private_channel_list = getPrivateChannelIdList(slack_client) # チャンネル一覧取得
if len(private_channel_list) > 0:
print 'Select channel num(0-' + str(len(private_channel_list)-1) + '):',
input = raw_input() # 標準入力から対象チャンネルを選択
channel_id = private_channel_list[int(input)]
outputFilesFromChannel(slack_client, channel_id) # 選択したチャンネルに対して、ファイル出力
else:
print 'private channel num is 0'
実行してみる
実行にはトークンが必要となるので、以下より取得します。未発行の場合は「Create token」で発行して下さい。
https://api.slack.com/custom-integrations/legacy-tokens
スクリプト10行目の <ここにトークンを設定> に設定し、スクリプトを実行します。slackclient がインストールされていない場合は先にインストールして下さい。
pip install slackclient
実行例:
$ python getFilesFromPrivateChannel.py
0 : team-general
1 : team-randam
2 : team-meeting
3 : test-a17
4 : test-a18
5 : test-a19
Select channel num(0-5): 1
Output : 2018-01-25_151642_F8ZCQA19V.txt(ポスト(POST))
Output : 2017-12-20_112936_F8GFXA4D9.txt(2017-12-21 - メモ)
Output : 2017-11-22_160327_F83BM9KEU.txt(2017-11-22 - メモ)
Output : 2017-10-25_143619_F7P27V5QE.txt(2017-10-26 - メモ)
$ cat 2018-01-25_151642_F8ZCQA19V.txt
{"version":100,"revision":139,"root":{"children":[{"type":"p","text":"・これが"},{"type":"p","text":"・ポスト"},
{"type":"p","text":"・POST"},{"type":"p","text":"・通常よりも"},{"type":"p","text":"・長めの"},{"type":"p","text"
:"・メッセージ"},{"type":"p","text":"・複数人で","formats":{"i":[0,5]}},{"type":"p","text":"・共有しての","formats
":{"i":[0,6]}},{"type":"p","text":"・編集も可能","formats":{"i":[0,6]}},{"type":"p","text":""}]}}
うまくダウンロードできたようです。ファイルはjson形式になっているので、必要に応じて整形して利用できます。