Commit Graph

289 Commits

Author SHA1 Message Date
cal
bebe25b9dd Merge pull request 'fix: prefix trade validation errors with team abbreviation' (#71) from fix/trade-errors-show-team-abbrev into next-release
All checks were successful
Build Docker Image / build (push) Successful in 3m5s
Reviewed-on: #71
2026-03-10 15:46:42 +00:00
cal
4314b67537 Merge pull request 'feat: add is_admin() helper to utils/permissions.py (#55)' (#64) from ai/major-domo-v2#55 into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m11s
Reviewed-on: #64
2026-03-09 14:38:07 +00:00
Cal Corum
c41166d53c feat: add is_admin() helper to utils/permissions.py (#55)
Add centralized `is_admin(interaction)` helper that includes the
`isinstance(interaction.user, discord.Member)` guard, preventing
AttributeError in DM contexts.

Use it in `can_edit_player_image()` which previously accessed
`guild_permissions.administrator` directly without the isinstance
guard. Update the corresponding test to mock the user with
`spec=discord.Member` so the isinstance check passes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 09:37:22 -05:00
Cal Corum
db08d0eaa4 fix: auto-fetch next_week for trade validation against projected roster
Trade validation now automatically fetches the current week from
league_service and validates against next week's projected roster
(including pending transactions), matching /dropadd behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:48:15 -05:00
Cal Corum
8ee35e564c fix: prefix trade validation errors with team abbreviation
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m5s
Roster-level errors, warnings, and suggestions now display as
"[BSG] Too many ML players" so users know which team each issue
applies to.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:37:39 -05:00
cal
ee324693b1 Merge pull request 'ci: Use docker-tags composite action for multi-channel release support' (#68) from ci/docker-tags-multi-channel into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m6s
Reviewed-on: #68
2026-03-07 03:33:26 +00:00
cal
1a6300854e Merge pull request 'test: implement test_validate_transaction_exception_handling (#35)' (#67) from ai/major-domo-v2#35 into next-release
Reviewed-on: #67
2026-03-07 03:32:22 +00:00
cal
b6b997c15e Merge pull request 'fix: reuse persistent aiohttp.ClientSession in GiphyService (#26)' (#66) from ai/major-domo-v2-26 into next-release
Reviewed-on: #66
2026-03-07 03:31:02 +00:00
cal
26a22aae4f Merge pull request 'refactor: extract duplicate command hash logic into _compute_command_hash (#31)' (#65) from ai/major-domo-v2-31 into next-release
Reviewed-on: #65
2026-03-07 03:28:28 +00:00
cal
f048a3c04b Merge pull request 'fix: update roster labels to use Minor League and Injured List (#59)' (#63) from ai/major-domo-v2-59 into next-release
Reviewed-on: #63
2026-03-07 03:26:15 +00:00
Cal Corum
72df98936b ci: Use docker-tags composite action for multi-channel release support
Adds next-release branch trigger and replaces separate dev/production
build steps with the shared docker-tags action for tag resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 15:41:05 -06:00
Cal Corum
ebec9a720b test: implement test_validate_transaction_exception_handling (#35)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m6s
Removes the @pytest.mark.skip and implements the test using a
patched RosterValidation that raises on the first call, triggering
the except clause in validate_transaction. Verifies the method
returns is_legal=False with a descriptive error message.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 02:04:34 -06:00
Cal Corum
e9dd318e5a perf: reuse persistent aiohttp.ClientSession in GiphyService (#26)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m5s
Both get_disappointment_gif and get_gif previously created a new
ClientSession per call. Replace with a lazily-initialised shared
session stored on the instance, eliminating per-call TCP handshake
and DNS overhead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 01:32:52 -06:00
Cal Corum
2242140dcd refactor: extract duplicate command hash logic into _compute_command_hash (#31)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m6s
Both _should_sync_commands and _save_command_hash contained an identical
~35-line block building the command data list and computing the SHA-256 hash.
Extracted into a new synchronous helper method _compute_command_hash() that
both callers now delegate to.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 00:32:03 -06:00
Cal Corum
346e36bfc6 fix: update roster labels to use Minor League and Injured List (#59)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m10s
- Add section headers (Active Roster, Minor League, Injured List) to the
  main summary embed in _create_roster_embeds so each roster section is
  clearly labeled for users
- Fix incorrect docstring in team_service.get_team_roster that had the
  shortil/longil mapping backwards

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 22:04:57 -06:00
cal
88ad58fa12 Merge pull request 'fix: implement actual maintenance mode flag in /admin-maintenance (#28)' (#62) from ai/major-domo-v2-28 into next-release
Reviewed-on: #62
2026-03-03 22:08:19 +00:00
Cal Corum
e3610e84ea fix: implement actual maintenance mode flag in /admin-maintenance (#28)
- Add `maintenance_mode: bool = False` flag to `SBABot.__init__`
- Register a global `@tree.interaction_check` that blocks non-admin users
  from all commands when maintenance mode is active
- Update `admin_maintenance` command to set `self.bot.maintenance_mode`
  and log the state change, replacing the no-op placeholder comment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 22:08:02 +00:00
cal
bc8a256b14 Merge pull request 'fix: refresh roster data before validation to prevent stale cache' (#60) from hotfix/stale-roster-cache into next-release
Reviewed-on: #60
2026-03-02 21:06:59 +00:00
Cal Corum
ffa0366441 refactor: invalidate roster cache after submission instead of force-refreshing
Simplify review found that force_refresh=True on every validate_transaction()
call caused redundant API fetches on every embed render and button press.

Instead, invalidate the roster cache after successful submit_transaction() so
the next operation fetches fresh data. This preserves the cache for normal
interaction flows while still preventing stale data after submissions.

Also adds type annotation for roster_svc DI parameter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:06:00 +00:00
Cal Corum
c70669d474 fix: refresh roster data before validation to prevent stale cache
TransactionBuilder cached roster data indefinitely via _roster_loaded flag,
causing validation to use stale counts when builders persisted across multiple
/ilmove invocations. Now validate_transaction() always fetches fresh roster
data. Also adds dependency injection for roster_service to improve testability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:06:00 +00:00
cal
6e4191f677 Merge pull request 'refactor: move 42 unnecessary lazy imports to top-level' (#58) from refactor/remove-unnecessary-lazy-imports into next-release
Reviewed-on: #58
2026-03-02 20:48:26 +00:00
Cal Corum
c961ea0dea docs: clarify git branching workflow in CLAUDE.md
Branch from next-release for normal work, main only for hotfixes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:42:18 -06:00
Cal Corum
858663cd27 refactor: move 42 unnecessary lazy imports to top-level across codebase
Codebase audit identified ~50 lazy imports. Moved 42 unnecessary ones to
top-level imports — only keeping those justified by circular imports,
init-order dependencies, or optional dependency guards. Updated test mock
patch targets where needed. See #57 for remaining DI candidates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:35:23 -06:00
cal
677dd3b773 Merge pull request 'fix: auto-detect player roster type in trade commands' (#56) from fix/trade-from-roster-detection into next-release 2026-03-02 19:14:42 +00:00
cal
ced67a5eef Merge pull request 'feat: add team ownership verification to /injury commands (closes #18)' (#53) from fix/injury-team-ownership-check into next-release 2026-03-02 19:14:40 +00:00
Cal Corum
58043c996d fix: auto-detect player roster type in trade commands instead of assuming ML
/trade add-player hardcoded from_roster=MAJOR_LEAGUE for all players,
causing incorrect transaction records when trading MiL/IL players. This
cascaded into false roster validation errors for other teams' /dropadd
commands because pre-existing transaction processing misidentified which
roster a player was leaving from.

Now looks up the player's actual team and calls roster_type() to determine
the correct source roster. Same fix applied to /trade supplementary.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 23:29:01 -06:00
Cal Corum
99489a3c42 feat: add team ownership verification to /injury set-new and /injury clear (closes #18)
Prevents users from managing injuries for players not on their team.
Admins bypass the check; org affiliates (MiL/IL) are recognized.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:59:58 -06:00
cal
98d47a1262 Merge pull request 'fix: key plays score text shows "tied at X" correctly (closes #48)' (#52) from fix/key-plays-tied-score into next-release
Reviewed-on: #52
2026-03-01 21:38:33 +00:00
Cal Corum
0daa6f4491 fix: key plays score text shows "tied at X" instead of "Team up X-X" (closes #48)
The else branch in descriptive_text() caught both "away leading" and
"tied" cases, always overwriting the tied text. Changed to if/elif/else
so tied scores display correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:36:38 -06:00
cal
f7a65706a1 Merge pull request 'next-release' (#51) from next-release into main
All checks were successful
Build Docker Image / build (push) Successful in 1m0s
Reviewed-on: #51
2026-03-01 20:56:38 +00:00
cal
46afbf25e0 Merge pull request 'fix: roster validation includes org affiliate transactions' (#50) from fix/roster-validation-org-affiliates into next-release
All checks were successful
Build Docker Image / build (pull_request) Successful in 4m10s
Reviewed-on: #50
2026-03-01 20:50:21 +00:00
Cal Corum
aa27769ed6 fix: roster validation now includes org affiliate transactions (closes #49)
load_existing_transactions only queried for the base team abbreviation
(e.g. "POR"), missing trades involving MiL/IL affiliates ("PORMIL",
"PORIL"). This caused false "too many players" errors when a pending
trade would have cleared a roster spot.

- get_team_transactions now accepts Union[str, List[str]] for team_abbrev
- load_existing_transactions queries all org affiliates [BASE, BASEMiL, BASEIL]
- Added 5 tests covering the fix and backwards compatibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:45:21 -06:00
cal
a80addc742 Merge pull request 'next-release' (#47) from next-release into main
All checks were successful
Build Docker Image / build (push) Successful in 46s
Reviewed-on: #47
2026-02-22 22:33:35 +00:00
cal
22c7f841e8 Merge branch 'main' into next-release
All checks were successful
Build Docker Image / build (pull_request) Successful in 48s
2026-02-22 22:31:07 +00:00
cal
e280928b4d Merge pull request 'feat: include current week number in weekly-info channel post' (#46) from feat/weekly-info-current-week into next-release
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m10s
Reviewed-on: #46
2026-02-22 22:22:00 +00:00
Cal Corum
b7a88844b6 feat: include current week number in weekly-info channel post
The #weekly-info message already shows season and game times but not
which week it is, making managers check elsewhere for that context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:20:08 -06:00
cal
1df9527697 Merge pull request 'fix: use explicit America/Chicago timezone for freeze/thaw scheduling' (#45) from fix/utc-timezone-scheduling into next-release
Reviewed-on: #45
2026-02-22 22:16:54 +00:00
Cal Corum
8a1a957c2a fix: use explicit America/Chicago timezone for freeze/thaw scheduling
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m16s
The production container has ambiguous timezone config — /etc/localtime
points to Etc/UTC but date reports CST. The transaction freeze/thaw task
used datetime.now() (naive, relying on OS timezone), causing scheduling
to fire at unpredictable wall-clock times.

- Add utils/timezone.py with centralized Chicago timezone helpers
- Fix tasks/transaction_freeze.py to use now_chicago() for scheduling
- Fix utils/logging.py timestamp to use proper UTC-aware datetime
- Add 14 timezone utility tests
- Update freeze task tests to mock now_chicago instead of datetime

Closes #43

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:00:22 -06:00
Cal Corum
a668a3505c docs: add release workflow section to CLAUDE.md
Documents the next-release staging branch pattern used for
batching changes before merging to main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:59:07 -06:00
cal
12fe600e83 Merge pull request 'next-release' (#42) from next-release into main
All checks were successful
Build Docker Image / build (push) Successful in 50s
Reviewed-on: #42
2026-02-20 20:28:15 +00:00
Cal Corum
d1a6b57ccd fix: scorebug stale data, win probability parsing, and read-failure tolerance (closes #39, #40)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m14s
#40: ScorecardTracker cached data in memory at startup — background task never
saw newly published scorecards. Fixed by reloading from disk on every read.

#39: Win percentage defaulted to 50% when unavailable, showing a misleading
50/50 bar. Now defaults to None with "unavailable" message in embed. Parsing
handles decimal (0.75), percentage string, and empty values. Also fixed
orientation bug where win% was always shown as home team's even when the
sheet reports the away team as the leader.

Additionally: live scorebug tracker now distinguishes between "all games
confirmed final" and "sheet read failures" — transient Google Sheets errors
no longer hide the live scores channel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:14:23 -06:00
Cal Corum
67f9c734b0 Merge branch 'fix/quick-wins-batch' into next-release 2026-02-20 13:14:49 -06:00
Cal Corum
9cd577cba1 fix: batch quick-wins — 4 issues resolved (closes #37, #27, #25, #38)
- #37: Fix stale comment in transaction_freeze.py referencing wrong moveid format
- #27: Change config.testing default from True to False (was masking prod behavior)
- #25: Replace deprecated asyncio.get_event_loop() with get_running_loop()
- #38: Replace naive datetime.now() with timezone-aware datetime.now(UTC) across
  7 source files and 4 test files to prevent subtle timezone bugs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:48:16 -06:00
Cal Corum
f64fee8d2e fix: remove 226 unused imports across the codebase (closes #33)
Ran `ruff check --select F401 --fix` to auto-remove 221 unused imports,
manually removed 4 unused `import discord` from package __init__.py files,
and fixed test import for DISAPPOINTMENT_TIERS to reference canonical location.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:35:04 -06:00
Cal Corum
a44d037611 Merge branch 'fix/security-issues' into next-release 2026-02-20 10:39:47 -06:00
Cal Corum
f4be20afb3 fix: address 7 security issues across the codebase
- Remove hardcoded Giphy API key from config.py, load from env var (#19)
- URL-encode query parameters in APIClient._add_params (#20)
- URL-encode Giphy search phrases before building request URLs (#21)
- Replace internal exception details with generic messages to users (#22)
- Replace all bare except: with except Exception: (#23)
- Guard interaction.guild access in has_player_role (#24)
- Replace MD5 with SHA-256 for command change detection hash (#32)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 09:54:53 -06:00
Cal Corum
5af62171da chore: remove obsolete MoveAction test stubs
Closes #16

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 22:28:47 -06:00
Cal Corum
9e43ffa1c1 feat: add local deploy script for production deploys
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m13s
Automates the SSH-to-akamai deploy workflow: pulls latest image,
restarts the container, and verifies health. Includes pre-deploy
checks (dirty git warning, confirmation prompt) and prints a
rollback command if the image changed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:45:56 -06:00
cal
eaaa9496a3 Merge pull request 'fix: ContextualLogger crashes when callers pass exc_info=True' (#14) from fix/contextual-logger-exc-info into main
All checks were successful
Build Docker Image / build (push) Successful in 48s
Reviewed-on: #14
2026-02-20 03:26:39 +00:00
cal
9db128bd27 Merge branch 'main' into fix/contextual-logger-exc-info
All checks were successful
Build Docker Image / build (pull_request) Successful in 46s
2026-02-20 03:25:32 +00:00