Discord游戏服务器订阅角色关联Buttons权限控制技术问询
基于discord.py的实现方案
针对你的需求,核心问题是Discord原生不支持同一消息对不同用户展示差异化的按钮禁用状态,所以我们通过按钮点击时权限校验+专属警告的方式实现,以下是可落地的代码示例:
1. 实现角色等级判断工具
先写个辅助函数,快速判断用户的最高捐赠等级(替换成你服务器中实际的角色ID):
def get_max_donator_level(member: discord.Member) -> int: # 替换成你的T1/T2/T3角色ID ROLE_ID_MAP = { 3: 112233445566, # T3角色ID 2: 998877665544, # T2角色ID 1: 111222333444 # T1角色ID } # 从高到低检查用户角色 for level, role_id in sorted(ROLE_ID_MAP.items(), reverse=True): role = member.guild.get_role(role_id) if role and role in member.roles: return level # 频道仅T1及以上可见,理论上不会触发此返回 return 0
2. 带权限校验的自定义按钮类
创建继承自discord.ui.Button的自定义类,在点击时自动校验用户等级:
class DonatorActionButton(discord.ui.Button): def __init__(self, required_level: int, **kwargs): super().__init__(**kwargs) self.required_level = required_level # 该按钮需要的最低捐赠等级 async def callback(self, interaction: discord.Interaction): user_level = get_max_donator_level(interaction.user) if user_level >= self.required_level: # 这里写对应等级的业务逻辑,比如设置专属颜色、发放游戏道具 await interaction.response.send_message( f"已为你处理{self.label}的专属服务!", ephemeral=True # 仅当前用户可见,避免频道刷屏 ) # 示例:给用户添加专属颜色角色 # color_role = interaction.guild.get_role(...) # await interaction.user.add_roles(color_role) else: # 权限不足时发送警告 await interaction.response.send_message( f"权限不足!需要至少[{self.required_level}级捐赠]才能使用该功能。", ephemeral=True )
3. 创建对应等级的消息视图
为T1/T2/T3三条订阅消息分别创建视图,添加对应权限的按钮:
# T1专属消息视图 def build_t1_view(): view = discord.ui.View(timeout=None) view.add_item(DonatorActionButton( required_level=1, label="选择T1专属昵称颜色", style=discord.ButtonStyle.primary, custom_id="t1_color_picker" # 持久化需要唯一ID )) view.add_item(DonatorActionButton( required_level=1, label="领取T1游戏道具包", style=discord.ButtonStyle.primary, custom_id="t1_item_claim" )) return view # T2专属消息视图 def build_t2_view(): view = discord.ui.View(timeout=None) view.add_item(DonatorActionButton( required_level=2, label="选择T2专属昵称颜色", style=discord.ButtonStyle.success, custom_id="t2_color_picker" )) view.add_item(DonatorActionButton( required_level=2, label="领取T2专属游戏道具", style=discord.ButtonStyle.success, custom_id="t2_item_claim" )) return view # T3专属消息视图 def build_t3_view(): view = discord.ui.View(timeout=None) view.add_item(DonatorActionButton( required_level=3, label="选择T3专属昵称颜色", style=discord.ButtonStyle.danger, custom_id="t3_color_picker" )) view.add_item(DonatorActionButton( required_level=3, label="领取T3专属游戏道具", style=discord.ButtonStyle.danger, custom_id="t3_item_claim" )) view.add_item(DonatorActionButton( required_level=3, label="解锁T3专属频道权限", style=discord.ButtonStyle.danger, custom_id="t3_channel_unlock" )) return view
4. 发送订阅消息
在指定的捐赠专属频道发送三条消息(替换成你的频道ID):
@bot.command() @discord.ext.commands.has_role(111222333444) # 仅T1及以上用户可触发该命令 async def send_sub_messages(ctx): target_channel = bot.get_channel(123456789012) # 替换成你的捐赠专属频道ID if not target_channel: await ctx.send("目标频道不存在!") return # 发送三条订阅消息 await target_channel.send("=== T1订阅专属服务 ===", view=build_t1_view()) await target_channel.send("=== T2订阅专属服务 ===", view=build_t2_view()) await target_channel.send("=== T3订阅专属服务 ===", view=build_t3_view()) await ctx.send("订阅消息已发送!", ephemeral=True)
5. 持久化视图(机器人重启后仍生效)
要让按钮在机器人重启后还能正常响应,需要在机器人启动时加载视图:
@bot.event async def on_ready(): bot.add_view(build_t1_view()) bot.add_view(build_t2_view()) bot.add_view(build_t3_view()) print(f"机器人已登录:{bot.user.name}")
关于按钮置灰的补充说明
Discord没有提供“同一消息对不同用户展示不同按钮状态”的原生支持,所有用户看到的按钮状态是统一的。如果强行要实现“置灰”效果,只能通过动态生成视图的方式(比如用户点击消息时重新发送带禁用按钮的消息),但这种方式体验较差且实现复杂,更推荐用上面的“点击校验+专属警告”方案,既简洁又能满足需求。
内容的提问来源于stack exchange,提问作者Aiyusho
相关产品推荐
相关产品推荐

