RaspberryPIでSlack APIを利用して通知アプリを作成#2(SlackのMSG登録編）

#今日のゴール
SlackのメッセージをDBへ登録します。
メッセージの種類がどのくらいあるか分からないですが、
とりあえず次のパターンのデータを登録するようにします。

#メッセージ種類
①一般てきなメッセージ：スレッドのメッセージがないメッセージとスレッドのメッセージを持っている親のメッセージを指しています。
②スレッドのメッセージ：親のメッセージの配下に存在するメッセージを指しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/26e57389-6860-b610-43fb-94d66a912a6e.png)

#テーブル構成
下記のテーブル項目はメッセージ履歴APIからのレスポンス項目を基に作成した項目一覧です。
一部項目ではJson形式に保存される項目もあります。

##メッセージテーブル
一般的なメッセージが登録されるテーブルです。

```bash
CREATE TABLE `msg` (
  `id` int(11) NOT NULL,
  `client_msg_id` varchar(50) DEFAULT NULL,
  `thread_ts` varchar(50) DEFAULT NULL,
  `subscribed` tinyint(1) DEFAULT NULL,
  `blocks` varchar(2048) DEFAULT NULL,
  `reply_users` varchar(50) DEFAULT NULL,
  `reply_users_count` tinyint(3) UNSIGNED DEFAULT NULL,
  `text` varchar(2048) DEFAULT NULL,
  `last_read` varchar(50) DEFAULT NULL,
  `ts` varchar(50) DEFAULT NULL,
  `reply_count` tinyint(3) UNSIGNED DEFAULT NULL,
  `user` varchar(50) DEFAULT NULL,
  `team` varchar(50) DEFAULT NULL,
  `latest_reply` varchar(50) DEFAULT NULL,
  `files` varchar(4096) DEFAULT NULL,
  `upload` tinyint(1) DEFAULT NULL,
  `display_as_bot` tinyint(1) DEFAULT NULL,
  `type` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `msg`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `msg`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
```

##スレッドメッセージテーブル
スレッドのメッセージが登録されるテーブルです。

```bash
CREATE TABLE `ts_msg` (
  `id` int(11) NOT NULL,
  `client_msg_id` varchar(50) DEFAULT NULL,
  `thread_ts` varchar(50) DEFAULT NULL,
  `blocks` varchar(2048) DEFAULT NULL,
  `text` varchar(2048) DEFAULT NULL,
  `ts` varchar(50) DEFAULT NULL,
  `user` varchar(50) DEFAULT NULL,
  `team` varchar(50) DEFAULT NULL,
  `parent_user_id` varchar(50) DEFAULT NULL,
  `files` varchar(4096) DEFAULT NULL,
  `upload` tinyint(1) DEFAULT NULL,
  `display_as_bot` tinyint(1) DEFAULT NULL,
  `type` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `ts_msg`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `ts_msg`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
```

#Slackのapi
・使用するスコープ：channels.history
該当チャネルIDを指定してそこのメッセージ履歴を取得する機能です。
※チャネルのすべてのメッセージを取得します。
→今後日付を指定してその日付に該当するものを取得できるように追記します。

```bash
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import json

url = "https://slack.com/api/channels.history"
token = "token key"
channel_id = "CTR4WAPEY" #　★その他のソースを参照★


def main():
    payload = {
        "token": token,
        "channel": channel_id
        }
    response = requests.get(url, params=payload)

    json_data = response.json()
    messages = json_data["messages"]
    #print(messages)
    for i in messages:
        print(i["text"])


if __name__ == '__main__':
    main()
```

#メッセージ履歴の実行結果
本文のメッセージのみ表示しています。
レスポンスキーが確認したい場合は、上記のソースで次の部分を修正すれば
APIのすべてのキーが表示されます。
この部分は各自の環境で試してみてください。
print(messages)


```bash
pi@raspberry:~ $ python channels.history.py
ABCD
test11111
test1234
testtest
test
pi@raspberry:~ $
```

#実行結果のSlackメッセージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/b10dbc36-79f8-3aef-5bf6-a19eeb4eb904.png)


#その他：チャネルIDを取得するAPI
使用するスコープ：channels.list
Slackのチャネル一覧情報を取得します。

```bash
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import json

url = "https://slack.com/api/channels.list"
token = "token key"

def main():
    userlist = {}
    payload = {"token":token }
    response = requests.get(url,params=payload)
    user_json = response.json()
    #print(user_json)
    for i in user_json["channels"]:
        print("id=" + i["id"] + " name=" + i["name"])

if __name__ == '__main__':
    main()
```

#その他実行結果

```bash
pi@raspberry:~ $ python channels.list.py
id=CTE4GJVV1 name=project
id=CTR4WAPEY name=team
id=CTRJY6Y1K name=welcome
pi@raspberry:~ $
```

