Search code examples
pythonpython-3.xdiscorddiscord.py

How to unban a user?


I know how to ban members and I know how to kick them, but I don't know how to unban them. I have the following code which outputs the error:

discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'generator' object has no attribute 'id'

Code:

@bot.command(pass_context=True)
@commands.has_role("Moderator")
async def unban2(ctx):
    mesg = ctx.message.content[8:]
    banned = client.get_user_info(mesg)
    await bot.unban(ctx.message.server, banned)
    await bot.say("Unbanned!")

Solution

  • To unban a user, you need their user object. The way you seem to be doing it is by passing a user_id in your command and then creating the user object based on that. You could also do it using get_bans() explained below, but I'll answer your question first.

    Passing user_id in command

    In your code, mseg is the user_id and banned is the user object.

    mesg = ctx.message.content[8:]
    banned = await client.get_user_info(mesg)
    

    Edit: As squaswin pointed out, you need to await get_user_info()

    You are defining user_id as ctx.message.content[8:], which in this case is the text in your message from the 8th character onward with the first character being 0.

    Based on your code, the following should work:

    (The numbers below are just to show character position)

    !unban2 148978391295820384
    012345678...
    

    The problem with this is if your command name or prefix changes length, then you'll have to change the index in ctx.message.content[8:] to line up with the user_id in your message.

    The better way is to pass user_id as an argument to your command:

    async def unban(ctx, user_id):
        banned = await client.get_user_info(user_id)
    

    Now you can use it directly with client.get_user_info().

    Using get_bans()

    You could instead use get_bans() to get a list of banned users, and then use that list to get a valid user object. For example:

    async def unban(ctx):
        ban_list = await self.bot.get_bans(ctx.message.server)
    
        # Show banned users
        await bot.say("Ban list:\n{}".format("\n".join([user.name for user in ban_list])))
    
        # Unban last banned user
        if not ban_list:
            await bot.say("Ban list is empty.")
            return
        try:
            await bot.unban(ctx.message.server, ban_list[-1])
            await bot.say("Unbanned user: `{}`".format(ban_list[-1].name))
        except discord.Forbidden:
            await bot.say("I do not have permission to unban.")
            return
        except discord.HTTPException:
            await bot.say("Unban failed.")
            return
    

    To turn this into a working set of commands, you could create one command to show an indexed list of banned users, and another command to unban a user based on their list index.