Help us understand the problem. What is going on with this article?

Slack APIでチャンネルのメッセージを取り出してみる

Webの初心者です。さらに?Qiita初投稿です。
Slack APIを使ってチャンネル内のメッセージ(会話)を取り出す、というのをやってみたので、そのときの手順を書きます。ほかの初心者の方の参考になれば幸いです。

まずはテスト用のワークスペースを作成。convhist(conversation history)という名前をつけました。
image.png

このワークスペース内にapitestというチャンネルを作成。このチャンネルのメッセージ(会話)をSlack APIで取り出すことを目標とします。

  1. Slack Appの作成(API受付準備)
  2. 使用するAPI

1. Slack Appの作成(API受付準備)

"App"とあるのでWebサーバー上にアプリを作るのかと思ったのですが、アプリというよりはむしろワークスペースに参加できる架空のユーザーを作成する感じです。普通のユーザー(人)がSlack画面から操作するのに対し、AppはAPI経由でアクセスする、というイメージです。

APIを使うには、Appの作成 → トークン取得 → APIに必要なスコープの設定、となります。

Appの作成

Appは以下のWebサイトから作成します。Appの作成手順はいくつかのサイトで詳しく書かれているので割愛します。
https://api.slack.com/
このページで、Your Apps > Create New App で、[Create a Slack App] ダイアログがでてきます。
[Create a Slack App]ダイアログにてAppNameを決めます。
App Name: GetConvHist (なんでもいい)
Develpment Slack Workspace: convhist (上記のワークスペース名)

このAppに対する情報設定画面が表示されます。ここでトークン取得およびスコープ設定が必要になります。最低でも一つのスコープを設定(追加)しないとトークンが得られないようです。

ユーザーのトークンとボットのトークン

Appがワークスペースにアクセスするとき、あるときはボットとして、またあるときは自分(App作成者)の代行として振る舞うことができます。どちらで振る舞うかは、APIを実行するときにつかうトークンによって区別されます。

APIに必要なスコープ

Appには、許される操作の範囲を設定する必要があります。許される操作の範囲は"スコープ"と呼ばれるものでカテゴライズされています。ボットとして振る舞うとき、自分(App作成者)の代行として振る舞うときそれぞれに対し、あらかじめ(APIを実行する前に)スコープが設定されている必要があります。

左側のメニューリスト > OAuth & Permissions を選択。
今回は自分(App作成者)の代行として振る舞うことにして、User Token Scopes にスコープを追加します。チャンネルのメッセージを取得するのが目的なので、conversation list と conversation history(後述します) に必要な以下のスコープを追加します。
channels:history
channels:read
image.png

追加したら、その画面の一番上のほうにあるOAuth Tokens & Redirect URLs で、[Install App to Workspace]ボタンを押します。Appがワークスペースにアクセスする権限を[許可]します。すると、OAuth Access Token が得られます。このトークンはAPIを投げるときに使います。ちなみにスコープ設定変更のたびにAppの再インストールが必要です。再インストールといってもこのページ上の画面の操作で済むようになっており、下の添付画面ではボタンが[Reinstall App]になっています。再インストールしてもトークン文字列自体は変わりません。
image.png

もしAppをボットとして振る舞わせたいのなら、Bot Token Scopesにのほうにスコープを追加し、Bot User OAuth Access Token を取得し、APIを投げるときにはそちらのトークンを使います。

これで、ワークスペースがAppからのAPIを受け付けるようになります。

2. 使用するAPIメソッド

Slackの提供する大量のAPIメソッドから、目的のものを探します。チャンネルの情報を取得したいので、channels.???でしょうか? channels.historyというメソッドがあったので、ここからスタートです。まずはAPIメソッドのドキュメントを見ると、channels.historyはすでに非推奨になっており、conversations.historyを使え、とあります。
conversations.historyのページを見ると、メソッドの仕様や必要なスコープが記載されています。
image.png
ユーザートークンでconverstion.historyを使うには、channels:history, groups:hisotry, im:history, mpim:historyが必要となっています。実際には全部必要なわけではなく、操作対象に対応するもの、例えばpublicのチャンネルにアクセスするにはchannels:historyだけでよいようです。
conversations.historyの引数の説明を見てみると、tokenとchannelの2つがRequiredになっています。
image.png

APIメソッドドキュメントのページにはTesterというタブがあり、ありがたいことにお試し実行できるようになっています。いまはapitestというチャンネルの情報を取りたいので、試しに、tokenには上記のOAuth Access Tokenを入力、channelに#apitestと入力して実行してみました。
image.png
送信文字列とレスポンスが見れるようになっています。・・・channel_not_found。失敗しているようです。
image.png

改めて引数を確認すると、channel には Conversation ID なるものを使うことになっています。Conversation IDが何なのかを正当な?手段で調べてはいませんが、conversations.createやconversations.list のレスポンスにid という値があり、これを指すものと思われます。

conversations.listのページのTesterで実行し、そのレスポンスを見ると、apitestというチャンネルに"CTEE1LMQT"というidが割り当てられています。

"ok": true,
"channels": [
    {
        "id": "CTEE1LMQT",
        "name": "apitest",
        "is_channel": true,

conversations.historyのページに戻りTesterでこのidを使って実行すると、今度は成功です。

実際にメッセージを取れるのか確認です。Slackの普通の操作画面で、チャンネルapitestに「helloあいう」というメッセージを送信。この状態でconversations.historyを実行すると、以下のようなレスポンスになっています。最新のメッセージがレスポンスの先頭になるようです。

"ok": true,
"messages": [
    {
        "client_msg_id": "edc34a1f-6e19-47fe-864d-af762c939934",
        "type": "message",
        "text": "hello\u3042\u3044\u3046",
        "user": "UTRUE3W13",
        "ts": "1581446370.000500",

tsはunixtimeのtimestampのようです。メッセージの初回の送信の時刻が維持され、編集しても変わりません。さきほどの「helloあいう」を編集して「helloあいうえお」にするとeditというノードが作成され、そこにまたtsが現れます。

        "ts": "1581446370.000500", ← これは変わらない
        "edited": {
            "user": "UTRUE3W13",
            "ts": "1581446760.000000" ← 編集時刻
        },

API送信の確認

検索して最初に目についたpython slackclientを使ってみました。slackclientのドキュメントはここです。
メッセージごとにテキストのみを取り出しファイルに書き込むという簡単なコードです。

import slack

token_str = {OAuth Access Token}
client = slack.WebClient(token=token_str)

response = client.conversations_history(channel="CTEE1LMQT")

for res in response["messages"]:
    print(res['user'])
    print(res['ts'])
    if ('edited' in res):
        print('edited_ts='+res['edited']['ts'])
    with open(f"./slack/{res['user']}_{res['ts']}", "w") as f:
        f.write(res['text'])

以上、すこしでも参考になれば幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした