如何为Discord抽奖机器人实现离线可用的自更新Embed倒计时
需求说明
为开发中的Discord抽奖机器人Embed抽奖消息添加倒计时功能,需满足两个要求:
- 机器人离线时倒计时仍可自动更新
- 倒计时更新过程不会显示消息被编辑的标识
现有实现代码
const embed = new MessageEmbed(); embed.setAuthor({ name: `${message.guild.name} GiveAways!`, iconURL: `${message.guild.iconURL({ dynamic: true })}` }); embed.setThumbnail(`${message.guild.iconURL({ dynamic: true })}`); embed.setTitle(`${title.toUpperCase()}`); embed.setColor("BLURPLE"); embed.setDescription( ` **React With 🎉 To Enter!** **Ends In: ${time} ${}!** **Hosted By: ${message.author}!** ` ); embed.setFooter({ text: `${winnerCount.toString().slice(0, -1)} Winners | Ends` }); embed.setTimestamp(Date.now() + ms(duration)); const sentGiveaway = await channel.send({ content: "||@everyone|| **🥳 GIVEAWAY 🥳**", embeds: [embed] }); sentGiveaway.react("🎉");
变量说明
title:抽奖活动标题time:用户输入时长转换后的完整名称文本,例如4d转换为4 DayswinnerCount:抽奖的中奖人数duration:用户传入的时长参数Date.now() + ms(duration):抽奖活动的精确结束时间戳(毫秒级)
当前问题
目前使用embed.setTimestamp()仅能固定展示抽奖结束时间点,无法实现动态倒计时效果。观察到多款成熟抽奖机器人都实现了无需编辑消息即可自动更新、机器人离线也能正常运行的动态倒计时效果,求具体实现方案。
注:出于项目安全考虑,未提供完整项目代码。
实现方案
核心原理
你看到的无编辑、离线可用的动态倒计时,完全不需要机器人主动更新消息。这类效果用的是Discord官方自带的Unix时间戳动态渲染语法,所有倒计时计算、实时更新都由用户本地的Discord客户端完成,和机器人运行状态无关,也不会触发消息编辑标识。
Discord动态时间戳基础语法为<t:秒级Unix时间戳:显示格式>,要实现自动倒计时,只需要用R作为显示格式参数,即<t:结束时间戳:R>,客户端会自动渲染为动态更新的相对时间,比如in 3 days、in 1 hour、in 2 minutes,活动结束后会自动切换为x minutes ago样式,全程不需要机器人做任何后续操作。
代码修改步骤
你现有代码已经拿到了毫秒级的结束时间戳,只需要做两处调整即可:
- 将毫秒级时间戳转为秒级(Discord时间戳要求传秒级Unix时间戳,直接用毫秒值会显示成几十年后的错误时间)
- 把描述里写死的结束时间文本替换为动态时间戳语法,不需要额外加定时任务、不需要后续编辑消息。
修改后的核心代码示例:
// 计算秒级结束时间戳 const endTimestamp = Math.floor((Date.now() + ms(duration)) / 1000); const embed = new MessageEmbed(); embed.setAuthor({ name: `${message.guild.name} GiveAways!`, iconURL: `${message.guild.iconURL({ dynamic: true })}` }); embed.setThumbnail(`${message.guild.iconURL({ dynamic: true })}`); embed.setTitle(`${title.toUpperCase()}`); embed.setColor("BLURPLE"); embed.setDescription( ` **React With 🎉 To Enter!** **Ends In: <t:${endTimestamp}:R>(精确结束时间:<t:${endTimestamp}:F>)** **Hosted By: ${message.author}!** ` ); embed.setFooter({ text: `${winnerCount.toString().slice(0, -1)} Winners` }); // 原setTimestamp逻辑可按需保留,不影响倒计时效果 const sentGiveaway = await channel.send({ content: "||@everyone|| **🥳 GIVEAWAY 🥳**", embeds: [embed] }); sentGiveaway.react("🎉");
可选时间戳格式参数
你可以根据需求搭配其他格式参数,组合展示时间信息:
t:短时间格式,例如9:00 PMT:长时间格式,例如9:00:00 PMd:短日期格式,例如04/20/2024D:长日期格式,例如April 20, 2024f:短日期+时间(默认格式),例如April 20, 2024 9:00 PMF:长日期+时间,例如Saturday, April 20, 2024 9:00 PMR:相对时间(动态倒计时/已结束时长),例如in 2 days、5 minutes ago
效果说明
- 倒计时由用户本地Discord客户端自动刷新,机器人发完消息就算下线,倒计时也会正常运行
- 全程不需要机器人编辑消息,完全不会出现消息已编辑的标识
- 时间会自动适配用户本地时区,不会出现跨时区时间显示错误的问题
内容的提问来源于stack exchange,提问作者DarkWarrior
相关产品推荐
相关产品推荐

