refactor(teams): move team-role sync to the economy/community bot

The team-role feature was aimed at the wrong bot. Tournament participants
live in the economy/community guild, but team-role sync had been bolted onto
the dev bot's roster sync (sync_member), which bails out for anyone missing
from the internal member sheet - so it could never reach its actual audience.

Decouple it: keep the (roster-independent) team-sheet parsing, pull the team
wiring off the dev/member-sync path, and re-home it on the economy bot.

- core/member_sync: revert sync_member to add-only (drop team block +
  SyncResult.roles_removed); add roster-independent sync_team_role and a
  whole-guild sync_all_team_roles returning a reporting summary. Still only
  ever touches role NAMES present in the team sheet.
- commands/economy_team_commands: new admin-only /teamsync command.
- bot.py: hourly team_sync_hourly task (economy-only, no-op unless
  TEAM_SHEET_ID is set; first tick at boot covers startup load); register
  /teamsync under the economy profile; drop the dev-side startup load.
- commands/dev_member_commands: /check no longer refreshes teams or reports
  removed roles.
- strings + .env.example: TEAMSYNC_UI, CMD[teamsync], document TEAM_SHEET_ID.
- tests: retarget sync tests to sync_team_role; add sync_all_team_roles case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R6JZkyszyDFuFtk25WBbcR
This commit is contained in:
Rene Arumetsa
2026-08-28 15:04:23 +03:00
parent 52002c37fc
commit ce1ed28904
9 changed files with 331 additions and 103 deletions

View File

@@ -182,10 +182,6 @@ def register_dev_member_commands(
except Exception as e:
await interaction.followup.send(S.ERR["sheet_error"].format(error=e), ephemeral=True)
return
try:
await sheets.refresh_teams()
except Exception as e:
log.warning("/check: team sheet refresh failed, using stale team cache: %s", e)
ids_filled = 0
for row in data:
@@ -237,8 +233,6 @@ def register_dev_member_commands(
parts.append(S.CHECK_UI["detail_nickname"])
if result.roles_added:
parts.append(S.CHECK_UI["detail_roles_added"].format(roles=", ".join(result.roles_added)))
if result.roles_removed:
parts.append(S.CHECK_UI["detail_roles_removed"].format(roles=", ".join(result.roles_removed)))
details.append(S.CHECK_UI["detail_changed"].format(name=member.display_name, parts=", ".join(parts)))
else:
already_ok += 1