#メッセージ履歴をDBへ登録するコード
APIから返ってくるレスポンスIDが異なるケースがありました。
そのケースは以下の4点です。現在把握しているケースです。
各自Slackに下記のメッセージを入れてからソースを実行して見てください。

①添付ファイルがないメッセージ
②添付ファイルがないスレッドのメッセージ
③添付ファイルがあるメッセージ
④添付ファイルがあるスレッドのメッセージ
※その他：添付ファイルの拡張子によってレスポンスIDがまた異なるようです。

```bash
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import MySQLdb
import json

### slack api setup ###
url = "https://slack.com/api/channels.history"
token = "token key"
channel_id = "CTR4WAPEY "
#######################

### mysql setup ###
host='localhost'
user='user id'
passwd='user passwod'
db='database name'
###################

class ApiGet:
    def channel_list(self):
        try:
            payload = {
                "token": token,
                "channel": channel_id
            }
            response = requests.get(url, params=payload)

            json_data = response.json()
            messages = json_data["messages"]
        except Exception as e:
            print(e)
        return messages
 

class DataSet:
    def __init__(self,message):
        for i in message:
            self.client_msg_id = ""
            self.thread_ts = ""
            self.subscribed = ""
            self.blocks = ""
            self.reply_users = ""
            self.reply_users_count  = ""
            self.text = ""
            self.last_read = ""
            self.ts = ""
            self.reply_count = ""
            self.user = ""
            self.team = ""
            self.latest_reply = ""
            self.parent_user_id = ""
            self.files = ""
            self.upload = ""
            self.display_as_bot = ""
            self.type = ""

            if ('client_msg_id' in i):
                self.client_msg_id = i['client_msg_id']

            if ('thread_ts' in i): 
                self.thread_ts = i['thread_ts']

            if ('subscribed' in i):
                self.subscribed = i['subscribed']

            if ('blocks' in i):
                self.blocks = i['blocks']

            if ('reply_users' in i):
                self.reply_users = i['reply_users']

            if ('reply_users_count' in i):
                self.reply_users_count  = i['reply_users_count']

            if ('text' in i):
                self.text = i['text']

            if ('last_read' in i):
                self.last_read = i['last_read']

            if ('ts' in i):
                self.ts = i['ts']

            if ('reply_count' in i):
                self.reply_count = i['reply_count']

            if ('user' in i):
                self.user = i['user']

            if ('team' in i):
                self.team = i['team']

            if ('latest_reply' in i):
                self.latest_reply = i['latest_reply']

            if ('parent_user_id' in i):
                self.parent_user_id = i['parent_user_id']

            if ('files' in i):
                self.files = i['files']

            if ('upload' in i):
                self.upload = i['upload']

            if ('display_as_bot' in i):
                self.display_as_bot = i['display_as_bot']

            if ('type' in i):
                self.type = i['type']

            if ('parent_user_id' in i):
                if (self.rec_cnt(self.ts, self.user, 'ts_msg')<=0):
                    self.RegDB_TS()
                else:
                    self.UpdateTB_TS()
            else:
                if (self.rec_cnt(self.ts, self.user, 'msg')<=0):
                    self.RegDB()
                else:
                    self.UpdateTB()

            self.Output()


    def RegDB(self):
        try:
            conn = MySQLdb.connect(host=host, db=db, user=user, passwd=passwd, charset="utf8")
            cursor = conn.cursor()
            sql = """
                insert into msg (
                    client_msg_id,
                    thread_ts,
                    subscribed,
                    blocks,
                    reply_users,
                    reply_users_count,
                    text,
                    last_read,
                    ts,
                    reply_count,
                    user,
                    team,
                    latest_reply,
                    files,
                    upload,
                    display_as_bot, 
                    type
                )
                values
                (
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s
                )
            """
            cursor.execute(sql, (self.client_msg_id,self.thread_ts,str(self.subscribed),str(self.blocks),str(self.reply_users),str(self.reply_users_count),self.text,self.last_read,self.ts,str(self.reply_count),str(self.user),self.team,self.latest_reply,str(self.files),str(self.upload),str(self.display_as_bot),self.type))
            cursor.close()
            conn.commit()
            conn.close()
        except Exception as e:
            print(e)


    def RegDB_TS(self):
        try:
            conn = MySQLdb.connect(host=host, db=db, user=user, passwd=passwd, charset="utf8")
            cursor = conn.cursor()
            sql = """
                insert into ts_msg (
                    client_msg_id,
                    thread_ts,
                    blocks,
                    text,
                    ts,
                    user,
                    team,
                    parent_user_id,
                    files,
                    upload,
                    display_as_bot, 
                    type
                )
                values
                (
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s,
                    %s
                )
            """
            cursor.execute(sql, (self.client_msg_id,self.thread_ts,str(self.blocks),self.text,self.ts,str(self.user),self.team,str(self.parent_user_id),str(self.files),str(self.upload),str(self.display_as_bot),self.type))
            cursor.close()
            conn.commit()
            conn.close()
        except Exception as e:
            print(e)


    def UpdateTB(self):
        try:
            conn = MySQLdb.connect(host=host, db=db, user=user, passwd=passwd, charset="utf8")
            cursor = conn.cursor()
            sql = """
                update msg
                set
                    client_msg_id=%s,
                    thread_ts=%s,
                    subscribed=%s,
                    blocks=%s,
                    reply_users=%s,
                    reply_users_count=%s,
                    text=%s,
                    last_read=%s,
                    ts=%s,
                    reply_count=%s,
                    user=%s,
                    team=%s,
                    latest_reply=%s,
                    files=%s,
                    upload=%s,
                    display_as_bot=%s,
                    type=%s
                where ts=%s and user=%s
            """
            cursor.execute(sql,(self.client_msg_id,self.thread_ts,str(self.subscribed),str(self.blocks),str(self.reply_users),str(self.reply_users_count),str(self.text),self.last_read,self.ts,str(self.reply_count),str(self.user),self.team,str(self.latest_reply),str(self.files),str(self.upload),str(self.display_as_bot),self.type,self.ts,str(self.user)))
            cursor.close()
            conn.commit()
            conn.close()
        except Exception as e:
            print(e)


    def UpdateTB_TS(self):
        try:
            conn = MySQLdb.connect(host=host, db=db, user=user, passwd=passwd, charset="utf8")
            cursor = conn.cursor()
            sql = """
                update ts_msg
                set
                    client_msg_id=%s,
                    thread_ts=%s,
                    blocks=%s,
                    text=%s,
                    ts=%s,
                    user=%s,
                    team=%s,
                    parent_user_id=%s,
                    files=%s,
                    upload=%s,
                    display_as_bot=%s,
                    type=%s
                where ts=%s and user=%s
            """
            cursor.execute(sql,(self.client_msg_id,self.thread_ts,str(self.blocks),str(self.text),self.ts,str(self.user),self.team,self.parent_user_id,str(self.files),str(self.upload),str(self.display_as_bot),self.type))
            cursor.close()
            conn.commit()
            conn.close()
        except Exception as e:
            print(e)


    def Output(self):
        print("=================================================================================")
        print('client_msg_id = ' + self.client_msg_id)
        print('thread_ts = ' + self.thread_ts)
        print('subscribed = ' + str(self.subscribed))
        print('blocks = ' + str(self.blocks))
        print('reply_users = ' + str(self.reply_users))
        print('reply_users_count = ' + str(self.reply_users_count))
        print('text = ' + self.text)
        print('last_read = ' + self.last_read)
        print('ts = ' + self.ts)
        print('reply_count = ' + str(self.reply_count))
        print('user = ' + str(self.user))
        print('team = ' + self.team)
        print('latest_reply = ' + self.latest_reply)
        print('files = ' + str(self.files))
        print('upload = ' + str(self.upload))
        print('display_as_bot = ' + str(self.display_as_bot))
        print('type = ' + self.type)


    def rec_cnt(self, ts, id, tbl):
        try:
            conn = MySQLdb.connect(host=host, db=db, user=user, passwd=passwd, charset="utf8")
            cursor = conn.cursor()
            sql = "select count(*) from " + tbl + " where ts='" + ts + "' and user='" + id + "'"
            print(sql)
            cursor.execute(sql)
            return cursor.fetchall()[0][0]
        except Exception as e:
            print(e)
        return 0


if __name__ == '__main__':
    apiGet = ApiGet()
    msg = apiGet.channel_list() 
    dataSet = DataSet(msg)

```

