forked from sass/tipibot
feat(teams): add opt-in /teamsync reposition to tidy existing team roles
Creation-time placement only positions NEW team roles. Team roles made before divider placement existed (sitting at the bottom of the role list) stayed put. Add `reposition_team_roles(guild)` and expose it via `/teamsync reposition:true` (off by default, so the hourly task never reorders roles on its own). It moves each EXISTING team role under its game's divider, sheet-driven: - a role's game/divider comes from sheets.get_game_for_team; - roles whose team is no longer in the sheet (or game unknown) are left alone; - idempotent: a role already within its section band (below its own divider, above the next divider down) is skipped, so re-runs move nothing. Adds RepositionSummary, TEAMSYNC_UI/OPT strings, and tests. 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:
@@ -273,3 +273,46 @@ def test_new_team_role_without_known_divider_is_left_in_place(monkeypatch):
|
||||
assert result.created == "NEWTEAM" # still created, just not moved
|
||||
new_role = next(r for r in guild.roles if r.name == "NEWTEAM")
|
||||
assert new_role.position == 0 # default, untouched
|
||||
|
||||
|
||||
# --- reposition_team_roles (opt-in cleanup of existing roles) ---------------
|
||||
|
||||
def test_reposition_moves_out_of_section_roles_and_skips_placed_ones(monkeypatch):
|
||||
cs2_div = FakeRole(100, "CS2 divider", position=20)
|
||||
lol_div = FakeRole(200, "LoL divider", position=10)
|
||||
genesis = FakeRole(1, "GENESIS", position=2) # CS2 team stuck at bottom
|
||||
pushing = FakeRole(2, "Pushing 30s", position=5) # LoL team already in band
|
||||
unrelated = FakeRole(3, "Moderator", position=30) # not a team - ignored
|
||||
guild = FakeGuild([cs2_div, lol_div, genesis, pushing, unrelated])
|
||||
|
||||
games = {"GENESIS": "CS2", "Pushing 30s": "LoL"}
|
||||
monkeypatch.setattr(sheets, "all_team_names", lambda: {"GENESIS", "Pushing 30s"})
|
||||
monkeypatch.setattr(sheets, "get_game_for_team", lambda t: games.get(t))
|
||||
monkeypatch.setattr(config, "TEAM_DIVIDER_ROLE_IDS", {"CS2": 100, "LoL": 200})
|
||||
|
||||
repo = run(member_sync.reposition_team_roles(guild))
|
||||
|
||||
assert repo.scanned == 2 # only the two team roles
|
||||
assert repo.moved == 1 # only GENESIS was out of place
|
||||
assert repo.moves == ["GENESIS -> CS2"]
|
||||
assert genesis.position == 20 # moved under the CS2 divider
|
||||
assert pushing.position == 5 # already in its band, untouched
|
||||
assert unrelated.position == 30 # non-team role never considered
|
||||
|
||||
|
||||
def test_reposition_leaves_role_whose_team_is_not_in_sheet(monkeypatch):
|
||||
cs2_div = FakeRole(100, "CS2 divider", position=20)
|
||||
lol_div = FakeRole(200, "LoL divider", position=10)
|
||||
ghost = FakeRole(1, "GhostTeam", position=2) # a team role, but gone from sheet
|
||||
guild = FakeGuild([cs2_div, lol_div, ghost])
|
||||
|
||||
# Team no longer registered -> not in all_team_names, so never scanned/moved.
|
||||
monkeypatch.setattr(sheets, "all_team_names", lambda: {"GENESIS"})
|
||||
monkeypatch.setattr(sheets, "get_game_for_team", lambda t: None)
|
||||
monkeypatch.setattr(config, "TEAM_DIVIDER_ROLE_IDS", {"CS2": 100, "LoL": 200})
|
||||
|
||||
repo = run(member_sync.reposition_team_roles(guild))
|
||||
|
||||
assert repo.scanned == 0
|
||||
assert repo.moved == 0
|
||||
assert ghost.position == 2 # left exactly where it was
|
||||
|
||||
Reference in New Issue
Block a user