質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
npm

npmは、Node Packaged Modulesの略。Node.jsのライブラリ・パッケージを管理できるツールです。様々なモジュールを簡単にインストールでき、自分でモジュールを作成し公開する際にも使用できます。

cron

cronは、Unix系OS上でデーモンプロセスとして動作する、スクリプトの自動実行が可能なジョブスケジューラです。

Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

3252閲覧

特定の時刻になったらボイスチャットから切断する

hinanon

総合スコア13

npm

npmは、Node Packaged Modulesの略。Node.jsのライブラリ・パッケージを管理できるツールです。様々なモジュールを簡単にインストールでき、自分でモジュールを作成し公開する際にも使用できます。

cron

cronは、Unix系OS上でデーモンプロセスとして動作する、スクリプトの自動実行が可能なジョブスケジューラです。

Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2021/10/27 16:43

#前提・実現したいこと
特定の時刻になったらそのサーバーのボイスチャットに接続しているメンバーを全員切断したい。

#発生している問題
特定の時刻になってもボイスチャットから切断されない。

#該当のソースコード

js

1client.on('ready', () => { 2 3 var cron = require('node-cron'); 4 5 cron.schedule('00 17 * * *', () => { 6 7 const guildID = 'ギルドID' 8 9 const guild = client.guilds.fetch(guildID).catch(console.error); 10 11 const vchannel = guild.channels.cache.filter(channel => channel.type === 'voice'); 12 13 const channel = guild.channels.cache.find(ch => ch.name === 'general'); 14 15 vchannel.members.forEach(member => { 16 if (member) member.voice.kick().catch(console.error); 17 console.log(member.id) 18 19 setTimeout(() => { 20 channel.send(`2時になったのでボイスチャットからキックしました(*'▽')`) 21 }, 500) 22 }); 23 }); 24});

#自分で調べたことや試したこと
ギルドIDを適当な数値を入れたらエラーが出たのでcronの指定時刻に動作することは確認できています。

#バージョン
discord.js: 12.5.2
node-cron: 3.0.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

require()はできるだけファイル冒頭でする

細かいことですが、そのファイルがどんな外部モジュールに依存しているかをファイル冒頭にまとめておくと見やすいので、require()はできるだけファイルの冒頭に書きましょう。

varconstにしています。

js

1const cron = require('node-cron') 2 3/* ... なんやかんやあって ... */ 4 5client.on('ready', () => { 6 /* ... いろいろする ... */ 7})

client.guilds.fetch(guildID)ではなくclient.guilds.cache.get(guildID)

client.guilds.fetch()は引数にサーバID(Snowflake)ではなくサーバオブジェクト(GuildResolvable)を渡さなくてはならないので、代わりにclient.guilds.cache.get(guildID)を使います。

js

1cron.schedule('00 17 * * *', async () => { 2 const guildID = 'ギルドID' 3 4 const guild = client.guilds.cache.get(guildID); 5 /* ...guildを使ってなにかする... */

guild.channels.cache.filter()Collectionを返す

Array.prototype.filter()と同じような関数で、返値はChannelではなくCollectionです。

そのため、各チャンネルのmembersプロパティを取得するにはCollection.each()しましょう。

js

1const vchannels = guild.channels.cache.filter(channel => channel.type === 'voice') 2 3vchannels.each(vchannel => 4 vchannel.members.each(/* ... */) 5)

ユーザをVoiceChannelから退出させる方法

いくつか方法があり、その中でもバージョンによって動くものと動かないものがあるようです。

member.voice.setChannel(null)member.setVoiceChannel(null)はメンバーのチャンネル情報をnullに設定することにより、ボイスチャンネルから退出させるというものです。

一方、member.voice.disconnect()member.voice.kick()は文字通りメンバーをボイスチャンネルから退出させるために用意された関数です。
バージョンによってdisconnect()が使える・使えない分かれるようですが、どのバージョンから使えるのかは残念ながらわかりません。kick()は公式ドキュメントから見つけることすらできませんでしたが、ユーザ発の情報では割とありましたので、昔からある方法なのかもしれません(この辺は伝聞になってしまいますが申し訳ない)。

【追記】
hinanonさんによると「await member.voice.kick().catch(console.error)にしたら動きました」とのことです。
以下のコードもその情報に合わせて修正しました。

member.voice.disconnect('理由')member.voice.kick()Promiseを返す 非同期関数 なので、awaitで処理が終わるまで以降のコードの実行を中断します。
awaitを使うにはそのコードが含まれる関数をasyncにしなければいけないので、そこも修正します。

また、細かいことですが、if文周りでバグが入りそうなコードになっている(おそらくmember == nullのときでもconsole.log(member.id)が実行される)ので{...}で範囲を明確にしました。
ifwhileなどは例え1行だとしてもif (...) {...}にしておくと意図しない動作を防げます。

vchannel.membersCollectionなので、forEach()ではなくeach()を使っています。

js

1vchannel.members.each(async member => { 2 if (member) { 3 // disconnect()を使う方法 4 await member.voice.disconnect(`2時になったのでボイスチャットからキックしました(*'▽')`).catch(console.error) 5 6 // kick()を使う方法 7 await member.voice.kick().catch(console.error) 8 9 console.log(member.id) 10 } 11})

channel.send()Promiseを返す

Promiseを返す関数は基本的にawaitして.catch()でエラー処理するようにしましょう。

なお、await member.voice.disconnect()するとdisconnect()の処理が終わるまでそれ以降のコードの実行を中断するので、その後にメッセージを送る場合もsetTimeout()disconnect()の処理が終わるまで待つ必要はありません。

js

1await member.voice.disconnect(`2時になったのでボイスチャットからキックしました(*'▽')`).catch(console.error) 2 3/* 処理待ちは必要ない */ 4await channel.send(`2時になったのでボイスチャットからキックしました(*'▽')`).catch(console.error)

こんな感じでしょうか。
一応、guild, vchannels, channelnullundefined, []だった場合のエラー処理をしていませんのでご注意ください。
ご参考まで。

投稿2021/10/27 19:38

編集2021/10/28 08:40
fj68

総合スコア752

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hinanon

2021/10/28 07:11

TypeError: member.voice.disconnect is not a function とエラーが出て実行できませんでした・・・
fj68

2021/10/28 07:56 編集

回答を編集しました。 上記回答の「ユーザをVoiceChannelから退出させる方法」にも書いたことですが、バージョンによって違うのか最新のドキュメントで検索してもVoiceState.kick()やVoiceChannel.kick()が見つからず…… いくつか試してみて「このバージョンでこの方法がうまくいった」というのがわかれば回答か質問にその旨記入いただけると後々同じような問題を抱えた人にとっても役立つので、よろしくお願いします。 一番肝心のところが伝聞形の情報になってしまい申し訳ないです。
hinanon

2021/10/28 08:35

わかりました。試してみます!
hinanon

2021/10/28 08:36

await member.voice.kick().catch(console.error)にしたら動きました!
fj68

2021/10/28 08:37

おお、そうなんですね! 動いたようで、よかったです。 その旨、回答に追記しておきますね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問