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

Discord.py如何通过下拉菜单选对应角色并自动移除旧颜色角色

Discord.py 下拉选色角色功能实现方案

修改核心思路

  • 修正Select组件回调参数错误:discord.py的ui.Select回调默认仅接收interaction一个入参,不需要额外传入ctx
  • 预定义全量颜色角色名称集合:用来快速识别用户持有的角色是否属于颜色类,确保不会误删非颜色类角色
  • 优化回调交互逻辑:
    • 拿到用户选中的颜色名称,匹配服务器内对应名称的角色
    • 遍历用户现有角色,批量移除所有属于颜色类的旧角色
    • 为用户添加新选中的颜色角色,返回操作成功提示
  • 合并冗余代码:两个下拉菜单逻辑完全一致,可复用同一个Select类,无需重复定义重复代码

完整修改后代码

import discord
from discord.ext import commands
from discord.utils import get

# 预定义所有颜色角色名称,和你下拉选项的label完全对应
COLOUR_ROLES = {
    'Pomegranate', 'Rose', 'Apple', 'Crimson', 'Apricot', 'Tangerine', 'Giants Road', 'Cocoa', 'Chiffon', 'Lemon', 'Gold', 'Brass', 'Green Tea', 'Mint Leaves', 'Apple Green', 'Ivy',
    'Aero', 'Turquoise', 'Sapphire', 'Egyptian Blue', 'Periwinkle', 'Ube', 'Amethyst', 'Violet', 'Piggy', 'Carnation', 'Strawberry', 'Paradise', 'Platinum', 'Chalice', 'Silver', 'Smoke'
}

class ColourDropdown(discord.ui.Select):
    def __init__(self, options, placeholder="Choose your role colour..."):
        super().__init__(placeholder=placeholder, min_values=1, max_values=1, options=options)

    async def callback(self, interaction: discord.Interaction):
        # 拿到选中的颜色名称
        selected_colour = self.values[0]
        # 匹配服务器对应的角色
        target_role = get(interaction.guild.roles, name=selected_colour)
        if not target_role:
            await interaction.response.send_message("未找到对应颜色角色,请联系服务器管理员", ephemeral=True)
            return
        
        user = interaction.user
        # 移除用户所有旧的颜色角色
        roles_to_remove = [role for role in user.roles if role.name in COLOUR_ROLES]
        if roles_to_remove:
            await user.remove_roles(*roles_to_remove, reason="更换颜色角色")
        # 添加新的颜色角色
        await user.add_roles(target_role, reason="选择颜色角色")
        # 回应用户
        await interaction.response.send_message(f'已成功更换你的角色颜色为:{selected_colour}', ephemeral=True)


class DropdownView(discord.ui.View):
    def __init__(self):
        super().__init__()
        # 第一个下拉的选项
        options1 = [
            discord.SelectOption(label='Pomegranate', description='Your favourite colour is red', emoji='<:Pomegranate:910060219420278844>'),
            discord.SelectOption(label='Rose', description='Your favourite colour is green', emoji='<:Rose:910060219013410818>'),
            discord.SelectOption(label='Apple', description='Your favourite colour is blue', emoji='<:Apple:910060219256672266>'),
            discord.SelectOption(label='Crimson', description='Your favourite colour is blue', emoji='<:Crimson:910060219390906398>'),
            discord.SelectOption(label='Apricot', description='Your favourite colour is blue', emoji='<:Apricot:910060218883395675>'),
            discord.SelectOption(label='Tangerine', description='Your favourite colour is blue', emoji='<:Tangerine:910060219474780210>'),
            discord.SelectOption(label='Giants Road', description='Your favourite colour is blue', emoji='<:GiantsRoad:910060219348955206>'),
            discord.SelectOption(label='Cocoa', description='Your favourite colour is blue', emoji='<:Cocoa:910060219525107742>'),
            discord.SelectOption(label='Chiffon', description='Your favourite colour is blue', emoji='<:Chiffon:910060219286032384>'),
            discord.SelectOption(label='Lemon', description='Your favourite colour is blue', emoji='<:Lemon:910060219332198441>'),
            discord.SelectOption(label='Gold', description='Your favourite colour is blue', emoji='<:Gold:910060219239911456>'),
            discord.SelectOption(label='Brass', description='Your favourite colour is blue', emoji='<:Brass:910060219235700756>'),
            discord.SelectOption(label='Green Tea', description='Your favourite colour is blue', emoji='<:GreenTea:910060219315400704>'),
            discord.SelectOption(label='Mint Leaves', description='Your favourite colour is blue', emoji='<:MintLeaves:910060219126648884>'),
            discord.SelectOption(label='Apple Green', description='Your favourite colour is blue', emoji='<:AppleGreen:910060219239915551>'),
            discord.SelectOption(label='Ivy', description='Your favourite colour is blue', emoji='<:Ivy:910060219294433280>'),
        ]
        self.add_item(ColourDropdown(options1))

