You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.js决斗机器人开发问题:仅允许被挑战者接受决斗

解决Discord.js决斗机器人仅允许被挑战者确认的问题

嘿,我完全懂你现在的窘境——本来想做一个只有被挑战者能确认的决斗系统,结果现在只有发起挑战的人能响应,这显然和预期不符对吧?我之前开发类似互动机器人的时候也踩过这个坑,给你一步步拆解怎么改:

问题根源分析

大概率是你之前的代码里,把响应确认的判断条件写成了检查消息作者是否是挑战发起者(比如message.author.id === challengerId),这就直接把被挑战者的权限给排除了。我们需要反过来,把挑战的目标对象(被挑战者)的ID存起来,然后在处理确认请求时验证当前用户是不是这个被挑战者。

具体解决方案

我们可以用一个Map来跟踪所有活跃的决斗挑战,存储每个挑战的发起者、被挑战者和发起频道信息,这样就能精准判断谁有权限确认。

1. 初始化活跃挑战存储

首先创建一个全局的Map来保存待确认的挑战:

// 全局变量,用于跟踪所有待确认的决斗挑战
const activeDuels = new Map();
// 结构示例:key = 被挑战者ID,value = { challengerId: '发起者ID', channelId: '挑战发起频道ID' }

2. 发起挑战的逻辑调整

在用户发起挑战时,把被挑战者的ID作为键,存储对应的挑战信息:

client.on('messageCreate', async (message) => {
  // 假设!duel是发起挑战的命令,格式如!duel @用户名
  if (message.content.startsWith('!duel')) {
    const mentionedUser = message.mentions.users.first();
    
    // 检查是否有@用户
    if (!mentionedUser) {
      return message.reply('请@一个用户来发起决斗挑战哦!');
    }
    // 禁止自我挑战
    if (mentionedUser.id === message.author.id) {
      return message.reply('你总不能自己和自己决斗吧?😅');
    }
    // 检查被挑战者是否已有待处理的挑战
    if (activeDuels.has(mentionedUser.id)) {
      return message.reply(`<@${mentionedUser.id}>已经有一个待确认的挑战了,请等对方回复后再发起!`);
    }

    // 存储挑战信息
    activeDuels.set(mentionedUser.id, {
      challengerId: message.author.id,
      channelId: message.channel.id
    });

    // 发送挑战通知
    message.channel.send(`⚔️ <@${mentionedUser.id}>!<@${message.author.id}>向你发起了决斗挑战!回复\`!accept\`接受挑战,\`!decline\`拒绝挑战!`);
  }
});

3. 处理确认/拒绝的逻辑

现在在处理!accept或!decline命令时,只允许被挑战者操作:

client.on('messageCreate', async (message) => {
  const userId = message.author.id;
  const currentDuel = activeDuels.get(userId);

  // 处理接受挑战
  if (message.content === '!accept') {
    if (!currentDuel) {
      return message.reply('你目前没有待接受的决斗挑战哦!');
    }
    // 验证是否在发起挑战的频道操作(可选,防止跨频道误操作)
    if (currentDuel.channelId !== message.channel.id) {
      return message.reply('请在发起挑战的频道里确认决斗哦!');
    }

    // 执行决斗开始的逻辑(这里可以替换成你自己的决斗流程)
    message.channel.send(`🎉 决斗开始!<@${currentDuel.challengerId}> VS <@${userId}>!准备好战斗吧!`);
    
    // 移除已处理的挑战,避免重复操作
    activeDuels.delete(userId);
  }

  // 处理拒绝挑战(可选功能)
  if (message.content === '!decline') {
    if (!currentDuel) {
      return message.reply('你目前没有待拒绝的决斗挑战哦!');
    }
    if (currentDuel.channelId !== message.channel.id) {
      return message.reply('请在发起挑战的频道里拒绝决斗哦!');
    }

    message.channel.send(`😔 <@${currentDuel.challengerId}>,你的决斗挑战被<@${userId}>拒绝了!`);
    activeDuels.delete(userId);
  }
});

额外优化建议

  • 超时自动取消:可以给每个挑战加个定时器,比如5分钟后如果被挑战者没回复,就自动移除挑战并通知发起者
  • 多挑战支持:如果需要同时支持多个挑战(比如A挑战B,C挑战D),当前的Map结构已经能满足,因为键是被挑战者ID,不会冲突
  • 权限验证:可以额外检查用户是否是机器人,避免机器人误操作

这样改完之后,就只有被@的目标用户才能用!accept或!decline来响应挑战,发起者自己回复这些命令会提示没有待处理的挑战,完美符合你的需求!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:47:03