Discord工单机器人无法创建频道/分类,点击按钮触发AttributeError
Discord工单机器人创建频道失败:AttributeError 问题解决
错误现象
点击「Create Ticket」按钮时无法创建频道或分类,触发如下错误:
[2023-08-12 20:05:06] [ERROR ] discord.ui.view: Ignoring exception in view <TicketPanelView timeout=None children=1> for item <Button style=<ButtonStyle.secondary: 2> url=None disabled=False label='Create Ticket' emoji=<PartialEmoji animated=False name='✉️' id=None> row=None> Traceback (most recent call last): File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ui\view.py", line 427, in _scheduled_task await item.callback(interaction) File "C:\Users\user\Desktop\ticket bot\main2.py", line 15, in create_ticket if interaction.user.id in open_tickets: ^^^^^^^^^^^^^^^^ AttributeError: 'Button' object has no attribute 'user'
问题分析
- 按钮回调方法位置错误:
@discord.ui.button装饰的create_ticket方法必须定义在TicketPanelView类内部,否则Discord.py无法正确绑定视图上下文,导致回调参数顺序错乱(把interaction传入了button参数位置)。 - 变量未初始化:
open_tickets字典未提前定义,后续使用会触发NameError。 - 缩进错误:创建分类、频道的代码块缩进在
return语句之后,永远不会被执行。
修正后的完整代码
import discord from discord.ext import commands intents = discord.Intents.default() intents.message_content = True intents.members = True # 新增:获取成员权限所需的意图 bot = commands.Bot(command_prefix='!', intents=intents) # 初始化工单跟踪字典 open_tickets = {} class TicketPanelView(discord.ui.View): def __init__(self): super().__init__(timeout=None) # 将按钮回调方法移至类内部 @discord.ui.button(label='Create Ticket', emoji='✉️', style=discord.ButtonStyle.secondary) async def create_ticket(self, button: discord.ui.Button, interaction: discord.Interaction): if interaction.user.id in open_tickets: await interaction.response.send_message("你已经有一个未关闭的工单了。", ephemeral=True) return # 修正缩进:确保这部分逻辑能正常执行 category = discord.utils.get(interaction.guild.categories, name='Tickets') if not category: category = await interaction.guild.create_category('Tickets') ticket_channel = await category.create_text_channel(f'ticket-{interaction.user.display_name}') # 设置权限:隐藏工单频道对普通用户的可见性 await ticket_channel.set_permissions(interaction.guild.default_role, read_messages=False) await ticket_channel.set_permissions(interaction.user, read_messages=True, send_messages=True) await ticket_channel.send(f'欢迎 {interaction.user.mention}!你的工单已创建。') await interaction.response.send_message('正在创建新工单...', ephemeral=True) open_tickets[interaction.user.id] = ticket_channel.id @bot.command() async def panel(ctx): embed = discord.Embed( title='工单系统', description='点击下方按钮创建你的专属工单', color=discord.Color.blue() ) view = TicketPanelView() await ctx.send(embed=embed, view=view) # 替换为你的机器人令牌 bot.run('YOUR_BOT_TOKEN')
关键修改说明
- 将
create_ticket方法移至TicketPanelView类内部,确保装饰器正确绑定视图上下文。 - 新增
open_tickets = {}初始化工单跟踪字典,避免未定义变量错误。 - 修正代码缩进,让创建分类和频道的逻辑不再被
return语句阻断。 - 新增
intents.members = True,确保机器人能正确处理成员权限设置。 - 补充
@everyone角色的权限移除,增强工单频道的私密性。
内容的提问来源于stack exchange,提问作者lucaa
相关产品推荐
相关产品推荐

