You need to enable JavaScript to run this app. 基于discord.js实现表情交互活动签到列表面板的bot开发求助
优惠活动
大模型
产品
解决方案
定价
更多

基于discord.js实现表情交互活动签到列表面板的bot开发求助

discord.js 可直接复用的交互嵌入式活动面板实现

零额外存储的核心逻辑

  • 直接复用discord.js自带的表情反应用户列表做统计,不需要搭建数据库,大幅降低实现复杂度
  • 用户添加/移除表情时自动触发面板刷新,实时更新参与人数和成员列表
  • 固定按「参与数/100」格式展示统计值,数值下方自动列出所有参与成员昵称

可直接抄用的代码

所有需要自定义的配置项单独放在最开头,修改内容只需要改动这部分,后续核心逻辑不需要调整,避免卡壳:

// 自定义配置区
const activityOptions = [
  { emoji: '👍', optionName: '确定参与' },
  { emoji: '👎', optionName: '不参与' },
  { emoji: '🤷', optionName: '待定' }
];
const MAX_PARTICIPANT_LIMIT = 100; // 固定显示的分母,修改数值直接改这里

发送活动面板的逻辑,直接接入你已有的斜杠命令触发流程即可:

// 触发后发送活动面板
async function launchActivityPanel(interaction) {
  // 初始化嵌入式面板
  const activityEmbed = new EmbedBuilder()
    .setTitle('活动参与统计')
    .setDescription('点击对应表情选择你的参与状态,统计值会实时更新');

  // 给每个选项加初始占位内容
  const initialFields = activityOptions.map(option => ({
    name: `${option.emoji} ${option.optionName}`,
    value: `0/${MAX_PARTICIPANT_LIMIT}\n暂无成员参与`
  }));
  activityEmbed.addFields(initialFields);

  // 发送面板,获取消息本体用于后续编辑
  const panel = await interaction.reply({
    embeds: [activityEmbed],
    fetchReply: true
  });

  // 给每个选项加上对应表情反应
  for (const option of activityOptions) {
    await panel.react(option.emoji);
  }
}

全局监听表情变化的逻辑,放在bot初始化完成后的事件监听块即可:

// 表情变化触发的统一处理逻辑(加/删表情都会触发)
async function refreshPanelOnReactionChange(reaction, user) {
  // 跳过非活动面板的消息,不做多余处理
  if (reaction.message.partial) await reaction.message.fetch();
  const matchedOption = activityOptions.find(opt => opt.emoji === reaction.emoji.toString());
  if (!matchedOption) return;
  // 跳过bot自身的反应,不把bot计入统计
  if (user.bot) return;

  // 拉取所有点击该表情的真实成员
  const reactionUsers = await reaction.users.fetch();
  const realParticipants = reactionUsers.filter(u => !u.bot);
  const participantCount = realParticipants.size;
  const participantList = realParticipants.map(u => u.globalName || u.username).join('\n') || '暂无成员参与';

  // 更新面板的对应字段,不改动其他选项的内容
  const currentEmbed = EmbedBuilder.from(reaction.message.embeds[0]);
  const targetFieldIndex = currentEmbed.data.fields.findIndex(field => field.name.startsWith(matchedOption.emoji));
  currentEmbed.data.fields[targetFieldIndex] = {
    name: `${matchedOption.emoji} ${matchedOption.optionName}`,
    value: `${participantCount}/${MAX_PARTICIPANT_LIMIT}\n${participantList}`
  };

  // 直接编辑原面板,不发新消息
  await reaction.message.edit({ embeds: [currentEmbed] });
}

// 同时绑定加表情、删表情的事件,保证实时更新
client.on('messageReactionAdd', refreshPanelOnReactionChange);
client.on('messageReactionRemove', refreshPanelOnReactionChange);

新手避坑提示

  • 运行前先去Discord开发者门户的bot设置页,打开「Server Members Intent」「Message Content Intent」两个权限开关,重启bot即可解决拉取反应用户报错的问题
  • 如果使用服务器自定义表情,只要把配置区里的emoji字符串换成对应表情的id即可,不需要修改核心逻辑
  • 全程不需要手动存储参与数据,所有数据来自Discord原生的反应记录,不会出现数据不同步的问题

内容的提问来源于stack exchange,提问作者Stribbits

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 16:36:05