見出し画像

Pythonで雀魂の対局結果を自動集計する⑤

こんにちは!カツキチです。

前回、対局結果画像から抽出した名前、素点、順位点をOneDriveの Excelに記録し、過去の結果を集計して表示するプログラムが完成しました。
しかし今のままではDiscordにアップされた画像を手でプログラムに渡し、出力された結果をDiscordに手で投稿しなければなりません。
Discordとの自動連係をするにはどうしたら良いのだろう、、、眠れない日々が続きました(約1日)。

Discordと自動連携する

私が参加するDiscordには頼もしい人たちが大勢います。雑談していたところ、yabukilabさんという方が有用な情報をくれました。

なるほど、PythonだとDiscordのBOTも作れてしまうのですね、スゴすぎる。
実装するにあたり、フローを考えました。Discord.pyは単体のプログラムで動作させる想定です。

  1. Discordのサーバーにログインする

  2. 雀魂チャンネルに画像がアップロードされたらURLを取得する

  3. 結果抽出プログラムに画像のURLを渡す

  4. 結果抽出プログラムの結果をDiscordに投稿する

なお、Discordにログインや投稿をするためのBOTアカウントを作成し、ログインしたいサーバーの管理権限を与える必要があります。手順は前述のサイトの通りです。管理権限はサングルサーバの管理者であるコージ師範に付与していただきました、感謝!

Discord連携プログラム Ver 0.1

Dicord.pyは2022年5月にメジャーバージョンアップがあったようです。新バージョンの情報が少ないため、結構苦戦しました。
テスト用のサーバーで試行錯誤を繰り返し、アップロードした画像のURLを投稿するプロトタイププログラムを作成しました。

from discord.ext import commands
import discord

# Discordの権限設定
intents = discord.Intents.default()
intents.members = True # メンバー管理の権限
intents.message_content = True # メッセージの内容を取得する権限

bot = commands.Bot(
    command_prefix="$", # $コマンド名 でコマンドを実行できるようになる
    case_insensitive=True, # 大文字小文字を区別しない
    intents=intents # 権限を設定
)

# Discordにログイン
@bot.event
async def on_ready():
    print(f"Logged in as {bot.user.name}")

# 投稿を確認
@bot.event
async def on_message(message: discord.Message):

    # BOTのメッセージは無視
    if message.author.bot:
        return
    
    # ターゲットのチャンネルID
    target_channel_id = xxxxxxxxxxxxxxxx # 練習用チャンネル

    # 投稿されたメッセージが特定のチャンネルIDの場合
    if message.channel.id == target_channel_id:

        # ファイルが添付されている場合
        if message.attachments:

            # 添付ファイルごとに処理
            for attachment in message.attachments:

                # 画像のURLをDiscordに投稿
                await message.reply(attachment)
            
# BOTのアクセストークン 
bot.run('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') # maskしています

ライブラリは以下の手順でインストールします。

PS > pip install discord.py

さて、プロトタイプを実行してみます。

PS > python.exe .\sample.py 
2025-02-22 20:29:58 INFO     discord.client logging in using static token
2025-02-22 20:30:00 INFO     discord.gateway Shard ID None has connected to Gateway (Session ID:XXXXXXXXXXXXXXXXXXXXXX X).
Logged in as カツキチBOT

この状態でDiscordの練習用チャンネルに画像をアップロードしてみます。

BOTが応答した!

うまく行きました!

Discord連携プログラム Ver 1.0

subprocessライブラリを使って画像のURLを結果抽出プログラムに渡すように変更して、完成です。

from discord.ext import commands
import discord
import subprocess

# 結果抽出プログラム
result_py = './result.py'

# Discordの権限設定
intents = discord.Intents.default()
intents.members = True # メンバー管理の権限
intents.message_content = True # メッセージの内容を取得する権限

bot = commands.Bot(
    command_prefix="$", # $コマンド名 でコマンドを実行できるようになる
    case_insensitive=True, # 大文字小文字を区別しない
    intents=intents # 権限を設定
)

# Discordにログイン
@bot.event
async def on_ready():
    print(f"Logged in as {bot.user.name}")

# 投稿を確認
@bot.event
async def on_message(message: discord.Message):

    # BOTのメッセージは無視
    if message.author.bot:
        return
    
    # ターゲットのチャンネルID
    target_channel_id = xxxxxxxxxxxxxxxx # 麻雀チャンネル

    # 投稿されたメッセージが特定のチャンネルIDの場合
    if message.channel.id == target_channel_id:

        # ファイルが添付されている場合
        if message.attachments:

            # 添付ファイルごとに処理
            for attachment in message.attachments:
          
                # 結果抽出プログラムを実行
                command = ["python", result_py, str(attachment)] 
                proc = subprocess.run(command, capture_output=True, text=True)
                
                print("標準出力:")
                print(proc.stdout)
                # 標準出力のみDiscordに投稿
                await message.reply(proc.stdout)
        
                print("\n標準エラー出力:")
                print(proc.stderr)

# BOTのアクセストークン 
bot.run('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') # maskしています

大成功!

とっさに反応するBOT

これでようやく、最初に定義した大まかなフローが完成しました!

  1. (対局した人が)対局結果のスクリーンショットをDiscordにアップする

  2. アップしたスクリーンショット画像から名前、素点、順位点を抽出する【完成】

  3. 抽出した情報を記録する【完成】

  4. 記録した情報から当月の対局結果をDiscordに投稿する【完成】

やっと完成した・・・。余韻に浸りながらパソコンを閉じた時、気づいてしまったのです。

これ、パソコン落としたら実行されないじゃん・・・

パソコンを起動せずとも、このプログラムを常時実行するにはどうしたらよいものか。
次回へ続きます。


いいなと思ったら応援しよう!