首页 > 解决方案 > 如何修复 Discord.JS 中的循环命令

问题描述

我的 Discord Bot 上有一个循环命令,您可以在其中重复语音频道中的歌曲。虽然当我运行命令时,它会显示一条消息,表明它将循环当前歌曲:

循环命令截图

但是当歌曲结束时(它应该再次重复自己),机器人会断开与语音通道的连接。它使用 YTDL-Core。关于如何解决这个问题的任何想法?重复.JS

let { RichEmbed } = require('discord.js')
const config = require('../../config.json')

exports.run = async(client, msg, args) => {
  const serverQueue = client.queue.get(msg.guild.id);
  if (!msg.member.voiceChannel) return msg.channel.send('You are not in a voice channel!');
  if(!serverQueue) return msg.channel.send('Not playing anything right now');
  if(serverQueue.voiceChannel.id !== msg.member.voiceChannel.id) return msg.channel.send(`You must be in **${serverQueue.voiceChannel.name}** to loop the queue`);
  serverQueue.loop = !serverQueue.loop;
  client.queue.set(msg.guild.id, serverQueue);
  if(serverQueue.loop) return msg.channel.send('** Repeated current queue!**');
  return msg.channel.send('** Unrepeated current queue!**');
}




exports.conf = {
    aliases: ['loop'],
    cooldown: "3"
}

exports.help = {
    name: "repeat",
    description: "Repeat the queue",
    usage: "repeat"
}

队列.JS

const { RichEmbed } = require('discord.js');
const { chunk } = require('../../util.js');

exports.run = async (client, msg, args) => {
    try{
        const serverQueue = client.queue.get(msg.guild.id);
        if(!serverQueue) return msg.channel.send('**Music  |** There is no music playing!\n\nPlay some music with **n!play <YouTube URL>** or **n!play <word>**.');
        let queues = [];
        serverQueue.songs.forEach((x, i) => {
            if(i !== 0){
                queues.push(x);
            }
        });
        const embed = new RichEmbed()
    .setColor('0xd677ff');
        if(!queues || queues.length < 1) return msg.channel.send(`**Music  |** **Now playing »** **${serverQueue.songs[0].title}**`, {embed: embed.setDescription('**Music  |** **There are no songs in the queue**')});
        if(queues.length > 10){
            let index = 0;
            queues = queues.map((x, i) => `\`${i +1}\`. __**[${x.title}](${x.url})**__ **by** *${msg.author.username}*`);
            queues = chunk(queues, 10);
      embed.setAuthor('Music ', 'https://i.imgur.com/s6OpKNC.jpg')
            embed.setDescription(queues[index].join('\n'));
            embed.setFooter(`Page ${index+1} of ${queues.length}`);
            const queuesMess = await msg.channel.send(`**Music  |** **Now playing »** ${serverQueue.songs[0].title}`, {embed: embed});
            await queuesMess.react('⬅');
      await queuesMess.react('');
            await queuesMess.react('➡');
      awaitReactions();
            function awaitReactions(){
                const filter = (rect, usr)=> ['⬅', '➡'].includes(rect.emoji.name) && usr.id === msg.author.id;
                queuesMess.createReactionCollector(filter, {time: 30000, max: 1})
                .on('collect', col => {
          if(col.emoji.name === '') return queuesMess.delete();
                    if(col.emoji.name === '⬅') index--;
                    if(col.emoji.name === '➡') index++;
                    index = ((index % queues.length) + queues.length) % queues.length;
                    embed.setAuthor('Music ', 'https://i.imgur.com/s6OpKNC.jpg')
          embed.setDescription(queues[index].join('\n'));
                    embed.setFooter(`Page ${index+1} of ${queues.length}`);
                    queuesMess.edit(`**Music  |** **Now playing »** ${serverQueue.songs[0].title}`, {embed: embed});
                    return awaitReactions();
                });
            }
        }else{
            embed.setDescription(queues.map((x, i) => `\`${i +1}\`. __**[${x.title}](${x.url})**__ **by** *${msg.author.username}*`).join('\n'));
            return msg.channel.send(`**Music  |** **Now playing »** ${serverQueue.songs[0].title}`, {embed: embed});
        }
    }catch(e){
        return msg.channel.send(`**Music  |** **Error Occured** :( \`\`\`${e.stack}\`\`\`try again later`);
    }
}

exports.conf = {
    aliases: [],
    cooldown: "3"
}

exports.help = {
    name: "queue",
    description: "Show music queue in this server",
    usage: "queue"
}

主.JS

