嘿,
我正在构建一个 Discord Bot,用于使用 Node.js 和 Discord.js 进行一些练习。使用此机器人,您可以执行 ?audio audio 命令,它会重现音频。
我想设置机器人在 20 秒不播放任何内容后离开语音频道。我用函数 setTimeout() 做到了,但是当我想听另一个音频时,机器人在音频结束之前离开了频道。
问题出在 setTimeout() 上,但不知道如何解决。
这是我的代码。
stack uninstall
如果需要整个项目,由EnderF5027上传到GitHub,“KoalaBot” (可能代码很丑,我正在学习,如果您愿意,可以给我一些建议:D)
有人可以帮我吗? 谢谢
答案 0 :(得分:2)
我附上了我的代码。
我不处理文件库,只处理带有 ytdl 的 youtube。
所以,问题可能会有所不同。
我使用 Map()
Object 处理加入的频道。
// message.guild.id = '1234567812345678'
const queue = new Map();
// 1. set new queue
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
search: [],
volume: 5,
playing: true,
leaveTimer: null /* 20 seconds in question */
};
queue.set('1234567812345678', queueContruct);
// 2. get queueContruct from queue
const serverQueue = queue.get('1234567812345678');
if(!serverQueue) { /* not exist */ }
// 3. delete from queue
queue.delete('1234567812345678');
当播放列表为空时,我用 setTimeout
设置计时器
并在新播放列表出现时取消设置 clearTimeout
。
下面是我的一段代码。
我希望这会有所帮助。
const Discord = require('discord.js');
const bot = new Discord.Client();
const queue = new Map();
const prefix = "?"; // this prefix is in Question.
bot.on("message", async message => {
// if direct-message received, message.guild could be null
// Not handle that case.
const serverQueue = queue.get(message.guild.id);
if(message.content.startsWith(`${prefix}audio`)) {
execute(message, serverQueue);
}
});
// I assume user message is "?audio audioName"
function execute(message, serverQueue) {
const audioName = message.content.split(' ')[1]; // "audioName"
// check user who send message is in voiceChannel
const voiceChannel = message.member.voice.channel;
if(!voiceChannel) {
return message.channel.send("YOU ARE NOT IN VOICE CHANNEL");
}
// check permission
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has("CONNECT") || !permissions.has("SPEAK")) {
return message.channel.send("PERMISSION ERROR");
}
/*
I handle only songs with google youtube api
So, I skip how to get & push song information
*/
if(!serverQueue) {
// create new serverQueue
const queueContruct = {
textChannel: message.channel,
voiceChannel: voiceChannel,
connection: null,
songs: [],
search: [],
volume: 5,
playing: true
};
queue.set(message.guild.id, queueContruct);
// "song" value is one of play list in my case
// var song = {title: 'audioName', url: 'youtube-url'};
queueContruct.songs.push(song);
try {
var connection = await voiceChannel.join();
queueContruct.connection = connection;
playStart(message.guild, queueContruct.songs[0]);
} catch (err) {
queue.delete(message.guild.id);
return message.channel.send(err);
}
}
else { // exist serverQueue
// "song" value is one of play list in my case
// var song = {title: 'audioName', url: 'youtube-url'};
serverQueue.songs.push(song);
if(serverQueue.songs.length == 1) {
playStart(message.guild, serverQueue.songs[0]);
}
}
}
function play(guild, song) {
const serverQueue = queue.get(guild.id);
if(!song) {
if(serverQueue.songs.length == 0) {
serverQueue.leaveTimer = setTimeout(function() {
leave_with_timeout(guild.id);
}, 20 * 1000); // 20 seconds is for follow question
}
return;
}
// clear timer before set
try {
clearTimeout(serverQueue.leaveTimer);
} catch(e) {
// there's no leaveTimer
}
const dispatcher = serverQueue.connection
.play(ytdl(song.url))
.on('finish', () => {
serverQueue.songs.shift(); // pop front
play(guild, serverQueue.songs[0]); // play next
})
.on('error' error => console.log(error));
dispatcher.setVolumeLogarithmic( 1 );
serverQueue.textChannel.send(`Play Start ${song.title}`);
}
function leave_with_timeout(guild_id) {
const serverQueue = queue.get(guild_id);
if(serverQueue) {
serverQueue.textChannel.send(`20 seconds left. Bye!`);
serverQueue.voiceChannel.leave();
queue.delete(guild_id);
}
}