0

我使用 Node.js 和 YTDl-Core 为 Discord 编写了一个音乐机器人。我可以播放 YouTube 上的每一首歌曲,但有一个限制,如果我播放的频道的歌曲/视频很少,它会将其添加到队列中,但无法播放并且机器人离开 VoiceChannel,但我没有得到一个错误,如果我不尝试使用它完全工作的机器人,那么只要我坚持这个限制。这是我的代码:

const Discord = require('discord.js')
const fs = require('fs')
const ytdl = require('ytdl-core')
const ffmpeg = require('ffmpeg')
const { debug, Console } = require('console')
const config = JSON.parse(fs.readFileSync('config.json', 'utf8'))
const ytapi3 = config.GoogleApiYT3
const search = require('youtube-search')
const { getInfo } = require('ytdl-core')
const queue = new Map()

var client = new Discord.Client()

//setting status
client.on('ready', () => {
    console.log("Logged in as", client.user.username, "...")
    client.user.setPresence({
        status: config.status,
        activity: {
            name: config.activity,
            type: 'STREAMING',
            url: config.streamingURL
        }
    })
})

//musicbot
client.on('message', async message => {
    if(message.author.bot) return // test if bot has written this message
    if(!message.channel.id == config.botcommandsChannelID) return //test if message is in botcommands channel
    if(!message.content.startsWith(config.prefix)) return // test if prefix is used

    const args = message.content.substring(config.prefix.length).split(" ") // split arguments into args[]-list and cut the prefix out
    const voiceChannel = message.member.voice.channel
    const serverqueue = queue.get(message.guild.id)

    //test if user has permissions to use command
    if(config.UseDJRole == "true") {
        if(message.member.roles.cache.has(config.DJroleID) || message.member.roles.cache.has(config.ModeratorRoleID) || message.member.user.id == config.owner){
        }else{
            return sendEmbed(message.channel, config.ErrorColor, "Error", config.NoPermissionsToUseThisCommand)
        }
    }

    if(!voiceChannel) return sendEmbed(message.channel, config.ErrorColor, "Error", config.InvalidVoiceChannel_404) //testing if user is in voiceChannel

    if(message.content.startsWith(config.prefix + config.PlayCommand)){ //Play-case
        const permission = voiceChannel.permissionsFor(message.client.user)
        if(!permission.has('CONNECT')) sendEmbed(message.channel, config.ErrorColor, "Error", config.NoPermissionsToJoinVC)
        if(!permission.has('SPEAK')) sendEmbed(message.channel, config.ErrorColor, "Error", config.NoPermissionsToSpeakInVC)

        var song = {
            url: null,
            title: null
        }

        //get link "song"
        if(args.length >= 2){
            if(ytdl.validateURL(args[1])){
                args.shift()
                try{
                    song = await searchOnYT(args[0], message.channel);
                }catch(error){
                    return console.log("returned")
                }
            } else{
                args.shift()
                const vidSearchLink = args.join(' ')
                try{
                    song = await searchOnYT(vidSearchLink, message.channel);
                } catch(error){
                    return console.log("returned")
                }
            }
        }else {
            return sendEmbed(message.channel, config.ErrorColor, "Error", config.NoArgs)
        }

        if(!serverqueue){
            const queueConstruct = {
                voiceChannel: voiceChannel,
                connection: null,
                songs: [],
                volume: config.musicDefaultVolume,
                playing: true
            }
            queue.set(message.guild.id, queueConstruct)

            queueConstruct.songs.push(song)

            try {
                queueConstruct.connection = await voiceChannel.join()
                play(message.guild, queueConstruct.songs[0], message)
            } catch (error) {
                console.log(error)
                queue.delete(message.guild.id)
                return sendEmbed(message.channel, config.ErrorColor, "Error", config.ErrorDuringConnectingToVoiceChannel)
            }
        }else{
            if(voiceChannel.id != queue.get(message.guild.id).voiceChannel.id){
                return sendEmbed(message.channel, config.ErrorColor, "Error", config.InvalidVoiceChannel_400)
            } else{
                try {
                    _url = song.url
                    //add to queue
                    serverqueue.songs.push(song)
                    return sendEmbed(message.channel, config.MusicEmbedColorHEX, "Adding", song.title + config.addedToQueue, _url)
                } catch (error) {
                    console.log(error)
                    return sendEmbed(message.channel, config.ErrorColor, "Error", config.ErrorDuringAddingToQueue)
                }
            }  
        }
        return undefined
    }else if(message.content.startsWith(config.prefix + config.StopCommand) || message.content.startsWith(config.prefix + config.LeaveCommand)){
        if(!serverqueue) return sendEmbed(message.channel, config.ErrorColor, "Error", config.NoMusicInQueue) //test if something playing
        if(voiceChannel.id != queue.get(message.guild.id).voiceChannel.id) return sendEmbed(message.channel, config.ErrorColor, "Error", config.InvalidVoiceChannel_400) //test if you are in one voice channel with the bot
        serverqueue.songs = []
        serverqueue.connection.dispatcher.end()
        return sendEmbed(message.channel, config.MusicEmbedColorHEX, "Stopping", config.stoped)
    }else if(message.content.startsWith(config.prefix + config.PauseCommand)){
        if(!serverqueue) return sendEmbed(message.channel, config.ErrorColor, "Error", config.NoMusicInQueue) //test if something playing
        if(voiceChannel.id != queue.get(message.guild.id).voiceChannel.id) return sendEmbed(message.channel, config.ErrorColor, "Error", config.InvalidVoiceChannel_400) //test if you are in one voice channel with the bot
        if(!serverqueue.playing) return sendEmbed(message.channel, config.ErrorColor, "Error", config.AllredyPaused)
        serverqueue.playing = false
        serverqueue.connection.dispatcher.pause()
        return sendEmbed(message.channel, config.MusicEmbedColorHEX, "Pausing", config.Paused)
    }else if(message.content.startsWith(config.prefix + config.ResumeCommand)){
        if(!serverqueue) return sendEmbed(message.channel, config.ErrorColor, "Error", config.NoMusicInQueue) //test if something playing
        if(voiceChannel.id != queue.get(message.guild.id).voiceChannel.id) return sendEmbed(message.channel, config.ErrorColor, "Error", config.InvalidVoiceChannel_400) //test if you are in one voice channel with the bot
        if(serverqueue.playing) return sendEmbed(message.channel, config.ErrorColor, "Error", config.AllredyPlaying)
        serverqueue.playing = true
        serverqueue.connection.dispatcher.resume()
        return sendEmbed(message.channel, config.MusicEmbedColorHEX, "Resuming", config.Resumed)
    }else if(message.content.startsWith(config.prefix + config.SkipCommand)){
        if(!serverqueue) return sendEmbed(message.channel, config.ErrorColor, "Error", config.NoMusicInQueue) //test if something playing
        if(voiceChannel.id != queue.get(message.guild.id).voiceChannel.id) return sendEmbed(message.channel, config.ErrorColor, "Error", config.InvalidVoiceChannel_400) //test if you are in one voice channel with the bot
        serverqueue.connection.dispatcher.end()
        return console.log("skipped")
    }else if(message.content.startsWith(config.prefix + config.QueueCommand)){
        if(!serverqueue) return sendEmbed(message.channel, config.ErrorColor, "Error", config.NoMusicInQueue) //test if something playing
        if(voiceChannel.id != queue.get(message.guild.id).voiceChannel.id) return sendEmbed(message.channel, config.ErrorColor, "Error", config.InvalidVoiceChannel_400)//test if you are in one voice channel with the bot
        if(serverqueue){
            if(serverqueue.playing){
                var status = config.Resumed
            }else{
                var status = config.Paused
            }
            const embedMessage = new Discord.MessageEmbed()
                .setColor(config.MusicEmbedColorHEX)
                .setTitle("Queue | volume(" + serverqueue.volume + "/5)" + status)
            for (let index = 0; index < serverqueue.songs.length; index++) {
                embedMessage.addField(serverqueue.songs[index].title, serverqueue.songs[index].url)
            }
            return message.channel.send(embedMessage)
        } else{
            return sendEmbed(message.channel, config.ErrorColor, "Error", config.NoMusicInQueue)
        }
    }else if(message.content.startsWith(config.prefix + config.VolumeCommand) || message.content.startsWith(config.prefix + config.VCommand)){
        if(!serverqueue) return sendEmbed(message.channel, config.ErrorColor, "Error", config.NoMusicInQueue) //test if something playing
        if(voiceChannel.id != queue.get(message.guild.id).voiceChannel.id) return sendEmbed(message.channel, config.ErrorColor, "Error", config.InvalidVoiceChannel_400)//test if you are in one voice channel with the bot
        if(!args[1]){
            if(serverqueue.volume == 0){
                var v = config.VMute
            }else{
                var v = config.VUnMute
                for (let index = 0; index < serverqueue.volume; index++) {
                    v = v + config.VSymbol
                }
            }
            return sendEmbed(message.channel, config.MusicEmbedColorHEX, "Volume (" + serverqueue.volume + "/5)", v) //return volume
        }
        if(args[1] == "+" || args[1] == "plus"){
            if(serverqueue.volume == 5) return sendEmbed(message.channel, config.ErrorColor, "Error", config.MaxVolume)
            serverqueue.volume = serverqueue.volume + 1
            if(serverqueue.volume == 0){
                var v = config.VMute
            }else{
                var v = config.VUnMute
                for (let index = 0; index < serverqueue.volume; index++) {
                    v = v + config.VSymbol
                }
            }
            serverqueue.connection.dispatcher.setVolumeLogarithmic(serverqueue.volume / 5)
            return sendEmbed(message.channel, config.MusicEmbedColorHEX, "Volume (" + serverqueue.volume + "/5)", v) //return volume
        }else if(args[1] == "-" || args[1] == "minus"){
            if(serverqueue.volume == 0) return sendEmbed(message.channel, config.ErrorColor, "Error", config.MinVolume)
            serverqueue.volume = serverqueue.volume - 1
            if(serverqueue.volume == 0){
                var v = config.VMute
            }else{
                var v = config.VUnMute
                for (let index = 0; index < serverqueue.volume; index++) {
                    v = v + config.VSymbol
                }
            }
            serverqueue.connection.dispatcher.setVolumeLogarithmic(serverqueue.volume / 5)
            return sendEmbed(message.channel, config.MusicEmbedColorHEX, "Volume (" + serverqueue.volume + "/5)", v) //return volume
        }else{
            return sendEmbed(message.channel, config.ErrorColor, "Error", config.VSyntax) //return volume
        }
        
    }
})

