【続・年末年始は積みゲーを消化したい！】PHP + Steam Web API + discord-php で Discord Bot に自分の積みゲーを発言させる

本記事は、[サムザップ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/sumzap) の12/7の記事です。

# はじめに
はじめまして、サムザップの[北島](https://twitter.com/RyotoKitajima)です。

ゲーム会社で働いているだけあって、私はゲームが大好きです！
特にPCゲームが大好きなのですが、仕事が忙しい社会人はついつい積みゲーが増えがちですよね（ゲームを買っただけで満足してしまう...）。

自分はどのくらい積みゲーが溜まっているのか！？
それを把握するため、[12/4の記事](https://qiita.com/RyotoKitajima/items/b9cbe230c42ab85d50b6)では、Steam Web APIを使った簡単なPHPプログラムを動かし、自分のSteamアカウントの積みゲー（プレイ時間が1時間以下のゲーム）の一覧を取得しました。
そして、その結果、91本もの積みゲーが溜まっているという状況が分かりました。
もうすぐ年末年始の休みが来ますが、さすがに91本は遊べません...

さて、いきなりですが、Steamのファミリーシェアリングという機能をご存知でしょうか？
ファミリーシェアリングを使うと、家族間でお互いのアカウントに所持しているゲームをプレイし合うことができます。

:::note info
__Steam ファミリーシェアリングとは__
Steamのライブラリを最大5つのアカウントまで家族間で共有する機能です。
https://store.steampowered.com/promotion/familysharing?l=japanese
:::

積みゲーが91本あるということで、とても自分だけでは遊びきれないと判断しましたww
そこで今回は、前回の記事で取得できるようになった積みゲーの情報を、Discord Botを使って家族がいるDiscordで発言させ、自分の代わりに積みゲーを遊んでもらうことを目指します。
自分で遊べないなら、せめて他の人に遊んでもらおう！w

# discord-php のインストール

弊社では、サーバーサイドのプログラムは主にPHPを使っています。
慣れている言語ということで、前回に引き続き今回もPHPを使いたいと思います。
Discord Botの開発には、discord-phpを使います。

まず、composerがない方は、以下でインストールしてください。

```
$ brew install composer
```

実行後、インストールされたことを確認するためにcomposerのバージョンを確認しましょう。

```
$ composer -v

   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 2.4.4 2022-10-27 14:39:29
```

次に、作業ディレクトリを作成します。

```
$ mkdir project
```

そして、作業ディレクトリの下にcomposer.jsonを作成します。
今回は、discord-phpを使いたいので、その記述をしています。

```project/composer.json
{
    "require": {
        "team-reflex/discord-php": "*"
    }
}
```

記述が終わったら、最後に以下を実行します。

```
$ composer install
```

これで、無事にdiscord-phpがインストールされるはずです。

# Discord Bot の準備

続いて、Discord側でBOTアカウントを作る必要があります。
下記から作ることが可能です。

https://discordapp.com/developers/applications/me

「New Application」ボタンを押下し、名前を入力、規約に同意するチェックを入れ、「Create」ボタンを押します。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539013/ef36c0b3-522b-4624-090d-1455cba4642d.png)

続いてメニューの「Bot」から、ICONの設定などをした上で、TOKENをコピーしておきます（後で使います）。
なお、「PUBLIC BOT」は公開するつもりがなければオフにしておくのが良さそうです。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539013/5146edbb-2997-ec66-8928-d6aa29b8954e.png)


最後に、メニューの「OAuth2 -> URL Generator」から`SCOPES: boy` 、 `BOT PERMISSIONS: Read Messages/View Channels, Send Messages` でURLを生成し、生成したURLにアクセスして作成したBOTを動かしたいDiscordサーバーに追加してください。

![2 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539013/53380d8f-ca21-af20-5fd7-2386afef6a3b.png)

これで準備が整いました。

# 作成したプログラム

準備が整ったので、BOTのコードを書いていきます。
今回書いたコード配下です。

```discord_bot.php
<?php

use Discord\Discord;
use Discord\Parts\Channel\Message;
use Discord\WebSockets\Event;

include __DIR__.'/vendor/autoload.php';

$token = "【Discord Bot のトークンを記載】";

function get_tsumige_info() {
    $api_key = "【Steam Web API の APIキー を記載】";
    $steam_id = "【Steam ID を記載】";

    // 所持しているゲームの情報を取得
    $data = json_decode(file_get_contents("http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?" . http_build_query(array("key" => $api_key, "steamid" => $steam_id, "include_appinfo" => 1))), true);

    // プレイ時間が60分以下のゲームを抽出
    $result = "";
    $count  =  0;
    foreach($data["response"]["games"] as $row) {
        if($row["playtime_forever"] <= 60) {
            $result = $result . $row["name"] . ": " . sprintf('%d時間 %d分', $row['playtime_forever'] / 60, $row['playtime_forever'] % 60) . "\n";
            $count++;
        }
    }
    $result = $result . "-------------------------------------------------------\n";
    $result = $result . "積みゲーの数: " . $count . "\n";

    $result = str_split($result, 2000);

    return $result;
}

$discord = new Discord(['token' => $token]);
$discord->on('ready', function ($discord) use ($channel_id) {
    echo "Botを起動しました。\n";

    $botUser = $discord->user;
    $discord->on('message', function ($message) use ($botUser) {
        if (isset($message->mentions[$botUser->id])) {
            $text_array = get_tsumige_info();
            foreach($text_array as $row) {
                $message->reply($row);
            }
        }
    });
});

$discord->run();
```

`get_tsumige_info()` は、中身を少し変更しているものの、前回の記事で作成した、積みゲーの情報を取得する関数になります。
Discordは1回の発言が2000文字までなので、2000文字を超える場合は配列で分割するようにしています。

`if (isset($message->mentions[$botUser->id]))` の部分ですが、BOTにメンションがついた時に、`get_tsumige_info()` で取得した積みゲーの情報をBOTに発言させています。

# 結果

では、作成したプログラムを動かしてみましょう。

```
$ php discord_bot.php

　・
　・
　・
DiscordPHP.INFO: client is ready [] []
Botを起動しました。
```

Botが起動したので、Discord上でBotにメンションを飛ばしてみます。
結果、下記画像の通り、BOTが反応し、積みゲーの情報を教えてくれました。
これを見たDiscordの家族が、私の積みゲーを代わりに遊んでくれることを願います！w

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539013/7e5d2389-6dc9-1aa1-0b17-45995a72bb29.png)

明日（アドベントカレンダー 12/8の記事）は @ozaki_shinya さんの記事になります、お楽しみに！！