はじめに
discord.jsを使ったbotの資料はたくさんありますが、
- v12対応
- voiceStateUpdateを利用
- VCの入退室に関連した資料
というのが殆どなかったのでメモっときます。v11対応だったりErisだったりするとあるんだけどdiscord.js v12がいいんだよ!!
このページに載っている情報でなにができる?
- 入退室時、ミュートなどの状態を変更したときに関数を発火させることができる
- 状態を変化させたユーザやチャンネル、ギルド(サーバ)などの情報を取得することができる
環境
Node.js v14.17.0
discord.js v12.5.3
サンプルコード
// discord.js モジュールのインポート
const Discord = require('discord.js');
// Discord Clientのインスタンス作成
const client = new Discord.Client();
// トークンの用意
const discord_token = `hogehogehoge`; //ここは各自のトークンを入力
client.on("voiceStateUpdate", (oldState, newState) => {
if(newState && oldState){
//newState関係
console.log(`NEW:userid : ${newState.id}`); //ユーザID
console.log(`NEW:channelid: ${newState.channelID}`);//チャンネルID、nullならdisconnect
console.log(`NEW:guildid : ${newState.guild.id}`); //ギルドID
//oldState関係
console.log(`OLD:userid : ${oldState.id}`); //ユーザID
console.log(`OLD:channelid: ${oldState.channelID}`);//チャンネルID、nullならconnect
console.log(`OLD:guildid : ${oldState.guild.id}`); //ギルドID
if(oldState.channelID===newState.channelID){
//ここはミュートなどの動作を行ったときに発火する場所
concole.log(`other`);
}
if(oldState.channelID===null && newState.channelID != null){
//ここはconnectしたときに発火する場所
concole.log(`connect`);
}
}
if(oldState.channelID !=null && newState.channelID === null){
//ここはdisconnectしたときに発火する場所
console.log(`disconnect`);
}
}
}
});
// Discordへの接続
client.login(discord_token);
コード解説
##discord.jsを使うに当たって当然必要な物たち
// discord.js モジュールのインポート
const Discord = require('discord.js');
// Discord Clientのインスタンス作成
const client = new Discord.Client();
// トークンの用意
const discord_token = `hogehogehoge`; //ここは各自のトークンを入力
~~中略~~
// Discordへの接続
client.login(discord_token);
- この辺りはおまじない的役割
- token流出に注意しましょう
##voiceStateUpdate
client.on("voiceStateUpdate", (oldState, newState) => {
~~中略~~
});
このページの肝となる場所です。
voiceStateUpdateをdiscordより受信すると、この関数が動きます。
###voiceStateUpdateを受信する条件
botが参加しているサーバ(guild)で
- ユーザがVCに参加する
- ユーザがVCから退出する
- ユーザが各種ミュートをする
の模様。
###oldState,newStateとは何ぞや?
documentを見るとこんなことが書いてあります
これしか書いてないです。説明雑では?
oldStateが変化前の状態で、newStateが変化後の状態です。
VoiceState型でデータをくれるみたいですね。
###VoiceState型とは?
documentにはたくさん情報があるのですが、はっきり言って読みづらいですね。
今回は、
- 状態の変化したチャンネルID取得
- 状態の変化したサーバ(guild)のID取得
- 状態の変化したユーザID取得
この3つに絞って説明します。
//newState関係
console.log(`NEW:userid : ${newState.id}`); //ユーザID
console.log(`NEW:channelid: ${newState.channelID}`);//チャンネルID、nullならdisconnect
console.log(`NEW:guildid : ${newState.guild.id}`); //ギルドID
//oldState関係
console.log(`OLD:userid : ${oldState.id}`); //ユーザID
console.log(`OLD:channelid: ${oldState.channelID}`);//チャンネルID、nullならconnect
console.log(`OLD:guildid : ${oldState.guild.id}`); //ギルドID
ただ表示するだけの部分ですが、以下のように取得することができます。
oldState | newState | 備考 | |
---|---|---|---|
ユーザーID | oldState.id | newState.id | newState.guild.members.resolve(newState.id).user.username とかでユーザ名を取得できる。 |
チャンネルID | oldState.channelID | newState.channelID | nullになる場合あり。newState.channel.name とかでチャンネル名を取得できる。 |
ギルドID | oldState.guild.id | newState.guild.id | このIDでサーバごとの設定変更とか状態保持とかするといいかも |
さらに、oldStateとnewStateのchannelIDの状態を確認することで以下のように判別できます。
oldState.channelID | newState.channelID | 状態 |
---|---|---|
チャンネルID | チャンネルID | ミュートなどをした場合。 oldStateとnewStateでチャンネルIDが別IDとなっていると、VC間の移動を検出できるようです。 |
null | チャンネルID | 入室 |
チャンネルID | null | 退室 |
ということで、
if(oldState.channelID===newState.channelID){
//ここはミュートなどの動作を行ったときに発火する場所
concole.log(`other`);
}
if(oldState.channelID===null && newState.channelID != null){
//ここはconnectしたときに発火する場所
concole.log(`connect`);
}
}
if(oldState.channelID !=null && newState.channelID === null){
//ここはdisconnectしたときに発火する場所
console.log(`disconnect`);
}
}
このようにコードを書くことができます。
以上、実際にDiscordの動作に反応すれば完了です。