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

Discord Advent Carendar 2017 3日目

こういった文を書くのがはじめてなのでお手柔らかにお願いします:bow:

はじめに

DiscordのBotを作るためにいろいろ記事をあさってみた所、
コメントに反応する例や、コマンドを実装する例は見つかったのですが、
ユーザの動作に反応する例が見つからなかったのでその簡単な実装例を記そうと思います。

環境

  • Node.js: 8.9.1
  • eris: 0.8.1

Node.jsの8系がLTSになったので使ってみました。
また、DiscordのAPIのNode.js wrapperとしてerisを使っています。

Botの準備

https://discordapp.com/developers/applications/me
↑のリンクのNew AppからBotを作成します。
スクリーンショット 2017-12-02 15.46.52.png

次にCreate a Bot Userをクリック
スクリーンショット 2017-12-02 15.48.08.png

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

そして、BotTokenを取得してください。このTokenが必要となります。
スクリーンショット 2017-12-02 15.55.54.png

Botを作る

目的

  • ユーザのゲーム開始/終了のイベントを取得する
  • 通話が開始/終了したイベントを取得する

今回は↑のイベントをトリガーにして、メッセージを投稿するというBotを作ろうと思います。

コード

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が1つの場合を想定しています。
  // 複数ある場合は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はドキュメントがしっかりしているので、見ればだいたい分かると思います。
Botが取得できるイベントはこちらにあります。

はじめにでも書きましたが、ユーザのコメントに反応する例や、任意のプレフィックスをつけてコマンドを作成する例はerisのexampleに例がありますのでそちらをご覧ください。