0

I'm trying to make a discord bot for a small server. When I try to run this code, I get the error: AttributeError: 'diff_btns' object has no attribute ctx when I try to run my code.

Code:

#Import libraries:
from discord.interactions import Interaction
from discord.ui import Button, View
import discord
import quiz
'''
code to get question:
quiz.get_data(quiz.diff1)
await ctx.respond(quiz.q_output)
'''


bot = discord.Bot()


@bot.event
async def on_ready():
    print(f'We have logged in as {bot.user}')
    

class diff_btns(discord.ui.View):
    
    @discord.ui.button(label="Easy", row=0, style=discord.ButtonStyle.blurple)
    async def button_callback1(self, button, interaction):
        await interaction.response.send_message("You picked easy")
        for child in self.children: # loop through all the children of the view
            child.disabled = True # set the button to disabled
        await interaction.response.edit_message(view=self)
    
    @discord.ui.button(label="Medium", row=0, style=discord.ButtonStyle.blurple)
    async def button_callback2(self, button, interaction):
        await interaction.response.send_message("You picked medium")
        for child in self.children: # loop through all the children of the view
            child.disabled = True # set the button to disabled
        await interaction.response.edit_message(view=self)

    @discord.ui.button(label="Hard", row=0, style=discord.ButtonStyle.blurple)
    async def button_callback3(self, button, interaction):
        await interaction.response.send_message("You picked hard")
        for child in self.children: # loop through all the children of the view
            child.disabled = True # set the button to disabled
        await interaction.response.edit_message(view=self)
    

        #Interaction checks:
    async def interaction_check(self, interaction) -> bool:

        if interaction.user != self.ctx.author:
            await interaction.response.send_message("Use /gkquiz to make your own quiz.", ephemeral=True)
            return False
        else:
            return True

#Quiz question:
@bot.command(description="Starts a general knowledge quiz.")
async def quizgk(ctx):

    #Send message
    await ctx.respond("How difficult do you want the questions to be?", view=diff_btns())


bot.run()

The code is meant to send a message with the 3 buttons, then send another message based on which button was pressed. Thanks in advance for any help.

Ignoring exception in view <diff_btns timeout=180.0 children=3> for item <Button style=<ButtonStyle.primary: 1> url=None disabled=False label='Medium' emoji=None row=0>:
Traceback (most recent call last):
  File "C:\Users\zadok\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ui\view.py", line 410, in _scheduled_task
    allow = await self.interaction_check(interaction)
  File "c:\Users\zadok\Documents\InterCity Bot\main.py", line 48, in interaction_check
    if interaction.user != self.ctx.author:
AttributeError: 'diff_btns' object has no attribute 'ctx'
Blue Robin
  • 847
  • 2
  • 11
  • 31

1 Answers1

0

So the problem is that ctx is not defined within the class itself. So, it returns an error. I assume you are trying to make sure that the author is the same author who ran the command. What you can do to achieve this is create a self variable under __init__ and save the author.

Below are some snippets of code explained:

Under the view object:

class diff_btns(discord.ui.View):
    def __init__(self, user):
        super().__init__()  # see here: https://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods
        self.user = user  # setting the self variable to user to use later

Then instancing the view object:

await ctx.respond("How difficult do you want the questions to be?", view=diff_btns(ctx.author))  # see that you pass ctx.author into the class instance

There is also another error in your code. You use await interaction.response.edit_message(view=self). However, this is improper and creates an error. Instead use: interaction.response.edit_original_response(view=self) This works and it shows the following: final product

Resources:

  1. https://docs.pycord.dev/en/stable/api/models.html#discord.Interaction.edit_original_response
  2. https://guide.pycord.dev/interactions/ui-components/buttons

Full code:

class diff_btns(discord.ui.View):
    def __init__(self, user):
        super().__init__()
        self.user = user

    @discord.ui.button(label="Easy", row=0, style=discord.ButtonStyle.blurple)
    async def button_callback1(self, button, interaction):
        await interaction.response.send_message("You picked easy")
        for child in self.children:  # loop through all the children of the view
            child.disabled = True  # set the button to disabled
        await interaction.response.edit_original_response(view=self)

    @discord.ui.button(label="Medium", row=0, style=discord.ButtonStyle.blurple)
    async def button_callback2(self, button, interaction):
        await interaction.response.send_message("You picked medium")
        for child in self.children:  # loop through all the children of the view
            child.disabled = True  # set the button to disabled
        await interaction.response.edit_original_response(view=self)

    @discord.ui.button(label="Hard", row=0, style=discord.ButtonStyle.blurple)
    async def button_callback3(self, button, interaction):
        await interaction.response.send_message("You picked hard")
        for child in self.children:  # loop through all the children of the view
            child.disabled = True  # set the button to disabled
        await interaction.response.edit_original_response(view=self)

        # Interaction checks:

    async def interaction_check(self, interaction) -> bool:

        if interaction.user != self.user:
            await interaction.response.send_message("Use /gkquiz to make your own quiz.", ephemeral=True)
            return False
        else:
            return True


# Quiz question:
@bot.command(description="Starts a general knowledge quiz.")
async def quizgk(ctx):
    # Send message
    await ctx.respond("How difficult do you want the questions to be?", view=diff_btns(ctx.author))
Blue Robin
  • 847
  • 2
  • 11
  • 31