Discord.js机器人开发:如何检测外部读取的变量是否发生变化
现有代码存在的核心问题
- 未声明的
html_prev属于全局隐式变量,在Discord.js多用户并发触发指令的场景下会出现数据串扰,完全无法区分不同用户的上次抽奖状态 - 条件判断使用单等号赋值而非比较运算符,
html = html_prev || html_prev == undefined的逻辑完全偏离预期,每次判断都会直接覆盖当前值 - 奖励计算逻辑缺失:仅把拉取到的文件内容展示出来,没有将抽奖金额累加到用户数据库余额中,最终展示的余额始终是未更新的旧值
- 缺少请求异常捕获:fetch请求遇到网络超时、域名访问异常时,会抛出未捕获的Promise错误,导致指令执行无响应
外部文件变化检测的正确实现方案
状态存储改造
不要依赖全局变量存储状态,直接复用已经引入的quick.db针对每个用户单独存状态,彻底解决多用户数据串扰问题:
- 存储
last_spin_result_${用户ID}:记录该用户上次已经领取过的转盘结果内容 - 无需额外维护全局的状态缓存,每次指令触发时直接拉取最新文件内容做比对即可
检测逻辑流程
- 拼对应用户的结果文件链接,拉取文本内容
- 识别到404占位内容时,直接提示用户先完成转盘操作
- 拉取到正常结果文本后,和数据库中存储的该用户上次已领取的结果做严格相等比较:
- 两者相等:说明当前文件内的结果已经被领取过,提示用户重新转动转盘
- 两者不等:说明网页刚写入了新的抽奖结果,解析结果对应的奖励金额,累加到用户的余额上
- 奖励发放完成后,立刻把数据库中存储的该用户已领取结果更新为当前文件的最新内容,避免后续重复领取
修正后的核心代码
const fetch = require("node-fetch") const db = require("quick.db"); const err_404 = '<html><head><meta http-equiv="refresh" content="0;http://errors.biz.nf/404.php" /></head><body></body></html>' module.exports = { config: { name: "spin", aliases: ['spi', 'spinn', 'sp'], category: 'economy', description: 'spin wheel', usage: ' ', accessableby: "everyone" }, run: async (bot, message, args) => { const userFileName = message.member.user.tag.replace("#", ""); const spinPageLink = "http://miers.c1.biz/spin/index.html"; const userResultFileLink = `http://miers.c1.biz/w/p/${userFileName}.txt`; try { const res = await fetch(userResultFileLink); const fileContent = await res.text(); if (fileContent === err_404) { return message.channel.send(`${message.member.user.tag},你还没有完成转盘抽奖哦\n抽奖页面:${spinPageLink}`); } const lastClaimedResult = db.fetch(`last_spin_result_${message.author.id}`); if (fileContent === lastClaimedResult) { return message.channel.send(`你已经领取过本轮转盘奖励啦,请重新转动转盘后再来领取`); } const rewardAmount = parseInt(fileContent.trim()); const currentBalance = db.fetch(`money_${message.author.id}`) || 0; const newBalance = currentBalance + rewardAmount; db.set(`money_${message.author.id}`, newBalance); db.set(`last_spin_result_${message.author.id}`, fileContent); message.channel.send(`成功领取转盘奖励:${rewardAmount} 金币\n当前新余额:${newBalance}`); } catch (err) { console.error("转盘结果拉取失败:", err); message.channel.send("暂时无法读取你的转盘结果,请稍后再试"); } } }
注意:如果你的转盘结果文本不是纯数字格式,需要根据实际写入的文本格式调整结果解析的逻辑,不要直接硬套
parseInt
内容的提问来源于stack exchange,提问作者my profile
相关产品推荐
相关产品推荐