#実際登録されているテーブル
文字が小さくて見にくいかもしれないですが、この形でテーブルへ登録しています。
項目の中にはJson形式で登録されている項目もあります。
Files項目の場合は、アップロードされたファイルがWEBからアクセス可能なURLになっていました。
RaspberryPIでそのファイルをダウンロードしたい場合、wgetコマンドを使えばダウンロードは可能です。

##添付ファイルをダウンロード

```bash
wget https://xxx.xxx.xxx/xxx/sss/xxxx/0610e9.png
```

##一般的なメッセージ（スレッドのメッセージの親メッセージ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/c379c129-e37c-8f2c-b81d-9480e60610e9.png)

##スレッドのメッセージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/bf2d0c06-5087-3552-a59d-dc38aa223978.png)

#MySQLパッケージインストール
インストールコマンドは以下の通りです。

```bash
pip install MySQL-Python
```

次のサイトを参照してください。
https://uxmilk.jp/23509

#終わりに
Pythonが得意ではないですが、色々調べながら完成したソースコードです。
例外ケースが足りない箇所もあるかもしれないですが、一応登録ができましたので、
次回は特定チャネルにエクセルファイルをアップロードするとサーバ側でそのファイルを解析し、DBへ登録する記事を作成します。

最後まで読んでいただいてありがとうございました。<(__)>