Discord.js v12.5.3 mention prefix功能触发Cannot read property '0'报错求助
问题排查与修复方案
错误原因
你收到的报错:
(node:19812) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '0' of null
触发根源是String.prototype.match()在没有匹配到结果时会返回null,你的代码没有做空值判断就直接访问mentionPrefix[0],当用户使用普通前缀(比如s!help)发命令、没有@机器人时,就会抛出这个类型错误。
现存逻辑问题
- 前缀赋值逻辑错误:
&&运算符的特性会让你写的prefix = "s!" && mentionPrefix[0]强制取后面的mentionPrefix[0]值,普通前缀完全失效,同时空值访问直接触发报错 - 无空值校验:所有调用
mentionPrefix[0]的位置都没有提前判断匹配是否成功 - 前缀匹配逻辑错误:你需要的是「普通前缀/提及前缀二选一匹配」,而非同时满足两个条件
修复后完整代码
const {MessageEmbed} = require('discord.js') const client = require('../index') const db = require('quick.db') const dbx = require('xen.db') client.on('message', async (message) => { if(message.author.bot || message.channel.type === "dm") return; let prefix; // 优先取自定义前缀,没有就用默认s! let prefixess = await db.fetch(`simply_prefix_${message.guild.id}`) || "s!" const mentionPrefix = message.content.match(new RegExp(`^<@!?(${client.user.id})>`,'gi')) // 前缀判断:优先匹配提及前缀,匹配不到用普通前缀 if(mentionPrefix && mentionPrefix.length){ prefix = mentionPrefix[0] // 单独@机器人直接返回前缀提示 if(message.content.trim() === prefix){ const pingEmbed = new MessageEmbed() .setColor('YELLOW') .setDescription(`本服务器的命令前缀是:\`${prefixess} || @SimplyBot\`\n查看命令列表请发送:\`${prefixess}help\` 或 \`@SimplyBot help\`!`) return message.channel.send(pingEmbed) } }else{ prefix = prefixess } const messageArray = message.content.split(' '); const cmd = messageArray[0]; const args = messageArray.slice(1); if (!message.content.startsWith(prefix)) return; const commandfile = client.commands.get(cmd.slice(prefix.length).trim()) || client.commands.get(client.aliases.get(cmd.slice(prefix.length).trim())); if(commandfile){ if(commandfile.config.premium){ if(commandfile.config.premium === true){ const premium = dbx.fetch(`simply_premium`) || [] const expiry = dbx.fetch(`simply_premium_date_${message.guild.id}`) if(!premium.includes(message.guild.id)){ return message.reply(`这是高级版专属命令,你无权使用`) } if(expiry && Date.now() > expiry) { dbx.pull(`simply_premium`, message.guild.id) dbx.set(`simply_premium_date_${message.guild.id}`, 0) return message.reply(`你的服务器高级版已过期`) } commandfile.run(client, message, args, dbx, db) } } else { commandfile.run(client, message, args, dbx, db) } } })
额外优化说明
- 修正了高级版权限判断的逻辑顺序,避免高级版过期后还能执行一次命令的漏洞
- 修正了
includes调用顺序,避免数组为空时报错 - 给命令名匹配加了trim处理,避免多余空格导致匹配失败
内容的提问来源于stack exchange,提问作者SImplehDUde
相关产品推荐
相关产品推荐

