discord.js v13获取指定用户最后消息的代码异常排查
问题定位
你的日期返回错误、出现未来日期的问题和if (msg.author.id === array_of_users[i])判断无关,核心是3个硬伤:
- 变量作用域污染:代码里的
x、old_date、year、monthC、dayNum都没有在单个用户的循环内初始化,遍历完第一个用户后这些变量会残留之前的计算结果,后续所有用户的计算都基于脏数据运行,跨用户的时间值混在一起比对,自然会出现乱值、未来日期。比如第一个用户匹配到当日消息后,x会一直等于1,后续用户循环永远不会走第一条匹配消息的初始化逻辑,直接用之前留存的当日日期做基准,这就是大部分没发过言的用户也返回当日日期的直接原因。 - 日期比对逻辑完全错误:你把时间转成
toDateString()后拆分年、月、日单独逐层比大小的逻辑存在先天缺陷,比如同一年的10月1日和9月30日,比对到日期层时1<30,代码会直接取9月30日作为更新日期,完全忽略10月比9月更晚的前提,结果必然出错。实际上根本不需要手动拆分日期,直接比较createdTimestamp的数值大小即可,时间戳数值越大代表时间越晚。 - API使用不符合预期:discord.js v13中
channel.messages.fetch()不传参数时,默认只会拉取对应频道最新的25条消息,不会拉取全量频道历史;同时拉取消息失败时你只打印错误,没有跳过后续逻辑,会直接触发messages.each的调用报错。
修复实现
直接基于时间戳做比对,每个用户独立初始化状态变量,修正后代码如下:
for (let i = 0; i < array_of_users.length; i++) { const targetUserId = array_of_users[i]; // 每个用户单独初始化最新时间戳,初始值为0 let latestTimestamp = 0; for (const channel of message.guild.channels.cache.values()) { // 只遍历有权限访问的文本类频道,排除语音、分类、频道目录等非文本频道 if (!channel.isText() || !channel.viewable) continue; try { // 拉取频道最新消息,单次最多拉100条,需要更早历史需要自行实现分页 const messages = await channel.messages.fetch({ limit: 100 }); messages.each(msg => { if (msg.author.id === targetUserId) { // 直接比时间戳,更大就更新 if (msg.createdTimestamp > latestTimestamp) { latestTimestamp = msg.createdTimestamp; } } }); } catch (e) { // 无权限拉取的频道直接跳过 console.log(`跳过频道${channel.id},拉取失败:`, e); } } if (latestTimestamp === 0) { console.log(`用户${targetUserId}未找到可查询到的发言记录`); } else { const latestDate = new Date(latestTimestamp); // 按需要格式化日期,示例输出 年-月-日 console.log(`${latestDate.getFullYear()}-${String(latestDate.getMonth()+1).padStart(2, '0')}-${String(latestDate.getDate()).padStart(2, '0')}`); } }
注意:受Discord API限制,无分页的单次拉取只能拿到频道最新的最多100条消息,如果需要检索全服务器全历史的用户最后发言,需要按频道做消息分页拉取,会消耗大量API配额,建议按需使用。
内容的提问来源于stack exchange,提问作者PackOf20
相关产品推荐
相关产品推荐

