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

discord.js命令处理器下为embed分页添加按钮交互的实现方法

实现方案

核心使用discord.js内置的组件收集器实现在单个命令文件内处理按钮交互,无需修改命令处理器的入口文件,同时解决await报错问题。
你遇到的await报错是因为你定义的cinfo是普通同步函数,await关键字仅可在被async标记的函数内使用,将cinfo改为async函数即可解决。

修改后的完整代码

const { SlashCommandBuilder } = require("@discordjs/builders");
const Discord = require("discord.js");
const info = require("./info.json");

module.exports = {
  data: new SlashCommandBuilder()
    .setName("cinfo")
    .setDescription("Shows AniGame card info")
    .addStringOption(option =>
      option
        .setName("name")
        .setDescription("Enter the name of a card")
        .setRequired(true) // 建议改为必填,避免空值报错
    ),
  async execute(interaction) {
    const msg = interaction.options.getString("name").toLowerCase();

    // 将cinfo改为async函数以支持await
    async function cinfo(
      name,
      info,
      stats,
      talent,
      image,
      sr1,
      sr2,
      sr3,
      srt,
      ur1,
      ur2,
      ur3,
      urt
    ) {
      const base = new Discord.MessageEmbed()
        .setTitle(name)
        .setColor(0xffd1dc)
        .setDescription(info)
        .addField("__Card Stats__", stats)
        .addField("Talent", talent)
        .setImage(image);

      const sr = new Discord.MessageEmbed()
        .setTitle(name + " | Level 50")
        .setColor(0xffd1dc)
        .addField("__SR Evo 1__", sr1, true)
        .addField("__SR Evo 2__", sr2, true)
        .addField("__SR Evo 3__", sr3, true)
        .addField("Talent", srt)
        .setImage(image);

      const ur = new Discord.MessageEmbed()
        .setTitle(name + " | Level 60")
        .setColor(0xffd1dc)
        .addField("__UR Evo 1__", ur1, true)
        .addField("__UR Evo 2__", ur2, true)
        .addField("__UR Evo 3__", ur3, true)
        .addField("Talent", urt)
        .setImage(image);

      const row = new Discord.MessageActionRow().addComponents(
        new Discord.MessageButton()
          .setCustomId("backward")
          .setStyle("PRIMARY")
          .setEmoji("⬅️"),

        new Discord.MessageButton()
          .setCustomId("forward")
          .setStyle("PRIMARY")
          .setEmoji("➡️"),

        new Discord.MessageButton()
          .setCustomId("delete")
          .setStyle("DANGER")
          .setEmoji("🗑️")
      );

      const pages = [base, sr, ur];
      let currentIndex = 0; // 记录当前分页索引

      // 等待回复发送完成,获取回复消息对象
      const reply = await interaction.reply({ embeds: [pages[currentIndex]], components: [row], fetchReply: true });

      // 定义过滤器:仅允许发起命令的用户操作按钮
      const filter = i => i.user.id === interaction.user.id;
      // 创建组件收集器,超时时间设为5分钟,单位为毫秒
      const collector = reply.createMessageComponentCollector({ filter, time: 300000 });

      // 监听按钮点击事件
      collector.on("collect", async i => {
        if (i.customId === "forward") {
          // 前进按钮:索引+1,超过数组长度则回到0
          currentIndex = currentIndex + 1 >= pages.length ? 0 : currentIndex + 1;
        } else if (i.customId === "backward") {
          // 后退按钮:索引-1,小于0则跳到最后一页
          currentIndex = currentIndex - 1 < 0 ? pages.length - 1 : currentIndex - 1;
        } else if (i.customId === "delete") {
          // 删除按钮:直接删除回复
          await reply.delete();
          return;
        }
        // 更新消息的嵌入内容
        await i.update({ embeds: [pages[currentIndex]], components: [row] });
      });

      // 监听收集器结束事件:超时后禁用所有按钮
      collector.on("end", async () => {
        // 消息已被删除的话跳过处理
        if (!reply.deletable) return;
        const disabledRow = new Discord.MessageActionRow().addComponents(
          row.components.map(btn => btn.setDisabled(true))
        );
        await reply.edit({ components: [disabledRow] });
      });
    }
    
    if (
      msg === "itaru hashida" ||
      msg === "itaru" ||
      msg === "hashida"
    ) {
      await cinfo(
        info.Itaru_Hashida[0],
        info.Itaru_Hashida[1],
        info.Itaru_Hashida[2],
        info.Itaru_Hashida[3],
        info.Itaru_Hashida[4],
        info.Itaru_Hashida[5],
        info.Itaru_Hashida[6],
        info.Itaru_Hashida[7],
        info.Itaru_Hashida[8],
        info.Itaru_Hashida[9],
        info.Itaru_Hashida[10],
        info.Itaru_Hashida[11],
        info.Itaru_Hashida[12]
      );
    } else {
      // 未匹配到卡牌的提示
      await interaction.reply({ content: "未找到对应卡牌信息", ephemeral: true });
    }
  }
};

注意事项

  • 代码中默认将卡牌名参数改为必填,避免空值导致报错,不需要的话可以改回setRequired(false)并补充空值处理逻辑
  • 分页默认做了循环切换处理,不需要循环的话可自行修改currentIndex的边界判断逻辑
  • 收集器超时时间设为5分钟,可根据需求调整time参数的数值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 20:24:03