Trying to Kick All Members with a Role using Discord.py

Viewed 54

I'm fairly new to scripting in Python, but I used stack overflow to create a command for a Discord bot that should kick all members with a given role. This is the code I currently have:

    import discord 
from discord.ext import commands
from discord.ext.commands import has_permissions

bot = commands.Bot(command_prefix = ".")

@bot.command()

#async def hello(ctx):
 #   await ctx.reply('Hello!')

@has_permissions(administrator=True)
async def kickMembers(ctx, role: discord.Role, reason: str=None):
    await ctx.reply('Kicking members')
    for member in ctx.guild.members:
        await ctx.reply(f'Looping through member  {member}')
        if role in member.roles: # does member have the specified role?
            await ctx.reply('Found a member, kicking!')
            await ctx.guild.kick(member,reason=reason)

Now, the issue is that it begins to loop through, but completely freezes after sending the message 'Looping through member {member}'. It sends a message saying that it is looping through itself (the bot), but then freezes and does't loop through anyone else.

If anyone has any help that is much appreciated, thanks!

2 Answers

This works for me. You should adjust the intents, and send kickMyRole from the user whose first role you want to kick.

From what it sounds like, though, you just haven't given it the correct intents: make sure on the developer portal (https://discord.com/developers/applications/), select your application, then click bot, and select the server members intent and the message content one. You will need to update your code accordingly. (I have added some more stuff to this code to make it easier to test).

import discord 
from discord.ext import commands
from discord.ext.commands import has_permissions

intents = discord.Intents.default()
intents.members = True
intents.message_content = True
bot = commands.Bot(command_prefix = ".", intents=intents)

@bot.command()

#async def hello(ctx):
 #   await ctx.reply('Hello!')


# @has_permissions(administrator=True)
async def kickMembers(ctx, role: discord.Role, reason: str=None):
    print(role)
    await ctx.reply('Kicking members')
    for member in ctx.guild.members:
        await ctx.reply(f'Looping through member  {member}')
        if role in member.roles: # does member have the specified role?
            await ctx.reply('Found a member, kicking!')
            await ctx.guild.kick(member,reason=reason)

@bot.event
async def on_message(ctx):
    print(ctx.content)
    if ctx.content == "kickMyRole":
        await kickMembers(ctx, ctx.author.roles[1]) # Not @everyone

bot.run("TOKEN")

I commented about looping through the members associated with a role, so here is an example of that with your use case:

import discord 
from discord.ext import commands
from discord.ext.commands import has_permissions

bot = commands.Bot(command_prefix='.')

@bot.command()
@has_permissions(administrator=True)
async def kickMembers(ctx, role: discord.Role, reason: str = None):
    await ctx.reply('Kicking members')

    for member in role.members:
        await member.kick(reason=reason)

    await ctx.reply('Members kicked')

Doing it this way saves time by not looping through all the members of a guild and not needing to use logic to determine if the member has the role you are looking for.

Related