AttributeError: 'Button' object has no attribute 'guild'

class Buttons( discord.ui.View): 
    def __init__(self, *, timeout=180): 
        super().__init__(timeout=timeout)
    @discord.ui.button(label="Button",style=discord.ButtonStyle.gray)
    async def gray_button(self, button:discord.ui.button(), interaction:discord.Interaction):
        print(type(interaction))
        if config.guild['eventRole'] in interaction.guild.roles:
            await interaction.user.remove_roles(config.guild['eventRole'])
        else:
            await interaction.user.add_roles(config.guild['eventRole'])
@bot.command()
async def button(ctx):
    await ctx.send(
        "This message has buttons!",
        view=Buttons()

Ошибка

if config.guild['eventRole'] in interaction.guild.roles:
                                ^^^^^^^^^^^^^^^^^
AttributeError: 'Button' object has no attribute 'guild'

Почему объект disord.Interaction неожиданно превращается discord.ui.button.Buttonи как это решить?


Ответы (3 шт):

Автор решения: Unclear

Функция callback (ваша gray_button) принимает только 1 аргумент interaction. Получается так, что у вас self - это и есть объект кнопки, а button - это discord.Interaction

У вас должно получится так:

async def gray_button(self:discord.ui.Button, interaction:discord.Interaction): ...

если будут проблемы с self, то оставьте self без ":discord.ui.Button":

async def gray_button(self, interaction:discord.Interaction): ...
→ Ссылка
Автор решения: q r t s

Функция принимает только два аргумента, это self и interaction.

async def callback(self, interaction:discord.Interaction):

И само название gray_button измените на callback.

→ Ссылка
Автор решения: Unclear

Могу предложить такие классы для того, чтобы создавать ui.View:

class CustomButton(discord.ui.Button):
    def __init__(self, func: any, args: list | None=None, label: str | None=None, style: discord.ButtonStyle | None= discord.ButtonStyle.secondary, emoji: str | None=None, row: int | None=None) -> None:
        self.func = func
        self.args = args
        super().__init__(label=label, style=style, emoji=emoji, row=row)
    
    async def callback(self, interaction: discord.Interaction) -> None:
        if self.args == None:
            await self.func(self, interaction)
        else:
            await self.func(self, interaction, self.args)

class CustomView(discord.ui.View):
    def __init__(self, items: list, timeout: float) -> None:
        super().__init__(timeout=timeout)
        for i in items:
            self.add_item(item=i)

Вот пример использования:

async def hello_func(btn: CustomButton, interaction: discord.Interaction):
    await interaction.response.send_message("hello", ephemeral=True)

async def world_func(btn: CustomButton, interaction: discord.Interaction):
    await interaction.response.send_message("world", ephemeral=True)

await interaction.response.send_message(
    content = f"Какие то кнопки.",
    view = CustomView(
        items = [
            CustomButton(label="Hello", row=0, func=hello_func, style=discord.ButtonStyle.gray),
            CustomButton(label="World", row=0, func=world_func, style=discord.ButtonStyle.gray)
        ],
        timeout = None)
    )
→ Ссылка