const Discord = require('discord.js')
const YouTube = require('simple-youtube-api');
const ytdl = require('ytdl-core');
const queue = new Map();
const client = new Discord.Client({disableEveryone: true});
const api = require("./app");
const fs = require('fs' );
let config = require('./config.json');
var servers = {};
let prefix = config.prefix;
const youtube = new YouTube(config.youtube_api);
const {Util, RichEmbed } = require('discord.js')
const stations = require('./stations.json')
const SBL = require("spacebots");
const DiscordBotListAPI = require('dbl-api');
const DBL = require("dblapi.js");
const dbl = new DBL('DBL CODE',client);
const Owner = config.Owner;
const util = require('./util.js')
const { get } = require('node-superfetch');
const { load } = require('cheerio');
const number = ['1⃣', '2⃣', '3⃣', '4⃣', '5⃣', '6⃣', '7⃣', '8⃣', '9⃣'];
var guild = {};
client.config = config;
client.util = util
client.queue = queue
client.on("ready", () => {
console.log(`Starting Nate Bot Version » 5.0`)
})

client.config = config;


fs.readdir("./events/", (err, files) => {
  if (err) return console.error(err);
  files.forEach(file => {
    const event = require(`./events/${file}`);
    let eventName = file.split(".")[0];
    client.on(eventName, event.bind(null, client));
  });
}); 

client.commands = new Discord.Collection();

    fs.readdir('./commands/', (err, categories) => {
        if (err) console.log(err);
        console.log(`NateBot » Found total ${categories.length} category.`);
        categories.forEach(category => {
            fs.readdir(`./commands/${category}`, (err, files) => {
                console.log(`NateBot » Found total ${files.length} command from ${category}.`)
                if (err) console.log(err);
                let commands = new Array();
                files.forEach(file => {
                    //delete require.cache[require.resolve(`./commands/${category}/${file}`)];
                    if (!file.endsWith('.js')) return;
                    let prop = require(`./commands/${category}/${file}`);
                    let cmdName = file.split('.')[0];
                   client.commands.set(cmdName, prop)
                })
            })
        })
    })



/*
  fs.readdir("./commands/admin/", (err, files) =>{
    if(err) return console.error(err);
    files.forEach(file => {
      if(!file.endsWith(".js")) return;
      let props = require(`./commands/admin/${file}`);
      let commandName = file.split(".")[0];
      client.commands.set(commandName, props);
    });
  });*/

