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

如何在Discord.py中用按钮编辑Embed字段并实现防重复投票

实现Discord投票按钮更新Embed与防重复投票

核心思路

  1. 在View类中存储投票计数和已投票用户集合,跟踪投票状态
  2. 按钮点击时先校验用户是否已投票,拦截重复操作
  3. 更新投票计数后,修改原消息的Embed字段并重新编辑消息
  4. 用仅用户可见的临时消息反馈投票结果

修改后的完整代码

class Buttons(discord.ui.View):
    def __init__(self, upvote_count=0, downvote_count=0, *, timeout=180):
        super().__init__(timeout=timeout)
        self.upvote_count = upvote_count
        self.downvote_count = downvote_count
        self.voted_users = set()  # 存储已投票用户,避免重复投票

    @discord.ui.button(label="Yes", style=discord.ButtonStyle.success, emoji='👍')
    async def upvote_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        # 检查用户是否已投票
        if interaction.user in self.voted_users:
            await interaction.response.send_message("你已经投过票了,不能重复投票!", ephemeral=True)
            return
        
        # 更新赞成票计数
        self.upvote_count += 1
        # 获取当前消息的Embed并修改字段
        embed = interaction.message.embeds[0]
        embed.set_field_at(0, name="Upvotes", value=str(self.upvote_count), inline=True)
        # 编辑消息更新Embed
        await interaction.message.edit(embed=embed, view=self)
        # 标记用户已投票
        self.voted_users.add(interaction.user)
        # 给用户发送临时反馈
        await interaction.response.send_message("你已投赞成票!", ephemeral=True)

    @discord.ui.button(label="No", style=discord.ButtonStyle.danger, emoji='👎')
    async def downvote_button(self, button: discord.ui.Button, interaction: discord.Interaction):
        if interaction.user in self.voted_users:
            await interaction.response.send_message("你已经投过票了,不能重复投票!", ephemeral=True)
            return
        
        self.downvote_count += 1
        embed = interaction.message.embeds[0]
        embed.set_field_at(1, name="Downvotes", value=str(self.downvote_count), inline=True)
        await interaction.message.edit(embed=embed, view=self)
        self.voted_users.add(interaction.user)
        await interaction.response.send_message("你已投反对票!", ephemeral=True)

class Poll(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @app_commands.command(name="poll", description="Ask a question and receive upvotes or downvotes (Yes/No)")
    async def poll(self, interaction: discord.Interaction, *, question: str):
        embed = discord.Embed(
            description=question,
            color=0xb037e1
        )
        embed.set_author(name="Poll", icon_url=self.bot.user.avatar)
        embed.set_footer(text=f"Asked by: {interaction.user}", icon_url=interaction.user.avatar)

        # 初始化投票计数为0,替换原来的X
        embed.add_field(name="Upvotes", value="0", inline=True)
        embed.add_field(name="Downvotes", value="0", inline=True)

        # 初始化View并传入初始计数
        await interaction.response.send_message(embed=embed, view=Buttons(upvote_count=0, downvote_count=0))

关键细节说明

  • 已投票用户跟踪:用set()存储用户对象,查询效率高,能快速判断用户是否已投票
  • Embed更新:通过interaction.message.embeds[0]获取当前Embed,使用set_field_at()修改指定位置的字段值,确保投票数实时更新
  • 临时反馈:ephemeral=True让提示仅对操作用户可见,不会干扰投票频道的其他内容
  • View状态保留:View与消息绑定后,内部存储的计数和用户集合会持续存在直到超时(180秒),保证投票状态的一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:20:26