79496597

Date: 2025-03-09 21:07:46
Score: 2
Natty:
Report link

I'll summarize the information discussed in the comments, as well as the answer provided by OP in the edit to their original question. I believe this deserves to be a community wiki answer but I lack the reputation to mark it as such.

The original code halted unexpectedly after around 200 members. While the exact cause is unclear, fixing the following inefficiencies resolved the issue, suggesting that the problem stemmed from one (or a combination) of them.

  1. guild = discord.utils.get(bot.guilds, name = GUILD)

    The guild object is already in the context object.

    ✓ OP deleted this line, and further uses of guild were changed to context.guild.

  2. ServerMembers = [i for i in guild.members]

    First, guild.members is already a list, making this list comprehension unnecessary. ServerMembers will be the exact same list as guild.members every time this line is ran.

    In addition, guild.members itself potentially is potentially an incomplete list of members. guild.members relies on the bot's internal cache, which can be incomplete if the member list wasn’t fully populated. Switching to fetch_members() ensures the bot gets a complete list from the Discord API, even if the cache is incomplete.

    ✓ OP writes async for user in context.guild.fetch_members(limit = None):

  3. if (EmployeeRoleUS or EmployeeRoleCA) in user.roles

    As explained in this link by Queuebee, the above conditional does not work as intended. Assuming both EmpolyeeRoleUS and EmployeeRoleCA are not None, the above line is equivalent to just if EmployeeRoleUS in user.roles (the Canadian role is ignored).

    ✓ OP fixes this line to if (EmployeeRoleUS in user.roles) or (EmployeeRoleCA in user.roles)

  4. await guild.get_member(user.id).add_roles(guild.get_role(EMPLOYEE_FORMER_ROLE))

    The user object is already an instance of Member from guild.fetch_members().

    An additional suggestion not in OPs solution would be to define EmployeeFormerRole = guild.get_role(EMPLOYEE_FORMER_ROLE) once so it does not need to be redefined for every member. This would make the final line become user.add_roles(EmployeeFormerRole)

    ✓ OP changes it to user.add_roles(guild.get_role(EMPLOYEE_FORMER_ROLE)) which is sufficient.

  5. await guild.get_member(user.id).edit(roles = []) # Remove all roles

    ✓ OP opted to remove this line completely.

  6. await asyncio.sleep(15)

    The Discord.py library automatically handles rate limits internally.

    ✓ OP removed the manual await asyncio.sleep(15).

After making these changes, OP reported that the bot processed over 1,000 members successfully in around 24 minutes (~1-2 seconds per member) — confirming that the fixes resolved the halting issue.

It is unknown what exactly fixed the original issue, but it can be presumed that it was one of or a combination of the above changes.

@bot.command(name = "prune_unverified", help = "prune the unverified employees", enabled = True)
@commands.has_role("Owner")
async def prune_unverified(context):
    await context.message.delete()

    VerifiedEmployees = []
    PrunedUsers = []

    EmployeeRoleUS = context.guild.get_role(EMPLOYEE_ROLE)
    EmployeeRoleCA = context.guild.get_role(EMPLOYEE_CA_ROLE)
    VerifiedRole = context.guild.get_role(EMPLOYEE_VERIFIED_ROLE)
    FormerRole = context.guild.get_role(EMPLOYEE_FORMER_ROLE)

    # Fetch members directly from Discord API
    async for user in context.guild.fetch_members(limit=None):
        if (EmployeeRoleUS in user.roles) or (EmployeeRoleCA in user.roles):
            if VerifiedRole in user.roles:
                VerifiedEmployees.append(user)
            else:
                PrunedUsers.append(user)

    # Update roles for pruned users
    for user in PrunedUsers:
        await user.edit(roles=[])  # Remove all roles
        await user.add_roles(FormerRole)  # Add former employee role

    # Create CSV files of results
    with open("pruned_users.csv", mode="w") as pu_file:
        pu_writer = csv.writer(pu_file)
        pu_writer.writerow(["Nickname", "Username", "ID"])
        for user in PrunedUsers:
            pu_writer.writerow([user.nick, f"{user.name}#{user.discriminator}", user.id])

    with open("verified_users.csv", mode="w") as vu_file:
        vu_writer = csv.writer(vu_file)
        vu_writer.writerow(["Nickname", "Username", "ID"])
        for user in VerifiedEmployees:
            vu_writer.writerow([user.nick, f"{user.name}#{user.discriminator}", user.id])

    # Send results to Discord
    embed = discord.Embed(
        description=f":crossed_swords: **{len(PrunedUsers)} users were pruned by <@{context.author.id}>.**"
                    f"\n:shield: **{len(VerifiedEmployees)} users completed re-verification.**",
        color=discord.Color.blue()
    )
    await context.send(embed=embed)
    await context.send(file=discord.File("pruned_users.csv"))
    await context.send(file=discord.File("verified_users.csv"))
Reasons:
  • Blacklisted phrase (1): this link
  • RegEx Blacklisted phrase (1.5): I lack the reputation
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: Ryry013