2023年1番リアクションをもらった投稿、知りたくない？

# はじめに
はじめてpythonに挑戦してみた赤ちゃんエンジニア用の技術メモです。

### きっかけ
Slackの発信にリアクションをもらえるとすごく嬉しい。社内Slackであれバズると嬉しい。
沢山リアクションがもらえた投稿ってどんな投稿なのか気になる。

私の投稿もTOP10くらいにはランクインしてるのでは？（期待）
ということで1番だけと言わず沢山リアクションをもらった投稿ランキングを取ってみた！

## 完成したもの！
Slackへの投稿もPythonで出来るようにしてみた（かっこいいから）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586761/c66477d8-aa02-d6ff-62a6-3a2f7385daf1.png)

## 使用したもの
・Slack
・Slack api
・Python

## 流れ
1.Slackアプリを作る
2.Slack APIを使うための準備
3.Pythonで集計し結果をSlackチャンネルに投稿！

おしまい、簡単な気がしますね、行けます

# 早速やっていく！
## 1.Slackアプリを作る
初めての方はこちらを参考にどうぞ～。[【これを読めば誰でも出来るSlackアプリの作り方】SlackAPIを使うための準備](https://qiita.com/Himeka_Kawaguchi/items/66cce374a88c243c439d)

そんなの余裕だぜ！という方はこのままで
### Slackアプリの権限設定

プライベートチャンネルも調査対象にしたく、`groups:history`も追加

![slackapi_scope.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586761/147b42dd-17f3-1d0b-1018-14877b9f3ffd.png)

※2024/11/1追記
groups:read の追加が必要です:bow_tone1:

## 2.Slack APIを使う為の準備
毎度REST APIを呼び出すのは面倒ということでSlackが提供するSDKを使用する
### SlackのSDKをインストール
```
py -m pip install slack-sdk
```
これで準備万端！

## 3.Pythonで集計し結果をSlackチャンネルに投稿！
ここからはPythonを書いていく

```python:reaction_count.py
from collections import Counter

from slack_sdk.web import WebClient

#トークン
SLACK_API_TOKEN = "取得したあなたのトークン"
#調査対象のチャンネル
CHANNELS_ID = "調査したいチャンネル"
#集計結果を送信するチャンネル
POST_ID = "結果を送信するチャンネル"

#トークン情報を格納しておく
client = WebClient(token=SLACK_API_TOKEN)

#チャンネル名を取得
channel_info=client.conversations_info(channel=CHANNELS_ID)
channelname=channel_info['channel']['name']

#過去の会話を1000件取得する。2023年以降の投稿に絞り込み。
response = client.conversations_history(channel=CHANNELS_ID,limit=1000,oldest=1672498800.0)

#会話履歴から、一つの投稿ごとに処理する。
reacted_message_list = []
for num, post in  enumerate(response['messages']):
    #リアクションのあった投稿を取り出す。
    if 'reactions' in post.keys():
        reacted_message_list.append(post)
        

#抽出したメッセージから、リアクションの数をカウントする。
reactioncount_list = []
for message_dict in reacted_message_list:
    sum_reaction = 0
    #投稿のリンクを取得する
    message_ts = message_dict['ts']
    response = client.chat_getPermalink(channel=CHANNELS_ID,message_ts=message_ts)
    link = response['permalink']

    for reaction_dict in message_dict['reactions']:
        reaction_count = reaction_dict['count']
        sum_reaction += reaction_count

    #投稿のリンクとリアクション数の合計値を保管
    output={"link":link,"sum_reaction":sum_reaction}
    reactioncount_list.append(output)
    reactioncount_list.sort(key=lambda x:x['sum_reaction'],reverse=True)

#ランキングtopX
TOPX=5
topx_list=reactioncount_list[:TOPX]
topx_list.sort(key=lambda x:x['sum_reaction'])


#slackに投稿する内容
slack_output=f"{channelname}チャンネルの2023年リアクション数ランキングです！"
client.chat_postMessage(channel=POST_ID, text=slack_output)


for rank,topx_post in enumerate(topx_list):
  slack_output_countdown=f"第{str(TOPX-rank)} 位はこちら！{str(topx_post['sum_reaction'])}個のリアクションをもらっています！\n{str(topx_post['link'])}"
  client.chat_postMessage(channel=POST_ID, text=slack_output_countdown)


slack_output_comment=f"このランキングはpythonで集計・投稿しています！"
client.chat_postMessage(channel=POST_ID, text=slack_output_comment)

```
### やりたいこと
***・投稿につくリアクション数を集計*** 
　・過去の会話を取得
　・会話履歴からリアクションのついた投稿だけに絞り込み
　・投稿についたリアクションの数をカウント
 
***・チャンネル名を取得***
　XXXチャンネルのランキングです！と言いたい。

***・投稿のリンクを取得***
　ランキング結果を表示する際に、投稿のリンクをプレビューとして表示させたい。

***・カウントダウン形式でランキング結果をSlackに投稿***
　・ランキングとして表示したい件数を指定
　・カウントダウン形式にソート
　・Slackチャンネルに結果を投稿

## 詳しく見てみると
### あなたの情報を入れる
先ほど取得したトークンを入力。
該当するSlackチャンネルのチャンネルIDを取得し入力。

```python
from collections import Counter

from slack_sdk.web import WebClient

#トークン情報
SLACK_API_TOKEN = "取得したあなたのトークン"
#調査対象のチャンネル
CHANNELS_ID = "調査したいチャンネル"
#集計結果を送信するチャンネル
POST_ID = "結果を送信するチャンネル"

#トークン情報を格納しておく
client = WebClient(token=SLACK_API_TOKEN)
```
### チャンネルIDからチャンネル名を取得

```python
#チャンネル名を取得
channel_info=client.conversations_info(channel=CHANNELS_ID)
channelname=channel_info['channel']['name']
```

### 過去の会話からリアクションのあった投稿だけに絞り込み
`conversations_history()`を用い過去の会話履歴を取得。
デフォルトの取得件数は100件であるため、調査対象のチャンネルに100件以上の投稿がある場合は上限値を変更する必要あり。
確実に全件取れるようにしたく上限を1000件に指定。`limit=1000`
また2023年のランキングにしたいので、UNIX時間2023年1月1日以降の会話に指定。`oldest=1672498800.0`
```py
#過去の会話を1000件取得する。2023年以降の投稿に絞り込み。
response = client.conversations_history(channel=CHANNELS_ID,limit=1000,oldest=1672498800.0)
```
リアクションのあった投稿だけを取り出し、リアクションの数をカウント。
`chat_getPermalink`で投稿のリンクを取得。

```py
#会話履歴から、一つの投稿ごとに処理する。
reacted_message_list = []
for num, post in  enumerate(response['messages']):
    #リアクションのあった投稿を取り出す。
    if 'reactions' in post.keys():
        reacted_message_list.append(post)
        

#抽出したメッセージから、リアクションの数をカウントする。
reactioncount_list = []
for message_dict in reacted_message_list:
    sum_reaction = 0
    #投稿のリンクを取得する
    message_ts = message_dict['ts']
    response = client.chat_getPermalink(channel=CHANNELS_ID,message_ts=message_ts)
    link = response['permalink']

    for reaction_dict in message_dict['reactions']:
        reaction_count = reaction_dict['count']
        sum_reaction += reaction_count

    #投稿のリンクとリアクション数の合計値を保管
    output={"link":link,"sum_reaction":sum_reaction}
    reactioncount_list.append(output)
    reactioncount_list.sort(key=lambda x:x['sum_reaction'],reverse=True)
```


### ランキングで表示したい件数を決める
今回はTOP5に。TOPXにランキングで表示したい件数を入れる。
カウントダウン形式で表示したい為TOPXの結果をソート。
```python
#ランキングtopX
TOPX=5
topx_list=reactioncount_list[:TOPX]
topx_list.sort(key=lambda x:x['sum_reaction'])
```

### Slackへ投稿する内容
`chat_postMessage()`でSlackチャンネルへ投稿できる。
`:(絵文字の名前):`を入力するとSlackのカスタム絵文字も投稿できた

```py
#slackに投稿する内容
slack_output=f"{channelname}チャンネルの2023年リアクション数ランキングです！"
client.chat_postMessage(channel=POST_ID, text=slack_output)

for rank,topx_post in enumerate(topx_list):
  slack_output_countdown=f"第{str(TOPX-rank)} 位はこちら！{str(topx_post['sum_reaction'])}個のリアクションをもらっています！\n{str(topx_post['link'])}"
  client.chat_postMessage(channel=POST_ID, text=slack_output_countdown)

slack_output_comment=f"このランキングはpythonで集計・投稿しています！"
client.chat_postMessage(channel=POST_ID, text=slack_output_comment)

```

## 完成！
![完成形.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586761/4b5a8eab-efb8-4232-5bdb-977d7653d01e.png)

またまた沢山リアクションをもらいました！（嬉しい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586761/b0ca48bc-470e-3a21-b6c4-483437905738.png)



## おわり
リアクション数という形ではあるが、2023年の投稿を振り返ることができた！
結果からどの期間の投稿にリアクションが多くついているかなど、考えてみるのも面白い。
嬉しい事にTOP10にランクインしている投稿もあった（やったー）
2024年も沢山リアクションを押していきたいし、押されたい。