feat(teams): place new team roles under their game's divider role

Auto-created team roles now land directly under the CS2 / LoL "divider" role
in the community guild's role list, keeping it grouped by game.

- config: CS2_DIVIDER_ROLE_ID / LOL_DIVIDER_ROLE_ID (season-specific, env
  overridable) exposed as TEAM_DIVIDER_ROLE_IDS keyed by game code.
- core/sheets: tag each team with its game (CS2/LoL) from the section title it
  sits under; shared _scan_sections generator feeds both parse_team_rosters and
  the new parse_team_games; get_game_for_team accessor + _team_game cache.
- core/member_sync: on creating a team role, position it at its game divider's
  slot (best-effort; left in place if game/divider unknown or move refused).
- .env.example + tests for game tagging and role placement.

Each participant is in exactly one game, so one role per team is unambiguous.

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:51:48 +03:00
parent a4645e19c5
commit e179a35fc4
5 changed files with 160 additions and 9 deletions

View File

@@ -45,6 +45,19 @@ BIRTHDAY_CHANNEL_ID = (
BIRTHDAY_WINDOW_DAYS = int(os.getenv("BIRTHDAY_WINDOW_DAYS", "7"))
BASE_ROLE_IDS: list[int] = [1478304631930228779, 1478302278862766190]
# Team-section "divider" roles in the community guild. When a new team role is
# auto-created it is positioned directly under the divider for its game, so the
# role list stays grouped by game. Season-specific - update yearly (or override
# via CS2_DIVIDER_ROLE_ID / LOL_DIVIDER_ROLE_ID). 0 disables placement for that
# game (the role is still created, just left at the bottom of the list).
CS2_DIVIDER_ROLE_ID = _env_int("CS2_DIVIDER_ROLE_ID", 1498736834656604251)
LOL_DIVIDER_ROLE_ID = _env_int("LOL_DIVIDER_ROLE_ID", 1498736949706490017)
# Keyed by the canonical game code produced by core.sheets._detect_game.
TEAM_DIVIDER_ROLE_IDS: dict[str, int] = {
"CS2": CS2_DIVIDER_ROLE_ID,
"LoL": LOL_DIVIDER_ROLE_ID,
}
def _parse_admin_roles(raw: str) -> dict[int, set[int]]:
"""Parse DISCORD_ADMIN_ROLES env var as "guild_id:role_id[:role_id...],guild_id:role_id...".