如何在Discord.py中用按钮编辑Embed字段并实现防重复投票
实现Discord投票按钮更新Embed与防重复投票
核心思路
- 在View类中存储投票计数和已投票用户集合,跟踪投票状态
- 按钮点击时先校验用户是否已投票,拦截重复操作
- 更新投票计数后,修改原消息的Embed字段并重新编辑消息
- 用仅用户可见的临时消息反馈投票结果
修改后的完整代码
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
相关产品推荐
相关产品推荐

