Commit Graph

311 Commits

Author SHA1 Message Date
cal
6c49233392 Merge pull request 'fix: replace broken interaction_check decorator with MaintenanceAwareTree subclass' (#83) from fix/maintenance-mode-interaction-check into main
All checks were successful
Build Docker Image / build (push) Successful in 49s
Reviewed-on: #83
2026-03-17 17:34:15 +00:00
Cal Corum
9a4ecda564 Merge origin/main into fix branch to resolve conflict
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m3s
Keep both the type: ignore annotation and the logger.info call
in admin_maintenance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:32:38 -05:00
Cal Corum
d295f27afe fix: replace broken @self.tree.interaction_check with MaintenanceAwareTree subclass
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m11s
The previous code attempted to register a maintenance mode gate via
@self.tree.interaction_check inside setup_hook.  That pattern is invalid
in discord.py — interaction_check is an overridable method on CommandTree,
not a decorator.  The assignment was silently dropped, making maintenance
mode a no-op and producing a RuntimeWarning about an unawaited coroutine.

Changes:
- Add MaintenanceAwareTree(discord.app_commands.CommandTree) that overrides
  interaction_check: blocks non-admins when bot.maintenance_mode is True,
  always passes admins through, no-op when maintenance mode is off
- Pass tree_cls=MaintenanceAwareTree to super().__init__() in SBABot.__init__
- Add self.maintenance_mode: bool = False to SBABot.__init__
- Update /admin-maintenance command to actually toggle bot.maintenance_mode
- Add tests/test_bot_maintenance_tree.py with 8 unit tests covering all
  maintenance mode states, admin pass-through, DM context, and missing attr

Closes #82

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 12:25:01 -05:00
cal
0a2df0f36e Merge pull request 'Merge next-release into main' (#81) from next-release into main
All checks were successful
Build Docker Image / build (push) Successful in 53s
Reviewed-on: #81
2026-03-17 16:44:42 +00:00
Cal Corum
910a27e356 Merge main into next-release
All checks were successful
Build Docker Image / build (push) Successful in 3m26s
Build Docker Image / build (pull_request) Successful in 58s
Resolve conflict in views/trade_embed.py: keep main's hotfix
(emoji-stripped UI, inline validation errors) and apply next-release's
import refactor (lazy imports hoisted to top-level).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:28:05 -05:00
cal
541380acdf Merge pull request 'fix: re-fetch existing transactions on each validation' (#72) from fix/refresh-existing-transactions-on-validation into next-release
All checks were successful
Build Docker Image / build (push) Successful in 1m24s
Build Docker Image / build (pull_request) Successful in 57s
Reviewed-on: #72
2026-03-11 16:27:55 +00:00
cal
514797b787 Merge pull request 'fix: prevent partial DB writes on scorecard submission failure' (#80) from fix/scorecard-submission-resilience-v2 into next-release
Some checks failed
Build Docker Image / build (push) Has been cancelled
Reviewed-on: #80
2026-03-11 16:27:28 +00:00
Cal Corum
461112b2f8 fix: prevent partial DB writes and show detailed errors on scorecard submission failure
Read all spreadsheet data (plays, box score, pitching decisions) before any
database writes so formula errors like #N/A don't leave the DB in a partial
state. Also preserve SheetsException detail through the error chain and show
users the specific cell/error instead of a generic failure message.

Closes #78

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 20:55:10 -05:00
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
2f7b82e377 Merge pull request 'chore: pin all Python dependency versions in requirements.txt (#76)' (#77) from ai/major-domo-v2-76 into main
All checks were successful
Build Docker Image / build (push) Successful in 58s
Reviewed-on: #77
2026-03-10 14:05:47 +00:00
Cal Corum
88edd1fa10 chore: pin all Python dependency versions in requirements.txt (#76)
All checks were successful
Build Docker Image / build (pull_request) Successful in 2m58s
- Pin redis==7.3.0 and move to requirements.txt (production)
- Create requirements-dev.txt with all dev/test deps pinned to exact versions
  (pytest-mock==3.15.1, black==26.1.0, ruff==0.15.0)
- Remove dev/test tools from requirements.txt (not needed in Docker image)
- Document pinning policy and requirements-dev.txt usage in CLAUDE.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 01:03:27 -05:00
cal
9ba0713887 Merge pull request 'fix: trailing slash on all collection POST calls' (#75) from fix/trailing-slash-307-redirect into main
All checks were successful
Build Docker Image / build (push) Successful in 51s
Reviewed-on: #75
2026-03-10 00:42:16 +00:00
Cal Corum
ba55ed3109 fix: add trailing slashes to all collection POST calls
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m16s
Ensures all client.post() calls to collection endpoints include
trailing slashes, matching the standardized database API routes.
Covers BaseService.create(), TransactionService, InjuryService,
and DraftListService POST calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:34:36 -05:00
cal
269429254f Merge pull request 'fix: targeted trailing slashes for POST endpoints (hotfix)' (#74) from fix/trailing-slash-307-redirect into main
All checks were successful
Build Docker Image / build (push) Successful in 52s
Reviewed-on: #74
2026-03-09 22:52:29 +00:00
Cal Corum
f6a25aa16d fix: use targeted trailing slashes instead of universal (hotfix)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m7s
Reverts universal trailing slash in _build_url which broke custom_commands
endpoints (401 on /execute/). Instead, add trailing slashes only to the
two batch POST endpoints (plays/, decisions/) that need them to avoid
307 redirects dropping request bodies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 17:50:58 -05:00
cal
52ab92523c Merge pull request 'fix: add trailing slashes to prevent 307 redirects dropping POST bodies' (#73) from fix/trailing-slash-307-redirect into main
All checks were successful
Build Docker Image / build (push) Successful in 53s
Reviewed-on: #73
2026-03-09 22:26:52 +00:00
Cal Corum
9379ba587a fix: add trailing slashes to API URLs to prevent 307 redirects dropping POST bodies
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m13s
The FastAPI server returns 307 redirects for URLs without trailing slashes.
aiohttp follows these redirects but converts POST to GET, silently dropping
the request body. This caused play-by-play and decision data from
/submit-scorecard to never be persisted to the database despite the API
returning success.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 17:25:08 -05: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
556a30c397 fix: re-fetch existing transactions on each validation
The TransactionBuilder cached pre-existing transactions on first load
and never refreshed them. This meant transactions submitted by other
sessions (or newly visible after API fixes) were invisible for the
lifetime of the builder session, causing incorrect roster projections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 08:10: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
b3b8cd9683 Merge pull request 'fix: show validation errors in trade embed Quick Status' (#70) from fix/trade-embed-errors-and-cleanup into main
All checks were successful
Build Docker Image / build (push) Successful in 50s
Reviewed-on: #70
2026-03-08 16:29:06 +00:00
Cal Corum
58fe9f22de fix: trade validation now checks against next week's projected roster
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m5s
validate_trade() was passing next_week=None to each team's
validate_transaction(), which skipped load_existing_transactions()
entirely. Trades were validated against the current roster only,
ignoring pending /dropadd transactions for next week.

Now auto-fetches current week from league_service and passes
next_week=current_week+1, matching /dropadd validation behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:27:03 +00:00
Cal Corum
e98a658fde fix: show actual validation errors in trade embed Quick Status
Quick Status previously only showed "X errors found" with no details.
Now lists each error and suggestion inline. Also stripped all emoji
from embed titles, field names, values, buttons, and messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 16:27:03 +00: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
111a6cf338 Merge pull request 'fix: replace create_item_in_table placeholder with direct endpoint call (#30)' (#69) from ai/major-domo-v2#30 into main
All checks were successful
Build Docker Image / build (push) Successful in 57s
Reviewed-on: #69
2026-03-07 03:25:08 +00:00
Cal Corum
18ae65a8e2 fix: replace create_item_in_table placeholder with direct endpoint call (#30)
All checks were successful
Build Docker Image / build (pull_request) Successful in 1m10s
Remove the generic placeholder method from BaseService and replace the
single call site in CustomCommandsService.get_or_create_creator with a
direct client.post("custom_commands/creators", ...) call, consistent
with how _update_creator_stats and _update_creator_info already work.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 14:04:05 -06: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