NodeJS下Discord Bot无法实时读取更新后JSON文件的问题
解决Discord.js机器人无法实时读取更新后JSON的问题
嘿,我来帮你搞定这个问题!你遇到的核心问题有两个:一是Node.js缓存了初始加载的JSON文件,导致修改后不生效;二是原代码里的!spotify命令循环逻辑有bug,还有你尝试用fs读取时没处理好解析和错误。
先理清楚问题根源
- require的缓存机制:如果之前你是用
const ftpr = require('./buyers.json')加载的JSON,Node.js会把这个文件的内容缓存到内存里,之后修改文件内容也不会自动更新ftpr的值——除非重启机器人,这就是为什么修改ID后命令还在用旧数据的原因。 - fs读取的错误:你说出现
TypeError: Cannot read property 'buyers' of undefined,大概率是读取文件后没正确解析成JSON对象,或者文件路径写错了,导致ftpr不是预期的包含buyers数组的对象。 - 循环逻辑的坑:原代码里的for循环,只要第一个buyer的ID不匹配,就直接break并提示用户没有订阅,这意味着后面的ID根本不会被检查——比如用户是第二个ID,也会被错误拒绝。
下面是修复后的完整代码
我把所有问题都修正了,还加了错误处理,确保机器人稳定运行:
const Discord = require('discord.js'); const fs = require('fs'); const path = require('path'); // 用path模块处理文件路径,避免环境差异导致的路径错误 const client = new Discord.Client(); const TOKEN = "***********"; const PREFIX = "!"; // 定义JSON文件的绝对路径,__dirname是当前脚本所在的文件夹 const BUYERS_FILE = path.join(__dirname, 'buyers.json'); client.on("ready", function () { console.log("Ready!"); }); client.on("message", function (message) { if (message.author.equals(client.user)) return; if (!message.content.startsWith(PREFIX)) return; const args = message.content.substring(PREFIX.length).split(" "); switch (args[0]) { case "rules": const rulesEmbed = new Discord.RichEmbed() .setTitle("Ruleset") .addField("Where is my order?", "There's only one proper way to receive an order and help. It's the command `.ticket`") .addField("Why AZATEJ is such a bitch?", "If my status is 'don't disturb' and hue is way more red than green it means I have a reason to do so, I'm not a dick, but I receive a shitload of messages daily with stupid questions.") .addField("Don't ask stupid questions", "Stupid doesn't mean basic, we are up to help you but before you contact anyone read the explanation documents twice and use a ticket.") .setColor(0x00FFFF) .setFooter("This message is cool !") .setThumbnail(message.author.avatarURL); message.channel.send(rulesEmbed); break; case "spotify": const userId = message.author.id; let buyersData; try { // 每次执行命令时,重新读取并解析JSON文件,确保拿到最新内容 const fileContent = fs.readFileSync(BUYERS_FILE, 'utf8'); buyersData = JSON.parse(fileContent); } catch (error) { console.error('读取或解析buyers.json出错:', error); message.channel.send('服务器内部出错啦,请稍后再试~'); return; // 出错就终止命令执行 } // 检查用户ID是否在订阅列表里,用some方法更简洁高效 const hasValidSubscription = buyersData.buyers.some(buyer => buyer.id === userId); if (hasValidSubscription) { const spotifyEmbed = new Discord.RichEmbed() .setTitle("Spotify") .addField("Username", "testsda@yahoo.com") .addField("Password", "ithastobe8") .setColor(0x00FFFF) .setFooter("Sincerely, LajgaardMoneyService") .setThumbnail(message.author.avatarURL); message.author.send(spotifyEmbed); console.log(`${message.author.username}(${userId}) 刚刚使用了!spotify命令`); } else { message.channel.send(`${message.author} 你没有有效的订阅哦,获取新订阅后才能使用这个命令!`); } break; } }); client.on('guildMemberAdd', function(member) { console.log(`用户 ${member.id} 加入了服务器!`); const welcomeRole = member.guild.roles.find("name", "Google!"); if (welcomeRole) { // 加个判断,避免角色不存在导致报错 member.addRole(welcomeRole); } else { console.log(`找不到名为"Google!"的角色`); } }); client.login(TOKEN);
关键修改的细节解释
- 实时读取JSON:把JSON读取逻辑放到
!spotify命令内部,每次用户调用命令时都重新读取文件,这样修改JSON后,下一次命令就能拿到最新的ID列表,完全不用重启机器人。 - 错误处理:用
try/catch包裹文件读取和解析过程,就算文件损坏或者路径错了,机器人也不会崩溃,还会给用户友好的提示。 - 修复循环逻辑:用
Array.some()替代原来的for循环,这个方法会遍历整个数组,只要找到匹配的ID就返回true,解决了原循环只检查第一个ID的问题,代码也更简洁。 - 绝对路径:用
path.join(__dirname, 'buyers.json')生成绝对路径,不管机器人在哪个目录运行,都能正确找到JSON文件,避免相对路径的坑。 - 额外优化:给
guildMemberAdd事件加了角色存在的判断,避免角色被删除后机器人报错;还修正了规则里的一些拼写错误,让消息更规范。
这样修改后,你随时修改JSON里的ID,下次用户调用!spotify命令就会用新的校验规则,完全不用重启机器人啦!
内容的提问来源于stack exchange,提问作者Oscar
相关产品推荐
相关产品推荐