class DropdownView2(discord.ui.View):
    def __init__(self):
        super().__init__()
        # 第二个下拉的选项
        options2 = [
            discord.SelectOption(label='Aero', description='Your favourite colour is red', emoji='<:Aero:910060219030179841>'),
            discord.SelectOption(label='Turquoise', description='Your favourite colour is green', emoji='<:Turquoise:910060219294449694>'),
            discord.SelectOption(label='Sapphire', description='Your favourite colour is blue', emoji='<:Sapphire:910060219193770005>'),
            discord.SelectOption(label='Egyptian Blue', description='Your favourite colour is blue', emoji='<:EgyptianBlue:910060219449622589>'),
            discord.SelectOption(label='Periwinkle', description='Your favourite colour is blue', emoji='<:Periwinkle:910060218963091477>'),
            discord.SelectOption(label='Ube', description='Your favourite colour is blue', emoji='<:Ube:910060219302826034>'),
            discord.SelectOption(label='Amethyst', description='Your favourite colour is blue', emoji='<:Amethyst:910060219340566528>'),
            discord.SelectOption(label='Violet', description='Your favourite colour is blue', emoji='<:Violet:910060219323797534>'),
            discord.SelectOption(label='Piggy', description='Your favourite colour is blue', emoji='<:Piggy:910060219147624499>'),
            discord.SelectOption(label='Carnation', description='Your favourite colour is blue', emoji='<:Carnation:910060219059544115>'),
            discord.SelectOption(label='Strawberry', description='Your favourite colour is blue', emoji='<:Strawberry:910060219365748746>'),
            discord.SelectOption(label='Paradise', description='Your favourite colour is blue', emoji='<:Paradise:910060219298615316>'),
            discord.SelectOption(label='Platinum', description='Your favourite colour is blue', emoji='<:Platinum:910060219382530068>'),
            discord.SelectOption(label='Chalice', description='Your favourite colour is blue', emoji='<:Chalice:910060219248308264>'),
            discord.SelectOption(label='Silver', description='Your favourite colour is blue', emoji='<:Silver:910060219084714075>'),
            discord.SelectOption(label='Smoke', description='Your favourite colour is blue', emoji='<:Smoke:910060219378331648>'),
        ]
        self.add_item(ColourDropdown(options2))

class Bot(commands.Bot):
    def __init__(self):
        super().__init__(command_prefix=commands.when_mentioned_or('$'), intents=discord.Intents.all())

    async def on_ready(self):
        print(f'Logged in as {self.user} (ID: {self.user.id})')
        print('------')
    
    
bot = Bot()


@bot.command()
async def colour(ctx):
    """Sends a message with our dropdown containing colours"""
    view = DropdownView()
    view2 = DropdownView2()
    await ctx.send('第一组颜色选择:', view=view)
    await ctx.send('第二组颜色选择:', view=view2)

# 替换为你的机器人token启动
# bot.run("你的机器人token")

注意事项

  1. 请确保开启机器人的「服务器成员意图」(Server Members Intent),否则无法正常获取用户角色列表
  2. 机器人需要拥有「管理角色」权限,且机器人的角色在服务器角色列表中的排序要高于所有颜色角色,否则会出现加删角色失败的问题
  3. 代码中已经修正了你原来自定义emoji的格式错误,自定义emoji需要用<:emoji名称:emojiID>格式包裹,否则无法正常显示

内容的提问来源于stack exchange,提问作者Anymouse37.6

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 09:45:06