如何在Discord.JS中修复循环命令

时间:2019-05-27 12:03:40

标签: javascript discord.js

我在Discord Bot上有一个Looping命令,您可以在其中重复在语音通道中播放歌曲。尽管当我运行命令时,它会显示一条消息,提示它会循环播放当前歌曲:

Screenshot on Loop Command

但是,当歌曲结束时(应该再次重复播放),机器人将与语音通道断开连接。它使用YTDL-Core。关于如何解决这个任何想法? Repeat.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"
}

Queue.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"
}

Main.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);

谢谢

1 个答案:

答案 0 :(得分:0)

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

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

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