Discord.js执行/coderadio斜杠命令报读取voice属性未定义错误
Discord机器人
/coderadio命令报错修复 报错原因
两个核心问题直接触发报错,同时存在后续兼容隐患:
- 形参顺序完全不匹配调用逻辑:查看
index.js中交互事件的执行逻辑,非ban/userinfo命令触发时,给execute方法传参顺序为command.execute(interaction, player),第一个参数是斜杠交互对象,第二个是初始化完成的discord-player实例。但play-coderadio.js中定义的execute形参顺序为(client, message, args),运行时你命名为message的形参实际接收到的是player实例,该实例不存在member属性,因此访问message.member.voice时直接抛出undefined错误。 - 命令逻辑未适配斜杠命令规范:现有代码是旧版文本前缀命令的写法,所用的
message.channel.send、message.reply都是普通消息事件的API,斜杠命令的响应必须通过传入的interaction对象触发,就算修正参数顺序,也会出现交互超时、消息发送失败等问题。同时代码没有对接项目已初始化的player实例,后续开发停止播放命令时需要单独维护连接状态,和项目原有音乐逻辑不兼容。
修复方案
- 调整
execute方法的形参顺序,和入口文件的传参规则对齐 - 替换旧的消息响应逻辑为斜杠交互API,执行命令前先做延迟回复避免交互超时
- 复用项目已有的discord-player实例播放音频流,和原有音乐命令共用队列逻辑,降低后续停止命令的开发成本
- 修正权限校验、频道获取的取值路径,适配discord.js v13+版本的API规范
修复后完整play-coderadio.js代码
const { MessageEmbed } = require('discord.js') module.exports = { name: 'coderadio', description: 'play FCC Code Radio', async execute(interaction, player) { // 校验用户是否在语音频道 const voiceChannel = interaction.member.voice.channel; if(!voiceChannel) { return interaction.reply({ content: "你必须先加入一个语音频道才能使用该命令!", ephemeral: true }); } // 校验机器人语音权限 const permissions = voiceChannel.permissionsFor(interaction.client.user); if(!permissions.has('CONNECT') || !permissions.has('SPEAK')) { return interaction.reply({ content: "我缺少该语音频道的进入/发言权限!", ephemeral: true }); } try { // 延迟回复避免交互超时 await interaction.deferReply(); // 调用现有player实例播放电台流,复用音乐队列逻辑 await player.play(voiceChannel, "https://coderadio-relay-blr.freecodecamp.org/radio/8010/radio.mp3", { metadata: { channel: interaction.channel, requestedBy: interaction.user } }); // 构造播放成功提示 const embed = new MessageEmbed() .setTitle(`📻 freeCodeCamp Code Radio 已启动`) .setDescription(`正在向语音频道 **${voiceChannel.name}** 流式传输电台音频\n后续可使用停止命令终止播放`) return interaction.followUp({ embeds: [embed] }); } catch (err) { console.error('播放coderadio出错:', err); return interaction.followUp({ content: "启动电台播放时出现错误,请稍后重试", ephemeral: true }); } } }
注意事项
- 代码修改完成后,需要在服务器内发送
!deploy命令重新注册斜杠命令,否则Discord端缓存的旧命令配置不会更新 - 后续开发停止播放命令时,直接调用对应服务器player队列的
stop()方法即可,不需要单独维护语音连接状态 - 如果不想复用discord-player逻辑,自行实现语音连接时需要注意,discord.js v13之后语音功能需要单独安装
@discordjs/voice依赖,可执行npm i @discordjs/voice补装
内容的提问来源于stack exchange,提问作者rcfromcle
相关产品推荐
相关产品推荐

