Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@masteralice3104

discord.js v12でVCの入退室に反応するbotを作るメモ

はじめに

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を見るとこんなことが書いてあります
image.png

これしか書いてないです。説明雑では?
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の動作に反応すれば完了です。

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What is going on with this article?