LaravelアプリからDiscordのチャンネルに色々送れるようにする

発言に反応するDiscord Botの既存実装があり、そいつにブラウザとかから入力した内容を喋らせたくなったのでLaravelアプリにのっけた実装のメモ。

https://www.restcord.com/
<img width="816" alt="スクリーンショット 2020-07-25 0.25.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/ce01692b-86b0-0684-fc1b-1f33e5fa7c81.png">

## Setup

```bash
$ composer require restcord/restcord
```

## Test

```test.php
$discord = new DiscordClient(['token' => config('services.discord.token')]);
$discord->channel->createMessage(['channel.id' => 613584569618399251, 'content' => 'Foo Bar Baz']);
exit;
```

<img width="341" alt="スクリーンショット 2020-07-25 0.36.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/2020777c-8b7b-9006-b30f-27a3caff68f4.png">

## チャンネル一覧の実装

```php
// controller
public function index()
{
    $client = new DiscordClient(['token' => config('services.discord.token')]);
    $channels = $client->guild->getGuildChannels(['guild.id' => 319818715971715073]);     
    return view('Channel.index', compact('channels'));
}
```

```php
// blade
@foreach($channels as $channel)
    <ul>
        <li>{{ $channel->name }}</li>
    </ul>
@endforeach
```

<img width="612" alt="スクリーンショット 2020-07-25 0.51.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/05100ee8-264f-22e3-4910-8ec6a62ab021.png">

## チャンネル詳細からメッセージ送れるようにする実装

```php
// index.blade.php
@foreach($channels as $channel)
    <ul>
        <li><a href="{{ route('channels.show', ['channel' => $channel->id]) }}">{{ $channel->name }}</a></li>
    </ul>
@endforeach
```

```php
// show.blade.php
<h2>Post Message</h2>
<form action="{{ route('channels.store') }}" method="post">
    {{ csrf_field() }}
    <input type="hidden" name="channel_id" value="{{ $channelModel->id }}">
    <textarea name="content"></textarea>
    <button type="submit">submit</button>
</form>

<h2>Get Messages</h2>

<ul>
@foreach($messages as $message)
    <li>{{ $message->author['username'] }}:{{ $message->content }}</li>
@endforeach
</ul>
```

```php
// controller
class ChannelController extends Controller
{
    /** @var DiscordClient */
    private $discordClient;

    public function __construct()
    {
        $this->discordClient = new DiscordClient(['token' => config('services.discord.token')]);
    }

    public function index()
    {
        $channels = $this->discordClient->guild->getGuildChannels(['guild.id' => 319818715971715073]);
        return view('Channel.index', compact('channels'));
    }

    public function show(int $channel)
    {
        $channelModel = $this->discordClient->channel->getChannel(['channel.id' => $channel]);
        $messages = $this->discordClient->channel->getChannelMessages(['channel.id' => $channel]);
        return view('Channel.show', compact('channelModel', 'messages'));
    }

    public function store()
    {
        $params = [
            "channel.id" => (int)request()->input('channel_id'),
            "content" => (string)request()->input('content')
        ];
        $this->discordClient->channel->createMessage($params);
        return redirect(route('channels.show', ['channel' => (int)$params['channel.id']]));
    }
}
```

<img width="612" alt="スクリーンショット 2020-07-25 1.43.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/ad848391-ad00-3f2c-f8c1-09641e269b6b.png">
<img width="1052" alt="スクリーンショット 2020-07-25 1.43.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/fd7689c8-9dde-abf0-64b3-adcde16e5ece.png">

## VCチャンネルに参加させて何か喋らせる

追記予定

## 成果物

チャンネル一覧
https://www.ta9to.com/chimney/channels

チャンネル詳細（メッセージ投稿フォーム）
https://www.ta9to.com/chimney/channels/732386754056683651