Skip to content

Commit 0bf974b

Browse files
Add command to verify and restore 'Registered' role for all registered users; enhance user removal logic in team matching
1 parent 8b675d4 commit 0bf974b

File tree

2 files changed

+110
-12
lines changed

2 files changed

+110
-12
lines changed

cogs/admin_cog.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,5 +253,84 @@ async def close_signups_command(self, interaction: discord.Interaction):
253253
logger.error(f"Error in close-signups command: {e}", exc_info=True)
254254
await interaction.response.send_message("An error occurred while toggling signup status.", ephemeral=True)
255255

256+
@app_commands.command(name="verify-roles", description="Verify and restore 'Registered' role for all registered users")
257+
@app_commands.default_permissions(administrator=True)
258+
async def verify_roles_command(self, interaction: discord.Interaction):
259+
"""Admin command to verify and restore the 'Registered' role for all users who are registered in the database."""
260+
await interaction.response.defer(ephemeral=True)
261+
262+
try:
263+
# Get all registered users from database
264+
registered_users = await self.bot.db.get_registered_users()
265+
266+
if not registered_users:
267+
await interaction.followup.send("No users are currently registered in the database.", ephemeral=True)
268+
return
269+
270+
# Find the "Registered" role
271+
guild = interaction.guild
272+
registered_role = discord.utils.get(guild.roles, name="Registered")
273+
274+
if not registered_role:
275+
await interaction.followup.send("Could not find the 'Registered' role in this server.", ephemeral=True)
276+
return
277+
278+
# Track statistics
279+
total_users = len(registered_users)
280+
users_fixed = 0
281+
users_already_correct = 0
282+
users_not_found = 0
283+
errors = 0
284+
285+
# Process each registered user
286+
for user in registered_users:
287+
try:
288+
# Skip banned users
289+
if user.get('banned', False):
290+
continue
291+
292+
user_id = user['user_id']
293+
member = guild.get_member(user_id)
294+
295+
if member is None:
296+
users_not_found += 1
297+
logger.warning(f"User {user.get('username', user_id)} not found in guild")
298+
continue
299+
300+
if registered_role not in member.roles:
301+
try:
302+
await member.add_roles(registered_role)
303+
users_fixed += 1
304+
logger.info(f"Added 'Registered' role to {member.name} ({user_id})")
305+
except discord.Forbidden:
306+
errors += 1
307+
logger.error(f"Bot doesn't have permission to add roles to {member.name} ({user_id})")
308+
except Exception as e:
309+
errors += 1
310+
logger.error(f"Error adding role to {member.name} ({user_id}): {e}")
311+
else:
312+
users_already_correct += 1
313+
314+
except Exception as e:
315+
errors += 1
316+
logger.error(f"Error processing user {user.get('username', user['user_id'])}: {e}")
317+
318+
# Send summary
319+
summary = [
320+
f"Processed {total_users} registered users:",
321+
f"• {users_fixed} users had their 'Registered' role restored",
322+
f"• {users_already_correct} users already had correct roles",
323+
f"• {users_not_found} users were not found in the server",
324+
]
325+
326+
if errors > 0:
327+
summary.append(f"• {errors} errors occurred (check logs)")
328+
329+
await interaction.followup.send("\n".join(summary), ephemeral=True)
330+
331+
except Exception as e:
332+
logger.error(f"Error in verify-roles command: {e}", exc_info=True)
333+
await interaction.followup.send(f"An error occurred: {str(e)}", ephemeral=True)
334+
256335
async def setup(bot):
257336
await bot.add_cog(AdminCog(bot))

cogs/teams_cog.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -318,37 +318,56 @@ async def remove_unmatched_command(self, interaction: discord.Interaction, categ
318318
participants, db_users
319319
)
320320

321+
# Track all matched Discord IDs to avoid removing matched users
322+
matched_discord_ids = set()
323+
324+
# Add exact matches
325+
for match in exact_matches:
326+
matched_discord_ids.add(match["discord_id"])
327+
328+
# Add name-only matches - these are also valid matches
329+
for match in name_only_matches:
330+
matched_discord_ids.add(match["discord_id"])
331+
321332
users_to_remove = []
322333
description = ""
323334

324335
# Build list of users to remove based on category
325336
if category == "all":
326-
# All unmatched = unmatched DB users + ambiguous matches
327-
users_to_remove.extend([u["discord_id"] for u in unmatched_db_users])
328-
for match in ambiguous_matches:
329-
for potential in match["potential_matches"]:
330-
users_to_remove.append(potential["discord_id"])
331-
description = "Removing all unmatched users and ambiguous matches"
337+
# Only include users that aren't in exact or name-only matches
338+
for user in db_users:
339+
if user["user_id"] not in matched_discord_ids:
340+
users_to_remove.append(user["user_id"])
341+
description = "Removing all unmatched users"
332342
elif category == "unmatched_db":
333-
users_to_remove.extend([u["discord_id"] for u in unmatched_db_users])
343+
# Only include users that aren't in exact or name-only matches
344+
for user in unmatched_db_users:
345+
if user["discord_id"] not in matched_discord_ids:
346+
users_to_remove.append(user["discord_id"])
334347
description = "Removing unmatched database users"
335348
elif category == "unmatched_participants":
336-
# These are in unmatched_participants but we need to find their discord IDs from db
337-
participant_names = {p["name"].lower() for p in unmatched_participants}
349+
# Get the Discord IDs of users who are registered with usernames that match unmatched participants
350+
participant_names = {p["name"].lower().split('#')[0] for p in unmatched_participants}
338351
for user in db_users:
339-
if user.get("matcherino_username", "").lower() in participant_names:
352+
user_matcherino = user.get("matcherino_username", "").lower().split('#')[0]
353+
if user_matcherino in participant_names and user["user_id"] not in matched_discord_ids:
340354
users_to_remove.append(user["user_id"])
341355
description = "Removing unmatched Matcherino participants"
342356
elif category == "ambiguous":
357+
# Only include ambiguous matches if they're not exact or name-only matches
343358
for match in ambiguous_matches:
344359
for potential in match["potential_matches"]:
345-
users_to_remove.append(potential["discord_id"])
360+
if potential["discord_id"] not in matched_discord_ids:
361+
users_to_remove.append(potential["discord_id"])
346362
description = "Removing users with ambiguous matches"
347363

348364
if not users_to_remove:
349365
await interaction.followup.send("No users found to remove for the selected category.", ephemeral=True)
350366
return
351367

368+
# Log what we're about to do
369+
logger.info(f"{description}. Found {len(users_to_remove)} users to remove.")
370+
352371
# Remove users from database and update roles
353372
removed_count = 0
354373
guild = interaction.guild
@@ -361,7 +380,7 @@ async def remove_unmatched_command(self, interaction: discord.Interaction, categ
361380
member = await guild.fetch_member(user_id)
362381
if member:
363382
roles_to_remove = [role for role in member.roles
364-
if role.name.lower() in ["registered"]]
383+
if role.name.lower() in ["registered", "team member"]]
365384
if roles_to_remove:
366385
await member.remove_roles(*roles_to_remove)
367386
removed_count += 1

0 commit comments

Comments
 (0)