feat(members): assign team roles from the tournament registration sheet
Match members by Discord username against the lineup nicknames in the separate registration spreadsheet (TEAM_SHEET_ID) and give each their team's role. One team per person: switching teams removes the old team role, and a team with no Discord role yet is auto-created. Only role names present in the sheet are ever touched, so organisation/field/base roles are never at risk; the feature is a no-op when TEAM_SHEET_ID is unset. The sheet is not a single table (merged rows, stacked CS2/LoL sections with different layouts), so it is parsed via raw-row scanning rather than get_all_records. Citizenship markers like "(EST)" are used only as player delimiters and discarded. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -199,9 +199,35 @@ async def sync_member(
|
||||
else:
|
||||
result.errors.append(f"Baasrolli ID {rid} ei leitud serverist")
|
||||
|
||||
# --- Team role (from the separate registration spreadsheet) --------------
|
||||
# Matched by Discord username. One team per person: switching teams removes
|
||||
# the previous team's role; a team with no Discord role yet is auto-created.
|
||||
# Only role NAMES that appear in the team sheet are ever touched here, so
|
||||
# organisation/field/base roles are never at risk. When TEAM_SHEET_ID is
|
||||
# unset the caches are empty and this whole block is a no-op.
|
||||
team_name = sheets.get_team_for_username(member.name)
|
||||
all_teams = sheets.all_team_names()
|
||||
if team_name:
|
||||
team_role = discord.utils.get(guild.roles, name=team_name)
|
||||
if team_role is None:
|
||||
try:
|
||||
team_role = await guild.create_role(name=team_name, reason="Team sync: uus tiim")
|
||||
log.info("Created team role %r for %s", team_name, member)
|
||||
except discord.Forbidden:
|
||||
result.errors.append(f"Tiimirolli '{team_name}' loomiseks puudub õigus")
|
||||
team_role = None
|
||||
except discord.HTTPException as e:
|
||||
result.errors.append(f"Tiimirolli '{team_name}' loomine ebaõnnestus: {e}")
|
||||
team_role = None
|
||||
if team_role is not None:
|
||||
desired_roles.append(team_role)
|
||||
|
||||
# Team roles the member has but is no longer registered for (left/switched).
|
||||
to_remove = [r for r in member.roles if r.name in all_teams and r.name != team_name]
|
||||
|
||||
# Roles to add (desired but member doesn't have)
|
||||
to_add = [r for r in desired_roles if r not in member.roles]
|
||||
# (we currently only ADD the desired roles, not remove extras - safe default)
|
||||
# (outside of team roles we only ADD, never remove extras - safe default)
|
||||
|
||||
if to_add:
|
||||
try:
|
||||
@@ -212,6 +238,15 @@ async def sync_member(
|
||||
except discord.HTTPException as e:
|
||||
result.errors.append(f"Rolli viga kasutajale {member}: {e}")
|
||||
|
||||
if to_remove:
|
||||
try:
|
||||
await member.remove_roles(*to_remove, reason="Team sync: tiim vahetus")
|
||||
result.roles_removed = [r.name for r in to_remove]
|
||||
except discord.Forbidden:
|
||||
log.debug("No permission to remove roles for %s (likely admin), skipping", member)
|
||||
except discord.HTTPException as e:
|
||||
result.errors.append(f"Rolli eemaldamise viga kasutajale {member}: {e}")
|
||||
|
||||
# --- Birthday check ---
|
||||
birthday_str = str(row.get("Sünnipäev", "")).strip()
|
||||
if not _is_placeholder(birthday_str):
|
||||
|
||||
Reference in New Issue
Block a user