discord.py - remove role after stopped playing a game

Viewed 118

I want the bot to remove role after member stops playing the game.

When member's not playing a game, there is no game = [i for i in after.activities if str(i.type) == "ActivityType.playing"] anymore. so when trying to remove role it can't find game[0].name I think.

How do i fix this?

@client.event
async def on_member_update(before, after):
    game = [i for i in after.activities if str(i.type) == "ActivityType.playing"]
    
    if game:
        game_name = game[0].name
        role = discord.utils.get(after.guild.roles, name=game_name)
        if role == None:
            await after.guild.create_role(name=game_name, hoist=True, mentionable=True)
        await after.add_roles(role)
        
    elif before.activities and not game:
        game_name = game[0].name
        role = discord.utils.get(after.guild.roles, name=game_name)
        if role in after.roles: 
            await after.remove_roles(role)
  File "C:\Users\BUGA\Documents\VSCODE\Python Projects\activity role\main.py", line 35, in on_member_update
    game_name = game[0].name
IndexError: list index out of range
2 Answers

If you are trying to remove a role from a user once he stops playing a game, you should check which games he was playing in before, since that still holds the game he was playing.

You need to get game twice, or rather, split it into game_before and game_after.

Something like:

@client.event
async def on_member_update(before, after):
    game_before = [i for i in before.activities if str(i.type) == "ActivityType.playing"]
    game_after = [i for i in after.activities if str(i.type) == "ActivityType.playing"]

    if game_after:
        game_name = game_after[0].name
        role = discord.utils.get(after.guild.roles, name=game_name)
        if role == None:
            await after.guild.create_role(name=game_name, hoist=True, mentionable=True)
        await after.add_roles(role)     
    elif game_before:
        game_name = game_before[0].name
        role = discord.utils.get(after.guild.roles, name=game_name)
        if role in after.roles: 
            await after.remove_roles(role)

Your issue happens because you are only checking the Activity in the after, so if you try to get the name of the game from the after, of course it will return None after the user stops playing it, yet you try to access the name of the game doing:

game_name = game[0].name

In the second if you should check the name of the game in the before, something like this:

@client.event
async def on_member_update(before, after):
    game = [i for i in after.activities if str(i.type) == "ActivityType.playing"]
    
    if game:
        game_name = game[0].name
        role = discord.utils.get(after.guild.roles, name=game_name)
        if role == None:
            await after.guild.create_role(name=game_name, hoist=True, mentionable=True)
            role = discord.utils.get(after.guild.roles, name=game_name)
        await after.add_roles(role)
    elif before.activities and not game:
        # We get the game frim the before
        game = [i for i in before.activities if str(i.type) == "ActivityType.playing"]
        # Only remove role if he was actually playing a game before
        if game:
            game_name = game[0].name
            role = discord.utils.get(before.guild.roles, name=game_name)
            if role in before.roles: 
                await after.remove_roles(role)
Related