Discord.js消息收集器计时器重置及结束阶段回复问题求助
Discord.js消息收集器计时器重置及结束阶段回复问题求助
嘿,我看你碰到了两个关于Discord.js消息收集器的小问题:一是想让收集器在用户5分钟未输入时自动结束,且用户输入后能重置计时器;二是收集器结束时没法发送新回复的困扰。咱们一步一步来解决~
问题1:实现「用户5分钟未输入自动结束,输入后重置计时器」
你当前代码里的time: 300000确实设置了5分钟超时,但这个计时器是从收集器创建时开始计算的——哪怕用户中途输入了消息,到点还是会自动结束,这显然不是你想要的效果。另外代码里的max: 1会让收集器只收一条消息就停止,得先把这个去掉,才能实现无限收集直到超时或用户主动停止。
解决办法很简单:每次收集到用户消息时,调用收集器的resetTimer()方法,把计时器从当前时间重新开始计算。同时可以保留你想要的「输入stop手动结束」的逻辑,具体代码修改如下:
const collector = interaction.channel.createMessageCollector({ filter: (msg) => msg.author.id === interaction.user.id, time: 300000, // 5分钟超时,单位毫秒 }); collector.on("collect", (msg) => { // 先判断用户是否输入stop,手动终止收集器 if (msg.content.toLowerCase() === "stop") { collector.stop("user-initiated"); return; } textToSpeech(msg.content); collector.resetTimer(); // 关键:每次收到消息就重置计时器 });
这样一来,只要用户一直在输入,计时器就会不断重置;一旦用户超过5分钟没说话,收集器就会自动触发end事件。
问题2:收集器结束时发送回复的限制
你遇到的「一个交互只能回复一次」是Discord的规则——interaction.reply()只能调用一次,但我们可以用interaction.followUp()来发送后续消息,它会和最初的回复显示在同一个对话串里,完美解决这个问题。
修改end事件的代码,把原来的interaction.reply()换成interaction.followUp(),还可以根据收集器结束的原因(用户主动停止/超时)发送不同提示,体验更好:
collector.on("end", (collected, reason) => { let endMessage; switch (reason) { case "user-initiated": endMessage = "已根据你的指令停止echo功能,我不会再重复你的输入啦~"; break; case "time": endMessage = "5分钟没收到你的输入,echo功能已自动停止。"; break; default: endMessage = "echo功能已结束。"; } interaction.followUp(endMessage); });
完整修改后的代码
这里给你整合了所有优化点的完整代码,还把判断频道类型的数字换成了更易读的ChannelType枚举:
import { SlashCommandBuilder, ChannelType } from "discord.js"; import { command, textToSpeech } from "../../utils"; const meta = new SlashCommandBuilder() .setName("echo") .setDescription("I'll say in voice whatever you type."); export default command(meta, ({ interaction }) => { if (!interaction.channel) { return interaction.reply(`You can't use this command here.`); } // 用ChannelType枚举替代数字0,代码更易维护 if (interaction.channel.type !== ChannelType.GuildText) { return interaction.reply(`I can't read your messages here.`); } // 初始回复里加上stop提示,让用户知道怎么主动终止 interaction.reply(`Now I'll say everything you type. Type "stop" to end early.`); const collector = interaction.channel.createMessageCollector({ filter: (msg) => msg.author.id === interaction.user.id, time: 300000, // 5分钟超时 }); collector.on("collect", (msg) => { if (msg.content.toLowerCase() === "stop") { collector.stop("user-initiated"); return; } textToSpeech(msg.content); collector.resetTimer(); // 重置计时器 }); collector.on("end", (collected, reason) => { let endMsg; switch (reason) { case "user-initiated": endMsg = "You've stopped the echo command. I won't repeat your messages anymore."; break; case "time": endMsg = "5 minutes have passed without any input. The echo command has ended automatically."; break; default: endMsg = "The echo command has ended."; } interaction.followUp(endMsg); }); });
备注:内容来源于stack exchange,提问作者Ckemill
相关产品推荐
相关产品推荐

