Node.jsでユーザ動作に反応するDiscordのBotを作ってみた

# [Discord Advent Carendar 2017](https://qiita.com/advent-calendar/2017/discord) ３日目
こういった文を書くのがはじめてなのでお手柔らかにお願いします:bow:
# はじめに
DiscordのBotを作るためにいろいろ記事をあさってみた所、
コメントに反応する例や、コマンドを実装する例は見つかったのですが、
ユーザの動作に反応する例が見つからなかったのでその簡単な実装例を記そうと思います。
# 環境
- Node.js: 8.9.1
- [eris](https://github.com/abalabahaha/eris/): 0.8.1

Node.jsの8系がLTSになったので使ってみました。
また、DiscordのAPIのNode.js wrapperとして[eris](https://github.com/abalabahaha/eris/)を使っています。
# Botの準備
https://discordapp.com/developers/applications/me
↑のリンクの**New App**からBotを作成します。
![スクリーンショット 2017-12-02 15.46.52.png](https://qiita-image-store.s3.amazonaws.com/0/160452/8fd440dc-d733-1a5d-aa2d-ee31c2ab8866.png)

次に**Create a Bot User**をクリック
![スクリーンショット 2017-12-02 15.48.08.png](https://qiita-image-store.s3.amazonaws.com/0/160452/c7f92438-4aee-8e0f-754b-a6ad38ec9185.png)

次に↓のリンクの**CLIENT_ID**の部分を作成したBotのIDに置き換えて押してください。
https://discordapp.com/oauth2/authorize?&client_id=CLIENT_ID&scope=bot&permissions=0
その後Botを追加するサーバを選択してください。

そして、**Bot**の**Token**を取得してください。このTokenが必要となります。
![スクリーンショット 2017-12-02 15.55.54.png](https://qiita-image-store.s3.amazonaws.com/0/160452/20656ae1-3130-e2a0-5f04-43774a0a97d1.png)

# Botを作る
## 目的
- ユーザのゲーム開始/終了のイベントを取得する
- 通話が開始/終了したイベントを取得する

今回は↑のイベントをトリガーにして、メッセージを投稿するというBotを作ろうと思います。
## コード
```js:bot.js
const Eris = require('eris');
// BOT_TOKENには先程取得したTokenを入れてください。
const bot = new Eris("BOT_TOKEN");

// Botの準備が整ったらコンソールに通知
bot.on('ready', () => {
  console.log('Ready!');
});

// presenceUpdate というイベントは
// ユーザまたはrelationship(そのままですみません…)のステータスが変更された時、
// またはゲームが変更された時に発火します。
bot.on('presenceUpdate', (other, oldPresence) => {

  // Botが投稿するためのTextChannelを取得
  // TextChannelが１つの場合を想定しています。
  // 複数ある場合はchannel.id等で判別できます。
  const textChannel = other.guild.channels.find((channel) => channel.type === 0);
  const userName = other.user.username;

  if (other.game) { // ゲームが始まった時
    const gameName = other.game.name;
    bot.createMessage(textChannel.id, `${userName} が ${gameName} をはじめました`);
  } else if (oldPresence.game) { // ゲームを終了した時
    const gameName = oldPresence.game.name;
    bot.createMessage(textChannel.id, `${userName} が ${gameName} を終了しました`);
  }

});

// voiceChannelJoin というイベントは
// ユーザが音声チャンネルに参加した時に発火します。
bot.on('voiceChannelJoin', (member, newChannel) => {
  const textChannel = newChannel.guild.channels.find((channel) => channel.type === 0);
  const msg = `${member.username} が通話をはじめました`;
  bot.createMessage(textChannel.id, msg);
});

// voiceChannelLeave というイベントは
// ユーザが音声チャンネルから退出した時に発火します。
bot.on("voiceChannelLeave", (member, oldChannel) => {
  const textChannel = oldChannel.guild.channels.find((channel) => channel.type === 0);
  const msg = `${member.username} が通話をやめました`;
  bot.createMessage(textChannel.id, msg);
});

// BotをDiscordに接続します
bot.connect();
```
2017/12/06 修正 voiceChannelLeave の変数名を修正しました。
# まとめ
ユーザがゲームを始めたり、通話を開始したらメッセージを投稿するBotを作ってみました。
今回はイベント発火時にユーザ名やゲーム名を取得していますが、他にもゲームの開始時間を取得してプレイ時間を出したり、ユーザのIDを取得してメンションを飛ばしたりすることができるので試してみてください。

初めての記事なので読みにくいとは思いますが手助けになれば幸いです。
間違っている点や改善点等あればコメントにて教えていただける助かります。

# 補足
erisは[ドキュメント](https://abal.moe/Eris/docs/getting-started)がしっかりしているので、見ればだいたい分かると思います。
Botが取得できるイベントは[こちら](https://abal.moe/Eris/docs/Client)にあります。

[はじめに](#はじめに)でも書きましたが、ユーザのコメントに反応する例や、任意のプレフィックスをつけてコマンドを作成する例は[erisのexample](https://github.com/abalabahaha/eris/tree/master/examples)に例がありますのでそちらをご覧ください。