function sendEmbed(_channel, _Color, _Title, _Description, _URL){
    const embedMessage = new Discord.MessageEmbed()
        .setColor(_Color)
        .setTitle(_Title)
        .setDescription(_Description)
        .setURL(_URL);
    _channel.send(embedMessage)

}

function searchOnYT(searchstring, _channel){
    var opts = {
        maxResults: 1,
        key: config.GoogleApiYT3,
        type: 'video'
    }
    return new Promise((resolve, reject) => {
        search(searchstring, opts, function(err, results) {
            if(err) reject(err);

            if(results) {
                const r = results[0]
                u = r.link
                t = r.title.replaceAll("&quot;", '"').replaceAll("&amp;", "&")
                var ar = {
                    url: u,
                    title: t
                }
                resolve(ar)
            }
            else {
                sendEmbed(_channel, config.ErrorColor, "Error", config.NoResultsFound+ searchstring);
                var e = new Error(["no videofound"])
                reject(e)
            }
          })
    });

}

function play(guild, song, message){
    const serverqueue = queue.get(guild.id)

    if(!song){
        serverqueue.voiceChannel.leave()
        queue.delete(guild.id)
        client.user.setPresence({
            status: config.status,
            activity: {
                name: config.activity,
                type: 'STREAMING',
                url: config.streamingURL
            }
        })
        return (message.channel, config.MusicEmbedColorHEX, "Stopping", config.PlayedQueueTrough)
    }

    client.user.setPresence({
        status: config.status,
        activity: {
            name: "Music",
            type: 'STREAMING',
            url: serverqueue.songs[0].url
        }
    })

    

    const dispatcher = serverqueue.connection.play(ytdl(song.url))
    .on('finish', () => {
        serverqueue.songs.shift()
        play(guild, serverqueue.songs[0], message)
    })
    .on('error', error => {
        console.log(error)
    })
    dispatcher.setVolumeLogarithmic(serverqueue.volume / 5)

    sendEmbed(message.channel, config.MusicEmbedColorHEX, "Playing", config.startPlaying + serverqueue.songs[0].title, serverqueue.songs[0].url)
}

client.login(config.token)
4

1 回答 1

0

我不知道为什么 ytdl 不能播放很多歌曲,但我用 trycatch 修复了它,这样它就不会让我的机器人崩溃,有趣的是我不想播放的视频不是私人的或者很长,由于某种原因,ytdl 有很多视频问题

于 2021-01-24T09:06:09.970 回答