mattermostの投稿数やリアクション数をカウントするスクリプト作ってもらった

mattermostの投稿数等をカウントするPythonスクリプトをchatGPTにつくってもらいました。
出先で思いついたのでまだ自分でも試してないですが、とりあえずメモ代わりに。

2023/4/13 追記
残念ながら試してみたらURL構成の違いで動かないので、修正版です。
全部まとめてCSVにしてもらいます。
やっぱり自分で試さないとダメですね。

内容修正に当たっては[Mattermost-driver](https://vaelor.github.io/python-mattermost-driver/index.html)を使わせていただきました。
事前にインストールしておきましょう。

```Python
from mattermostdriver import Driver
import csv
from datetime import datetime, timedelta

# Mattermost API settings
api_url = "localhost"
api_key = "zoo41zod5385t8mc8nuyipe1fo"

# Set up Mattermost driver
mm = Driver({
    "url": api_url,
    "token": api_key,
    "scheme": "https",
    "port": 20443,
    'verify': False,
    "timeout": 30,
})

# Connect to Mattermost
mm.login()

# Get the default team ID
team_name = "default"
team = mm.teams.get_team_by_name(team_name)
team_id = team["id"]

# Get public channels in the team
channels = mm.channels.get_public_channels(team_id)

# Get users
users = mm.users.get_users()

# Initialize user stats
user_stats = {}
for user in users:
    user_stats[user["id"]] = {
        "username": user["username"],
        "total_posts": 0,
        "received_reactions": 0,
        "given_reactions": 0,
    }

# Calculate stats
yesterday = datetime.now() - timedelta(days=1)
yesterday_unix = int(yesterday.timestamp() * 1000)

for channel in channels:
    # Get channel's posts
    posts = mm.posts.get_posts_for_channel(channel["id"])["posts"]

    for post in posts.values():

        if yesterday_unix < post["create_at"] < datetime.now().timestamp() * 1000:

            # Increment user's total_posts
            user_stats[post["user_id"]]["total_posts"] += 1

            # Calculate received reactions
            reactions = post.get("reactions", [])
            user_stats[post["user_id"]]["received_reactions"] += len(reactions)

            # Calculate given reactions
            for reaction in reactions:
                user_id = reaction["user_id"]
                if user_id in user_stats:
                    user_stats[user_id]["given_reactions"] += 1

# Write the results to a CSV file
output_file = "mattermost_user_stats.csv"
with open(output_file, "w", newline="") as csvfile:
    csv_writer = csv.writer(csvfile)
    csv_writer.writerow(
        [
            "Username",
            "Total Posts",
            "Received Reactions",
            "Given Reactions",
        ]
    )

    for user_id, stats in user_stats.items():
        csv_writer.writerow(
            [
                stats["username"],
                stats["total_posts"],
                stats["received_reactions"],
                stats["given_reactions"],
            ]
        )

print(f"User stats saved to {output_file}.")

```

<details><summary>過去投稿分</summary>

# 投稿数カウント

質問:
mattermost 7のdefaultチームにおける全チャンネルに対する投稿数を日別・ユーザ別に集計し、csvファイルに出力するpythonスクリプトを作って欲しいです。

回答:ご要望いただいたPythonスクリプトを以下に示します。スクリプトを実行する前に、Pythonのバージョンが3.6以上であることを確認してください。また、必要に応じてpandasライブラリをインストールしてください。

```python
import requests
import pandas as pd
from datetime import datetime, timedelta

# MattermostサーバーのURLとAPIトークンを指定
MATTERMOST_URL = "https://your-mattermost-url.com/api/v4"
MATTERMOST_TOKEN = "your-api-token"

# 投稿数を取得する期間を指定
start_date = datetime(2023, 1, 1)  # 開始日
end_date = datetime(2023, 4, 7)  # 終了日

# Mattermost APIを使ってチームとチャンネルの情報を取得
headers = {"Authorization": "Bearer " + MATTERMOST_TOKEN}
teams_response = requests.get(f"{MATTERMOST_URL}/teams", headers=headers)
teams_data = teams_response.json()
default_team_id = [team["id"] for team in teams_data if team["name"] == "default"][0]
channels_response = requests.get(f"{MATTERMOST_URL}/teams/{default_team_id}/channels", headers=headers)
channels_data = channels_response.json()

# 日別・ユーザ別の投稿数を保存するためのデータフレームを初期化
date_range = pd.date_range(start_date, end_date)
users = []
for channel in channels_data:
    users += [user["username"] for user in channel["members"]]
users = list(set(users))
index = pd.MultiIndex.from_product([date_range, users], names=["date", "user"])
columns = [channel["display_name"] for channel in channels_data]
post_counts = pd.DataFrame(0, index=index, columns=columns)

# Mattermost APIを使って日別・ユーザ別の投稿数を集計
for channel in channels_data:
    channel_id = channel["id"]
    channel_name = channel["display_name"]
    posts_response = requests.get(f"{MATTERMOST_URL}/channels/{channel_id}/posts", headers=headers)
    posts_data = posts_response.json()
    for post in posts_data:
        post_date = datetime.fromtimestamp(int(post["create_at"]) / 1000)
        if start_date <= post_date < end_date:
            post_user = post["user_name"]
            post_counts.loc[(post_date, post_user), channel_name] += 1

# CSVファイルに出力
post_counts.to_csv("post_counts.csv")
```

スクリプトの使い方：

MATTERMOST_URLとMATTERMOST_TOKENを適切な値に変更します。
投稿数を取得する期間をstart_dateとend_dateで指定します。
スクリプトを実行します。
スクリプトが終了すると、同じディレクトリにpost_counts.csvが作成されます。
このスクリプトは、MattermostのAPIを使用して投稿数を取得します。APIトークンが必要なため、事前にMattermostの管理者からトークンを取得する必要

# リアクション数

質問:投稿数ではなく、投稿したコメントに対するリアクションをした数を出すようにできますか？

回答:はい、可能です。投稿されたコメントに対するリアクションを数えるには、MattermostのAPIにリアクションに関する情報を取得するエンドポイントがあります。具体的には、/posts/{post_id}/reactionsというエンドポイントを使用します。

投稿数をカウントするスクリプトをベースに、リアクション数をカウントするスクリプトを以下に示します。

```Python
import requests
import pandas as pd
from datetime import datetime, timedelta

# MattermostサーバーのURLとAPIトークンを指定
MATTERMOST_URL = "https://your-mattermost-url.com/api/v4"
MATTERMOST_TOKEN = "your-api-token"

# 投稿数を取得する期間を指定
start_date = datetime(2023, 1, 1)  # 開始日
end_date = datetime(2023, 4, 7)  # 終了日

# Mattermost APIを使ってチームとチャンネルの情報を取得
headers = {"Authorization": "Bearer " + MATTERMOST_TOKEN}
teams_response = requests.get(f"{MATTERMOST_URL}/teams", headers=headers)
teams_data = teams_response.json()
default_team_id = [team["id"] for team in teams_data if team["name"] == "default"][0]
channels_response = requests.get(f"{MATTERMOST_URL}/teams/{default_team_id}/channels", headers=headers)
channels_data = channels_response.json()

# 日別・ユーザ別のリアクション数を保存するためのデータフレームを初期化
date_range = pd.date_range(start_date, end_date)
users = []
for channel in channels_data:
    users += [user["username"] for user in channel["members"]]
users = list(set(users))
index = pd.MultiIndex.from_product([date_range, users], names=["date", "user"])
columns = [channel["display_name"] for channel in channels_data]
reaction_counts = pd.DataFrame(0, index=index, columns=columns)

# Mattermost APIを使って日別・ユーザ別のリアクション数を集計
for channel in channels_data:
    channel_id = channel["id"]
    channel_name = channel["display_name"]
    posts_response = requests.get(f"{MATTERMOST_URL}/channels/{channel_id}/posts", headers=headers)
    posts_data = posts_response.json()
    for post in posts_data:
        post_date = datetime.fromtimestamp(int(post["create_at"]) / 1000)
        if start_date <= post_date < end_date:
            post_user = post["user_name"]
            post_id = post["id"]
            reactions_response = requests.get(f"{MATTERMOST_URL}/posts/{post_id}/reactions", headers=headers)
            reactions_data = reactions_response.json()
            for reaction in reactions_data:
                reaction_user = reaction["user_name"]
                reaction_counts.loc[(post_date, reaction_user), channel_name] += 1

# CSVファイルに出力
reaction_counts.to_csv("reaction_counts.csv")

```

# リアクション受け取った数

質問:リアクションを受け取った数をカウントすることはできますか？

回答:はい、可能です。投稿されたコメントに対するリアクションを受け取った数を数えるには、MattermostのAPIにリアクションに関する情報を取得するエンドポイントがあります。具体的には、/reactions/{emoji_name}/usersというエンドポイントを使用します。

前回のスクリプトをベースに、リアクションを受け取った数をカウントするスクリプトを以下に示します。

```Python
import requests
import pandas as pd
from datetime import datetime, timedelta

# MattermostサーバーのURLとAPIトークンを指定
MATTERMOST_URL = "https://your-mattermost-url.com/api/v4"
MATTERMOST_TOKEN = "your-api-token"

# カウントする期間を指定
start_date = datetime(2023, 1, 1)  # 開始日
end_date = datetime(2023, 4, 7)  # 終了日

# Mattermost APIを使ってチームとチャンネルの情報を取得
headers = {"Authorization": "Bearer " + MATTERMOST_TOKEN}
teams_response = requests.get(f"{MATTERMOST_URL}/teams", headers=headers)
teams_data = teams_response.json()
default_team_id = [team["id"] for team in teams_data if team["name"] == "default"][0]
channels_response = requests.get(f"{MATTERMOST_URL}/teams/{default_team_id}/channels", headers=headers)
channels_data = channels_response.json()

# リアクションを受け取った数を保存するためのデータフレームを初期化
date_range = pd.date_range(start_date, end_date)
users = []
for channel in channels_data:
    users += [user["username"] for user in channel["members"]]
users = list(set(users))
index = pd.MultiIndex.from_product([date_range, users], names=["date", "user"])
columns = ["reactions_received"]
reaction_received_counts = pd.DataFrame(0, index=index, columns=columns)

# Mattermost APIを使ってリアクションを受け取った数を集計
for channel in channels_data:
    channel_id = channel["id"]
    channel_name = channel["display_name"]
    posts_response = requests.get(f"{MATTERMOST_URL}/channels/{channel_id}/posts", headers=headers)
    posts_data = posts_response.json()
    for post in posts_data:
        post_date = datetime.fromtimestamp(int(post["create_at"]) / 1000)
        if start_date <= post_date < end_date:
            post_user = post["user_name"]
            post_id = post["id"]
            reactions_response = requests.get(f"{MATTERMOST_URL}/posts/{post_id}/reactions", headers=headers)
            reactions_data = reactions_response.json()
            for reaction in reactions_data:
                reaction_emoji = reaction["emoji_name"]
                reaction_users_response = requests.get(f"{MATTERMOST_URL}/reactions/{reaction_emoji}/users", headers=headers)
                reaction_users_data = reaction_users_response.json()
                for reaction_user in reaction_users_data:
                    reaction_received_counts.loc[(post_date, reaction_user["username"]), "reactions_received"] += 1

# CSVファイルに出力
reaction_received_counts.to_csv("reaction_received_counts.csv")

```

# GPT-4 に全部入り作ってもらいました

## 質問

mattermostのdefaultチームにおける全チャンネルに対する
・投稿数
・投稿したコメントへの被リアクション数
・他人が投稿したコメントへのリアクション数
をユーザ別に集計し、csvファイルに出力するpythonスクリプトを作ってください。
対象日はスクリプト実行日の前日とします。
なお、行の途中で回答が止まらないように適宜出力を止めてください。
私が「続き」と言ったら、続きを出力してください。

## 回答

以下のPythonスクリプトは、Mattermost APIを使用して、指定された要件に基づいてデータを取得し、CSVファイルに出力します。

```Python
import requests
import csv
import os
from datetime import datetime, timedelta

# Mattermost API settings
api_url = "https://your-mattermost-server.com/api/v4/"
api_key = "your-personal-access-token"

# Set up headers for API requests
headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json",
}

# Get the default team ID
team_name = "default"
team_response = requests.get(api_url + "teams/name/" + team_name, headers=headers)
team_id = team_response.json()["id"]

# Get all the channels in the team
channels_response = requests.get(api_url + f"teams/{team_id}/channels", headers=headers)
channels = channels_response.json()

# Get users
users_response = requests.get(api_url + "users", headers=headers)
users = users_response.json()

# Initialize user stats
user_stats = {}
for user in users:
    user_stats[user["id"]] = {
        "username": user["username"],
        "total_posts": 0,
        "received_reactions": 0,
        "given_reactions": 0,
    }

# Calculate stats
yesterday = datetime.now() - timedelta(days=1)
yesterday_str = yesterday.strftime("%Y-%m-%d")

for channel in channels:
    # Get channel's posts
    posts_response = requests.get(
        api_url + f"channels/{channel['id']}/posts?since={yesterday_str}", headers=headers
    )
    posts = posts_response.json()["posts"]

    for post in posts.values():
        # Increment user's total_posts
        user_stats[post["user_id"]]["total_posts"] += 1

        # Calculate received reactions
        reactions = post.get("reactions", [])
        user_stats[post["user_id"]]["received_reactions"] += len(reactions)

        # Calculate given reactions
        for reaction in reactions:
            user_id = reaction["user_id"]
            if user_id in user_stats:
                user_stats[user_id]["given_reactions"] += 1

# Write the results to a CSV file
output_file = "mattermost_user_stats.csv"
with open(output_file, "w", newline="") as csvfile:
    csv_writer = csv.writer(csvfile)
    csv_writer.writerow(
        [
            "Username",
            "Total Posts",
            "Received Reactions",
            "Given Reactions",
        ]
    )

    for user_id, stats in user_stats.items():
        csv_writer.writerow(
            [
                stats["username"],
                stats["total_posts"],
                stats["received_reactions"],
                stats["given_reactions"],
            ]
        )

print(f"User stats saved to {output_file}.")
```

注意: このスクリプトを実行する前に、api_urlとapi_keyを正しい値に置き換えてください。また、必要に応じてteam_nameを適切なチーム名に置き換えてください。このスクリプトはPython 3.6以降で動作します。

このスクリプトは、Mattermostの全チャンネルにおける各ユーザーの投稿数、投稿したコメントへの被リアクション数、他人が投稿したコメントへのリアクション数を集計し、それらの情報をCSVファイルに出力します。スクリプトは前日のデータに基づいて集計を行います。

このスクリプトは、次の手順で動作します。

Mattermost APIを使ってデフォルトチームのIDを取得します。
デフォルトチーム内のすべてのチャンネルを取得します。
すべてのユーザーを取得し、各ユーザーの統計情報を初期化します。
前日の日付を計算し、その日付を元にチャンネルごとの投稿を取得します。
各投稿に対して、投稿数、投稿したコメントへの被リアクション数、他人が投稿したコメントへのリアクション数を集計します。
集計結果をCSVファイルに出力します。
このスクリプトを使用する際は、api_urlとapi_keyを適切な値に置き換える必要があります。また、必要に応じてteam_nameを正しいチーム名に置き換えてください。このスクリプトはPython 3.6以降で動作します。

# (おまけ)CSVファイルをもとにMattermostに投げる

せっかく作ってくれたCSVファイルを利用しないのはもったいないので、Mattermostに投稿してもらえるようにします。

## 質問

・ユーザ名
・投稿数
・投稿したコメントへの被リアクション数
・他人が投稿したコメントへのリアクション数
というカラムを持つCSVファイルを読み込んで
・ユーザ名以外のパラメータの合計値
を算出し
・ユーザ名以外のパラメータの合計値
・投稿数
・他人が投稿したコメントへのリアクション数
・投稿したコメントへの被リアクション数
の順にソートした形でMattermostへ投稿するPythonスクリプトを作ってください。

## 回答

まず、Pythonで chardet パッケージをインストールしてください。次のコマンドを実行します。
```
pip install chardet
```
次に、以下のPythonスクリプトを使用して、CSVファイルの内容をマークダウン形式のテーブルに変換し、指定された順序でソートしてMattermostに投稿します。

```python
import csv
import requests
import chardet


def read_csv(file_path):
    with open(file_path, "rb") as f:
        result = chardet.detect(f.read())

    data = []
    with open(file_path, newline='', encoding=result["encoding"]) as csvfile:
        csvreader = csv.reader(csvfile)
        for row in csvreader:
            data.append(row)
    return data


def process_data(data):
    processed_data = []
    for row in data[1:]:
        total_score = sum(map(int, row[1:]))
        processed_data.append([row[0], total_score] + row[1:])
    return sorted(processed_data, key=lambda x: (x[1], x[2], x[4], x[3]), reverse=True)


def convert_to_markdown_table(headers, data):
    table = ["| " + " | ".join(headers) + " |"]
    table.append("| " + " | ".join(["---"] * len(headers)) + " |")

    for row in data:
        table.append("| " + " | ".join(map(str, row)) + " |")

    return "\n".join(table)


def post_to_mattermost(table, config):
    base_url = config["url"]
    api_key = config["api_key"]
    team_name = config["team_name"]
    channel_name = config["channel_name"]

    headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}

    # Get team and channel IDs
    team_url = f"{base_url}/api/v4/teams/name/{team_name}"
    channel_url = f"{base_url}/api/v4/teams/name/{team_name}/channels/name/{channel_name}"

    response = requests.get(team_url, headers=headers)
    team_id = response.json()["id"]

    response = requests.get(channel_url, headers=headers)
    channel_id = response.json()["id"]

    # Create post
    post_url = f"{base_url}/api/v4/posts"
    post_data = {
        "channel_id": channel_id,
        "message": table
    }
    response = requests.post(post_url, headers=headers, json=post_data)

    if response.status_code != 201:
        raise Exception("Failed to post message")


if __name__ == "__main__":
    input_csv = "input.csv"  # CSVファイルのパス

    mattermost_config = {
        "url": "your-mattermost-url",  # MattermostサーバーのURL
        "api_key": "your-api-key",  # あなたのAPIキー
        "team_name": "your-team-name",  # チーム名
        "channel_name": "your-channel-name",  # チャンネル名
    }

    csv_data = read_csv(input_csv)
    headers = csv_data[0] + ['合計値']
    processed_data = process_data(csv_data)
    markdown_table = convert_to_markdown_table(headers, processed_data)
    post_to_mattermost(markdown_table, mattermost_config)

```
</details>