Discord.js声音,玩家完成事件

3

我正在尝试学习discord.js,所以我想了解音乐机器人的工作原理。下面的代码是我的尝试,一切都正常,但是我在队列方面遇到了问题。

我无法获取player.on "finish"或"end"事件。因此,当歌曲结束时,我想调用递归方法来播放一首歌曲,但我不知道如何获得正确的事件。

我尝试使用player.on(AudioPlayerStatus.Idle)事件并从中创建一些内容,但效果不太好。

如果有人对我做错了什么或者如何改进下面的代码有任何建议,我会非常感激。

const queue = new Map();
module.exports = {
    name: "play",
    aliases: ["skip", "stop", "leave"],
    async execute(message, args, cmd, client, Discord) {

        const voiceChannel = message.member.voice.channel;
        if (!voiceChannel) {
            return message.channel.send({
                content: "You need to be in a channel to execute this command!",
            });
        }

        const permissions = voiceChannel.permissionsFor(message.member);
        if (!(permissions.has('CONNECT')) || !(permissions.has('SPEAK'))) {
            return message.channel.send({
                content: "You don't have the correct permissions!",
            });
        }

        const serverQueue = queue.get(message.guild.id);

        if (cmd == "play") {
            if (!(args.length)) {
                return message.channel.send({
                    content: "Invalid song link!",
                });
            }

            let song = {};

            if (ytdl.validateURL(args[0])) {
                const songInfo = await ytdl.getInfo(args[0]);
                song = { title: songInfo.videoDetails.title, url: songInfo.videoDetails.video_url }
            } else {
                const videoFinder = async (query) => {
                    const videoResult = await ytSearch(query);
                    return (videoResult.videos.length > 1) ? videoResult.videos[0] : null;
                }

                const video = await videoFinder(args.join(" "));
                if (video) {
                    song = { title: video.title, url: video.url }
                } else {
                    message.channel.send({
                        content: `No video results found!`
                    })
                }
            }

            if (!(serverQueue)) {
                const queueConstructor = {
                    voiceChannel: voiceChannel,
                    textChannel: message.channel,
                    connection: null,
                    player: null,
                    songs: [],
                }

                queue.set(message.guild.id, queueConstructor);
                queueConstructor.songs.push(song);

                try {
                    const connection = await joinVoiceChannel({
                        channelId: message.member.voice.channel.id,
                        guildId: message.member.voice.channel.guild.id,
                        adapterCreator: message.member.voice.channel.guild.voiceAdapterCreator,
                    });
                    queueConstructor.connection = connection;

                    const player = createAudioPlayer({
                        behaviors: {
                            noSubscriber: NoSubscriberBehavior.Pause
                        }
                    });
                    queueConstructor.player = player;

                    videoPlayer(message.guild, queueConstructor.songs[0]);
                } catch (error) {
                    queue.delete(message.guild.id);

                    message.channel.send({
                        content: `There was an error connecting!`
                    })

                    throw error;
                }
            } else {
                serverQueue.songs.push(song);

                console.log(serverQueue.songs);

                return message.channel.send({
                    content: `${song.title} added to the queue!`
                })
            }
        } else if (cmd == "skip") {
            // TODO
        } else if (cmd == "leave") {
            // TODO
        }

    }

}

const videoPlayer = async (guild, song) => {
    const songQueue = queue.get(guild.id);

    if (!(song)) {
        songQueue.player.stop();
        songQueue.connection.destroy();
        queue.delete(guild.id);
        return;
    }

    const stream = await ytdl(song.url, { filter: "audioonly" });
    const songStream = await (createAudioResource(stream));

    const subscription = songQueue.connection.subscribe(songQueue.player);
    const dispatcher = songQueue.player.play(createAudioResource(stream)).on("finish", () => {
        songQueue.songs.shift();
        songQueue.playing = false;
        videoPlayer(guild, songQueue.songs[0]);
        songQueue.textChannel.send({
            content: `Now playing: ${song.title}`
        });
    });
}
1个回答

4
player.addListener("stateChange", (oldOne, newOne) => {
    if (newOne.status == "idle") {
        console.log("The song finished");
    }
});

使用事件stateChange。当语音状态从旧状态变为新状态时调用它。(例如:播放 -> 空闲)
新状态 { status: "playing | idle | buffering | ..." }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接