Discord Bot执行!play命令报错voiceChannel.join is not afunction求助
问题原因
- 你当前使用的discord.js为v14及以上版本,v13版本后官方就将语音相关功能从主库拆分到了独立的
@discordjs/voice包,旧版本的voiceChannel.join()方法已经被完全移除,调用不存在的方法自然会抛出类型错误。 - 客户端初始化时缺少
GUILD_VOICE_STATES语音状态意图,无法正常获取语音频道状态、执行加入操作。 - v14版本后读取消息内容需要额外开启
MessageContent意图,你当前的配置也缺少该配置,且未在Discord开发者后台开启对应权限开关的话也会影响命令识别。
解决方案
步骤1:安装必要依赖
执行以下命令安装语音相关依赖包:
npm install @discordjs/voice opusscript ffmpeg-static
步骤2:修正主文件配置
修改主文件的客户端初始化逻辑,补全所需意图:
const { Client, IntentsBitField } = require('discord.js'); const prefix = '!'; const fs = require('fs'); const { join } = require('path'); const client = new Client({ intents: [ IntentsBitField.Flags.Guilds, IntentsBitField.Flags.GuildMessages, IntentsBitField.Flags.GuildVoiceStates, IntentsBitField.Flags.MessageContent ] }); client.commands = new Discord.Collection(); const commandFiles = fs.readdirSync('./commands/').filter(file => file.endsWith('.js')); for(const file of commandFiles){ const command = require(`./commands/${file}`); client.commands.set(command.name, command); } client.once('ready', () => { console.log('Mein Mussig Bot ist nun online!'); }); client.on('messageCreate', message =>{ if(!message.content.startsWith(prefix) || message.author.bot) return; const args = message.content.slice(prefix.length).split(/ +/); const command = args.shift().toLowerCase(); if(command === 'ping'){ client.commands.get('ping').execute(message,args); } else if (command === 'play'){ client.commands.get('play').execute(message,args); } else if (command === 'stop'){ client.commands.get('stop').execute(message,args); } }); client.login('token')
同时需要前往Discord开发者平台的Bot管理页面,开启Message Content Intent权限开关。
步骤3:重写play.js语音逻辑
替换原有play.js的代码为适配v14版本的写法:
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus } = require('@discordjs/voice'); const ytdl = require('ytdl-core'); const ytSearch = require('yt-search'); module.exports = { name: 'play', description: 'Joins and plays a video from youtube', async execute(message, args) { const voiceChannel = message.member.voice.channel; if (!voiceChannel) return message.channel.send('You need to be in a channel to execute this command!'); const permissions = voiceChannel.permissionsFor(message.client.user); if (!permissions.has('CONNECT')) return message.channel.send('You dont have the correct permissions'); if (!permissions.has('SPEAK')) return message.channel.send('You dont have the correct permissions'); if (!args.length) return message.channel.send('You need to send the second argument!'); const validURL = (str) =>{ var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/; return regex.test(str); } // 初始化音频播放器 const player = createAudioPlayer(); // 加入语音频道 const connection = joinVoiceChannel({ channelId: voiceChannel.id, guildId: voiceChannel.guild.id, adapterCreator: voiceChannel.guild.voiceAdapterCreator, }); connection.subscribe(player); // 播放结束自动退出 player.on(AudioPlayerStatus.Idle, () => { connection.destroy(); message.channel.send('leaving channel'); }); // 捕获播放错误 player.on('error', error => { console.error(error); message.channel.send('播放出错,请重试'); connection.destroy(); }); if(validURL(args[0])){ const stream = ytdl(args[0], {filter: 'audioonly', highWaterMark: 1<<25}); const resource = createAudioResource(stream); player.play(resource); await message.reply(`:thumbsup: Now Playing ***Your Link!***`) return } 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){ const stream = ytdl(video.url, {filter: 'audioonly', highWaterMark: 1<<25}); const resource = createAudioResource(stream); player.play(resource); await message.reply(`:thumbsup: Now Playing ***${video.title}***`) } else { message.channel.send('No video results found'); connection.destroy(); } } }
内容的提问来源于stack exchange,提问作者Jona
相关产品推荐
相关产品推荐