exports.handleVideo = handleVideo
exports.queue = queue;
exports.youtube = youtube;
exports.queue = queue
exports.youtube = youtube;
  exports.ytdl = ytdl;
  exports.guild = guild;
  exports.config = config;

  client.on("message", async message =>{
 if(message.author.bot) return;
  if(message.channel.type === "dm") return;


    var args2 = message.content.substring(config.prefix.length).split(" ");
    if (!message.content.startsWith(config.prefix)) return;
  var searchString = args2.slice(0).join(' ');
  var url = args2[1] ? args2[1].replace(/<(.+)>/g, '$1') : '';
  var serverQueue = queue.get(message.guild.id);
    switch (args2[0].toLowerCase()) {
      case "skip":
    if (!message.member.voiceChannel) return message.channel.send(' **Music  |** You must connect to a Voice Channel.');
    if (!serverQueue) return message.channel.send('**Music  |** There is no music playing!\n\nPlay some music with **n!play <YouTube URL>** or **n!play <word>**.');
    serverQueue.connection.dispatcher.end('NateBot » Skip command has been used!');
    const embed = new Discord.RichEmbed()
      .setColor('#0xa8a8a8')
      .setAuthor('Music ', 'https://i.imgur.com/Fm1edxi.png')
      .setDescription('Song Successfully Skipped ⏩')
      message.channel.send({embed});      
        return undefined; 
        break;
      case "np":
    if (!serverQueue) return message.channel.send('**Music  |** There is no music playing!\n\nPlay some music with **n!play <YouTube URL>** or **n!play <word>**.');

        let nowplayingemb = new Discord.RichEmbed()
    .setColor('#0x76d6ff')
    .setAuthor('Music ', 'https://i.imgur.com/Fm1edxi.png')
    .setThumbnail("https://thumbs.gfycat.com/UnkemptWhiteKakapo-small.gif")
    .setDescription('**Now Playing** ')
    .addField('Song Name', `**${serverQueue.songs[0].title}**`, true)

    return message.channel.send(nowplayingemb);
break;
 case "queue":
    if (!serverQueue) return message.channel.send('**Music  |** There is no music playing right now!\n\nPlay some music with **n!play <YouTube URL>** or **n!play <word>**.');
        let queueemb = new Discord.RichEmbed()
      .setAuthor('Music ', 'https://i.imgur.com/s6OpKNC.jpg')
        .setTitle(`**Queue for ${message.guild.name}**`)
        .setDescription(`${serverQueue.songs.map(song => `**»** [${song.title}](https://www.youtube.com/watch?v=${song.id}})`).join('\n')}`)
        .setColor(`0xd677ff`)
    return message.channel.send(queueemb)
break;   
 case "leave":
    if (!message.member.voiceChannel) return message.channel.send('**Music  |** You must connect to a Voice Channel.');
        let stopemb = new Discord.RichEmbed()
        .setColor(0xff7777)
    .setAuthor(`Music `, 'https://i.imgur.com/Fm1edxi.png')
    .setDescription("Successfully Disconnected... ❌");
    message.guild.me.voiceChannel.leave();
  return message.channel.send(stopemb)
  break;
}
  })

async function handleVideo(video, message, voiceChannel, playlist = false) {
  var serverQueue = queue.get(message.guild.id);
 // console.log(video);
  var song = {
    id: video.id,
    title: video.title,
    url: `https://www.youtube.com/watch?v=${video.id}`,
    channel: video.channel.title,
    durationm: video.duration.minutes,
    durations: video.duration.seconds,
    durationh: video.duration.hours,
    publishedAt: video.publishedAt,
  };
  if (!serverQueue) {
    var queueConstruct = {
      textChannel: message.channel,
      voiceChannel: voiceChannel,
      connection: null,
      songs: [],
      volume: 5,
      playing: true,
      loop: true
    };
    queue.set(message.guild.id, queueConstruct);

    queueConstruct.songs.push(song);

    try {
      var connection = await voiceChannel.join();
      var listener = await voiceChannel.join();
      connection.on('error', console.error);
      queueConstruct.connection = connection;
      play(message.guild, queueConstruct.songs[0]);
    } catch (error) {
      queue.delete(message.guild.id);
      return message.channel.send(`**Music  |** **Error Occured** ${error}`);
    }
  } else { 
    serverQueue.songs.push(song);
    //console.log(serverQueue.songs);
    if (playlist) return undefined;

    let queueemb = new Discord.RichEmbed()
    .setAuthor('Music ', 'https://i.imgur.com/s6OpKNC.jpg')
    .setTitle(`**Song Successfully Queued!** `)
    .setColor(`#0xd677ff`)
    .addField(`**Uploader**`, `${song.channel}`, true)
    .addField(`**Video ID**`, song.id , true)
    .setFooter(`Published » ${song.publishedAt}`)
    .addField(`**Duration**`, `**\`${song.durationh}\`** Hours, **\`${song.durationm}\`** Minutes and **\`${song.durations}\`** Seconds`, true)
    .setDescription(`[${song.title}](https://www.youtube.com/watch?v=${song.id}})`)
    .setThumbnail(`https://i.ytimg.com/vi/${song.id}/sddefault.jpg`)
    .setColor(`0xd677ff`)
    return message.channel.send(queueemb).then(msg => {
      message.delete(10000)
    })
  }
  return undefined;
}
  function play(guild, song) {
  var serverQueue = queue.get(guild.id);

  if (!song) {
    serverQueue.voiceChannel.leave();
    queue.delete(guild.id);
    return;
  }
  //console.log(serverQueue.songs);

  const dispatcher = serverQueue.connection.playStream(ytdl(song.url))

  .on('end', reason => {
      if (reason === 'NateBot » Stream is not generating quickly enough.') console.log('NateBot » Song ended.');
      else console.log(reason);
      serverQueue.songs.shift();
      play(guild, serverQueue.songs[0]);
    })
  .on('error', error => console.error(error));
  dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
    let playingemb = new Discord.RichEmbed()
    .setAuthor('Music ', 'https://i.imgur.com/s6OpKNC.jpg')
    .setTitle(`**Now Playing!** `)
    .setColor(`0x76d6ff`)
    .addField(`**Uploader**`, `${song.channel}`, true)
    .addField(`**Video ID**`, song.id , true)
    .setFooter(`Published » ${song.publishedAt}`)
    .addField(`**Duration**`, `**\`${song.durationh}\`** Hours, **\`${song.durationm}\`** Minutes and **\`${song.durations}\`** Seconds`, true)
    .setThumbnail(`https://i.ytimg.com/vi/${song.id}/sddefault.jpg`)
    .setDescription(`[${song.title}](https://www.youtube.com/watch?v=${song.id}})`)

    serverQueue.textChannel.send(playingemb);

}
// Optional events
dbl.on('posted', () => {
  console.log('Server count posted!');
  console.log('NateBot » Server count posted!');
})

client.login(config.Token);
dbl.on('error', e => {
 console.log(`Oops! ${e}`);
 console.log(`NateBot » Oops! ${e}`);
})

  api.startApp(client);

client.login(config.Token);

谢谢

标签: javascriptdiscord.js

解决方案


尽管您正在设置队列的循环选项,但我看不到您在其他任何地方使用它。使队列重复的一个简单解决方案是将结束的歌曲再次添加到队列的末尾。例如...

if (serverQueue.loop === true) serverQueue.songs.push(serverQueue.songs.shift());
else serverQueue.songs.shift();
play(guild, serverQueue.songs[0]);

如果队列应该循环,上面的代码会从数组的开头删除元素并将其添加到末尾。这样,它将继续按顺序重复歌曲。如果队列不应该被循环,它只是删除第一首歌曲,就是这样。


推荐阅读