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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:20:46