#Nonetype for ctx

1 messages · Page 1 of 1 (latest)

prisma sorrel
#

So, I have something that checks when a button is pressed from an embed in a DM.

Here is my code:

@listen()
async def on_component(event: Component, ctx: ComponentContext = None):
    ctx = event.ctx
    if ctx.custom_id.startswith("accept_application"):
        ...
    elif ctx.custom_id.startswith("deny_application"):
        ...

    match ctx.custom_id:
        case "start_application":
            ...
        case "accept_invitation":
            guild_id = ctx.guild_id  # Retrieve the guild ID from the interaction context
            guild = bot.get_guild(guild_id)
            member = guild.get_member(ctx.author.id)
            print(member)
            await accept_invitation(ctx, member, 1138837807255781386)

So, my problem is that I'm using ctx: ComponentContext = None at the top, and for some reason here it decides to be None. Here's my exact error:

member = guild.get_member(ctx.author.id)
             ^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get_member'```
jovial pulsarBOT
#

Hey! Once your issue is solved, press the button below to close this thread!

crude sand
#

That your ctx is None is not the Error.
ctx would be overwritten in any case.
To using the ctx argument if present you can do this:

async def on_component(event: Component, ctx: ComponentContext = None):
    ctx = ctx or event.ctx #use event.ctx if ctx None

ctx should have ctx.guild. There is no need for get it by ID.
This also applies for member. ctx.author is your expected Member Object

#
...
case "accept_invitation":
    guild = ctx.guild
    member = ctx.author
    await accept_invitation(ctx, member, 1138837807255781386)
...
prisma sorrel
#

Ah, ty.

#

Thank you for the information.

prisma sorrel
#

Code:

async def accept_invitation(ctx: SlashContext, id: int, role: int):
    await ctx.defer()
    await ctx.member.add_role(role)
crude sand
#

can you print out the type of ctx?

prisma sorrel
crude sand
#

can you show your whole code?
By the way, it is a button in a guild, right?

prisma sorrel
#

No, it's a button in a DM.

crude sand
#

Then there is no guild 🤦‍♂️

prisma sorrel
#

I want it so that when the user presses that button, they get a role.

#

Is that possible to do in the DM?

crude sand
#

yeah, but not on your way. XD

prisma sorrel
#

Oh lol

crude sand
prisma sorrel
#

k ty.

#

@crude sand

Like this?

        case "accept_invitation":
            guildObject = bot.get_guild(1136789186515570698)
            guildObject.get_member(ctx.author.id)
            await ctx.member.add_role(1138837807255781386)
            await ctx.respond("You have been given the role! Please check the server for more information.", ephemeral=True)```
crude sand
#

you have to assign get_member to "member" and then use it instead of "ctx.member"

prisma sorrel
#
        case "accept_invitation":
            guildObject = bot.get_guild(1136789186515570698)
            member = guildObject.get_member(ctx.author.id)
            await member.add_role(1138837807255781386)

Still gives the nonetype error.

jovial pulsarBOT
#

In interactions.py, there is a difference between getting or fetching an object.
Getting an object only looks at objects that have been cached, and therefore is a synchronous function. Getting an object can occasionally return None if that object has never been cached before. Here are some use cases:

user: User | None = bot.get_user(123456789)
member: Member | None = guild.get_member(123456789)```

Although interactions.py's cache system is very reliable, you might sometimes want to make sure that None will not be returned. This is were **fetching** an object becomes useful. When fetching an object, interactions.py will first look if that object is cached. If not, it will then request that object from the Discord API asynchronously. Here are some use cases:
```py
user: User = await bot.fetch_user(123456789)
member: Member = await guild.fetch_member(123456789)```
_Note:_ If you want to skip interactions.py checking if the object is first cached, and directly fetch the object from the Discord API, you can use the optional argument `force=True`. This can become very useful for some features that are never passed by the Discord Gateway except when fetching.
Example: `user: User = await bot.fetch_user(123456789, force=True)`
prisma sorrel
#

member = guildObject.get_member(ctx.author.id)

get_member isnt a function there and neither is fetch. And I switched to fetching the guild.

#

@crude sand

When I use fetch for the get_member add role isnt availible however with get it is.

And it seems to be getting the member that returns none for some reason.

crude sand
#

Did you await the fetch functions?

prisma sorrel
#

It works now, thank you SO SO SO SO MUCH!!!

crude sand
#

No problem