Commit Graph

357 Commits

Author SHA1 Message Date
Cal Corum
42b9fa5df2 Fix /player autocomplete timeout by using current season only
All checks were successful
Build Docker Image / build (pull_request) Successful in 57s
The all_seasons=True parameter causes the API search query to take 15+ seconds,
exceeding Discord's 3-second autocomplete timeout. Changed to all_seasons=False
to search only the current season, which is fast enough.

Users can still access historical players by manually typing the name and using
the season parameter in the /player command.

Fixes: discord.errors.NotFound 404 (error code: 10062): Unknown interaction

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 20:45:09 -06:00
cal
0bc1ebc354 Update VERSION
All checks were successful
Build Docker Image / build (pull_request) Successful in 2m37s
2026-02-06 02:26:32 +00:00
cal
9f6db12d5a Update VERSION
Some checks failed
Build Docker Image / build (pull_request) Failing after 13s
2026-02-06 02:25:13 +00:00
Cal Corum
310e685670 Update format of /cc response 2026-02-05 20:23:49 -06:00
cal
9f11401f8b Merge pull request 'bugfix/injury-team-null-errors' (#1) from bugfix/injury-team-null-errors into main
All checks were successful
Build Docker Image / build (push) Successful in 1m44s
Reviewed-on: #1
2026-02-05 22:54:26 +00:00
cal
e03ba79fa5 Update VERSION
All checks were successful
Build Docker Image / build (pull_request) Successful in 2m54s
2026-02-05 22:50:06 +00:00
Cal Corum
ac3cbebb9f Remove unused .mcp.json config file
Some checks failed
Build Docker Image / build (pull_request) Failing after 18s
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 15:14:36 -06:00
Cal Corum
bfe78fb7ac Clean up legacy CI/CD files and one-time scripts
Removed legacy CI/CD infrastructure:
- GitLab CI config (.gitlab-ci.yml, .gitlab/ directory)
- Manual build scripts (build-and-push.sh, BUILD_AND_PUSH.md)
- Unused Dockerfile variant (Dockerfile.versioned)

Removed outdated documentation:
- AGENTS.md (superseded by comprehensive CLAUDE.md files)

Removed one-time recovery scripts:
- scripts/ directory (week 19 transaction recovery - completed)
- test_real_data.py (ad-hoc testing script)

Note: Runtime artifacts (.coverage, htmlcov/, __pycache__/, etc.) are already
properly excluded via .gitignore and were not tracked in git.

All CI/CD is now handled by .gitea/workflows/docker-build.yml

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 15:09:24 -06:00
Cal Corum
c7f55d79e3 Fix injury commands player.team None errors and add Gitea CI/CD
- Fix /injury roll and /injury clear commands crashing when player.team is None
- Add team fetching logic after search_players() for all injury commands
- The search_players() API endpoint returns team as ID only (not nested object)
- Added null checks and explicit team fetching using team_service.get_team()

- Add Gitea Actions workflow for automated Docker builds
- Implements semantic version validation on PRs
- Builds and pushes to Docker Hub on main branch merges
- Sends Discord notifications on success/failure
- Generates 3 image tags: latest, v{VERSION}, v{VERSION}-{COMMIT}

Fixes AttributeError: 'NoneType' object has no attribute 'roster_type'
Fixes AttributeError: 'NoneType' object has no attribute 'thumbnail'

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 14:16:22 -06:00
Cal Corum
ab8bfa115f Fix /injury roll command crash when player.team is None
The search_players() API endpoint returns team as an ID only (not nested object),
causing player.team to be None. Added null check before accessing team.thumbnail.

Fixes AttributeError: 'NoneType' object has no attribute 'thumbnail'

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-04 21:50:43 -06:00
Cal Corum
6935465210 Bump version to 2.29.2 2026-02-01 21:28:31 -06:00
Cal Corum
060287b7ca Fix API parameter name: use 'demotion_week' instead of 'dem_week'
The API expects 'demotion_week' as the query parameter name, not 'dem_week'.
Updated service to send correct parameter name and tests to verify.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-01 21:27:52 -06:00
Cal Corum
c7820eaea0 Bump version to 2.29.1 2026-02-01 21:16:48 -06:00
Cal Corum
788b7b30fc Fix missing Optional import in transaction_freeze.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-01 21:16:25 -06:00
Cal Corum
dca629a279 Bump version to 2.29.0 2026-02-01 21:15:51 -06:00
Cal Corum
00f8f4f0aa Merge branch 'feature/add-dem-week-to-player-updates' 2026-02-01 21:13:09 -06:00
Cal Corum
be3dbf1f8d Add dem_week parameter to player team updates
- Add optional dem_week parameter to PlayerService.update_player_team()
- Transaction freeze sets dem_week to current.week + 2
- /ilmove command sets dem_week to current.week
- Draft picks (manual and auto) set dem_week to current.week + 2
- Backwards compatible - admin commands don't set dem_week
- Add 4 unit tests for dem_week scenarios
- Enhanced logging shows dem_week values

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-01 21:12:06 -06:00
Cal Corum
f4523b99f2 Clear confirmation message content on delete result
Prevents double emoji display by clearing the " Confirmed!" content
when showing the delete result embed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 16:40:03 -06:00
Cal Corum
b5365f01f9 Fix custom command delete permission check using wrong ID field
Changed from command.creator_id (database ID) to command.creator.discord_id
to properly compare against the deleter's Discord user ID.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 16:10:52 -06:00
Cal Corum
4fb3bcef51 Bump version to 2.28.1
Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-28 16:02:31 -06:00
Cal Corum
2ab82aa2bf Fix custom command delete not actually deleting from database
The delete confirmation was showing success but never calling the delete
service. Added the actual delete_command() call when user confirms.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-28 16:02:26 -06:00
Cal Corum
484042e8ae Bump version to 2.28.0
Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-28 15:45:47 -06:00
Cal Corum
cf5df1a619 Fix custom command mentions not triggering notifications
- Use channel.send() instead of followup.send() for custom command output
  (webhook-based followup messages don't trigger mention notifications)
- Add ephemeral "Sending..." confirmation to satisfy interaction response
- Add utils/mentions.py for converting text @mentions to Discord format
- Add tests for mention conversion utility

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-28 15:45:38 -06:00
Cal Corum
d6ec2a11ec Add AGENTS.md with coding guidelines for AI agents
Comprehensive guide covering:
- Build/lint/test commands including single test execution
- Code style: imports, formatting, types, naming, error handling
- Discord patterns: @logged_command, autocomplete, embed emojis
- Service layer abstraction rules
- Model patterns (from_api_data, required IDs)
- Testing with aioresponses and complete model data
- Critical rules for git, services, and commits

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-23 15:13:25 -06:00
Cal Corum
2881207ca4 Update CLAUDE.md docs for all-season player search feature
- Document new autocomplete behavior (deduplicated, all-season search)
- Add PlayerService.search_players() method signature with all_seasons parameter
- Update search logic flow documentation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-23 14:36:03 -06:00
Cal Corum
471cb88d1f Bump version to 2.27.0 2026-01-23 14:23:19 -06:00
Cal Corum
bf079eab83 Add all-season player search with deduplicated autocomplete
- PlayerService.search_players() now supports all_seasons=True to search across all 13 seasons
- Autocomplete shows unique player names (most recent season's team) instead of duplicates
- Command defaults to most recent season when no season parameter specified
- Users can specify season parameter for historical data

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-23 14:23:16 -06:00
Cal Corum
249c17a64c Add production deployment documentation to CLAUDE.md
- Production server: ssh akamai
- Container path: /root/container-data/major-domo
- Service name: discord-app
- Full release workflow documented

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:40:55 -06:00
Cal Corum
a891bb962a Bump version to 2.26.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:38:37 -06:00
Cal Corum
f007c5b870 Fix frozen flag bug and add Transaction Thaw Report for admins
Bug Fix:
- Fixed /dropadd transactions being marked frozen=True during thaw period
- Now uses current_state.freeze to set frozen flag correctly
- Transactions entered Sat-Sun are now unfrozen and execute Monday

New Feature - Transaction Thaw Report:
- Added data structures for thaw reporting (ThawReport, ThawedMove,
  CancelledMove, ConflictResolution, ConflictContender)
- Modified resolve_contested_transactions() to return conflict details
- Added _post_thaw_report() to post formatted report to admin channel
- Report shows thawed moves, cancelled moves, and conflict resolution
- Handles Discord's 2000 char limit with _send_long_report()

Tests:
- Updated test_views_transaction_embed.py for frozen flag behavior
- Added test for thaw period (freeze=False) scenario
- Updated test_tasks_transaction_freeze.py for new return values
- All tests passing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:35:48 -06:00
Cal Corum
fb76f1edb3 Fix profile commands package not returning expected tuple
The setup_profile_commands() function was returning None instead of the
expected (successful, failed, failed_modules) tuple, causing bot startup
to log "Failed to load profile package: cannot unpack non-iterable NoneType".

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 16:25:38 -06:00
Cal Corum
ee434c98f1 Fix weekly freeze/thaw automation - API params not being sent
Root cause: league_service.update_current_state() was calling self.patch()
without use_query_params=True. The API expected query params but received
JSON body, so database updates for week/freeze silently failed.

Changes:
- Add use_query_params=True to league_service.py:99
- Fix service layer violation in transaction_freeze.py - now uses
  player_service.update_player_team() instead of direct API client
- Bump version to 2.25.8

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 14:00:54 -06:00
Cal Corum
023810538a Bump version to 2.25.7 2026-01-07 22:45:19 -06:00
Cal Corum
6b35a14066 Add dev-only loaded dice command for testing /ab rolls
- New !loaded <d6> <2d6> <d20> [user_id] command for predetermined dice
- Loaded values consumed on next /ab roll (one-shot)
- Supports targeting other users by ID for testing
- Admin-restricted prefix commands (!loaded, !unload, !checkload)
- Self-contained in commands/dev/ package

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 22:45:01 -06:00
Cal Corum
889b3a4e2d Fix sWAR cap validation for /ilmove and /dropadd commands
- Add sWAR cap validation to TransactionBuilder.validate_transaction()
- Use team-specific salary_cap from Team.salary_cap field
- Fall back to config.swar_cap_limit (32.0) if team has no custom cap
- Add major_league_swar_cap field to RosterValidationResult
- Update major_league_swar_status to show / with cap limit
- Add 4 new tests for sWAR cap validation

This fixes a bug where IL moves could put a team over their sWAR cap
because the validation only checked roster counts, not sWAR limits.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-06 13:17:05 -06:00
Cal Corum
4bdfe3ee0a Fix injury commands failing to find certain players
Changed /injury roll, /injury set-new, and /injury clear to use
search_players() instead of get_players_by_name(). The /players?name=
API endpoint fails to find some players (e.g., Gunnar Henderson) while
the /players/search?q= endpoint works correctly.

This fixes the "Player Not Found" error when users try to clear
injuries for players that exist in the database.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 20:15:14 -06:00
Cal Corum
a056dced5c Bump version to 2.25.4
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 14:24:20 -06:00
Cal Corum
37bf797254 Fix critical week rollover bugs causing 60x freeze message spam
Three bugs identified and fixed:

1. Deduplication logic tracked wrong week (transaction_freeze.py:216-219)
   - Saved freeze_from_week BEFORE _begin_freeze() modifies current.week
   - Prevents re-execution when API returns stale data

2. _run_transactions() bypassed service layer (transaction_freeze.py:350-394)
   - Added get_regular_transactions_by_week() to transaction_service.py
   - Now properly filters frozen=false and cancelled=false
   - Uses Transaction model objects instead of raw dict access

3. CRITICAL: Hardcoded current_id=1 (league_service.py:88-106)
   - Current table has one row PER SEASON, not a single row
   - Was patching Season 3 (id=1) instead of Season 13 (id=11)
   - Now fetches actual current state ID before patching

Root cause: The hardcoded ID caused every PATCH to update the wrong
season's record, so freeze was never actually set to True on the
current season. This caused the dedup check to pass 60 times (once
per minute during hour 0).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 14:15:26 -06:00
Cal Corum
3ea743a489 Bump version to 2.25.3
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 22:03:35 -06:00
Cal Corum
a942475950 Fix pending transaction check to use week_start parameter
The API was returning keepers transactions (week=0) when querying for
week 2 transactions. Changed from 'week' to 'week_start' parameter to
properly filter out earlier weeks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 22:03:19 -06:00
Cal Corum
f48b83668a Bump version to 2.25.2
Release includes:
- Add pending transaction validation for /dropadd command
- Players already in a pending transaction cannot be added to another

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 17:20:12 -06:00
Cal Corum
3cbc904478 Add pending transaction validation for /dropadd command
Prevents players who are already claimed in another team's pending
transaction (frozen=false, cancelled=false) from being added to a new
transaction for the same week.

Changes:
- Add is_player_in_pending_transaction() to TransactionService
- Make TransactionBuilder.add_move() async with validation
- Add check_pending_transactions flag (default True for /dropadd)
- Skip validation for /ilmove and trades (check_pending_transactions=False)
- Add tests/conftest.py for proper test isolation
- Add 4 new tests for pending transaction validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-21 17:13:43 -06:00
Cal Corum
466c8985cb Restrict injury logging to player's team GMs only
Security fix: Remove user_id from ConfirmationView so only the player's
team GM(s) can click "Log Injury" button. Anyone can still run /injury roll
to see the result, but only authorized GMs can record it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 00:13:42 -06:00
Cal Corum
62541ac750 Add injury log posting and fix view interaction permissions
Features:
- Post injury announcements to #sba-network-news when injuries are logged
- Update #injury-log channel with two embeds:
  - All injuries grouped by Major League team with return dates
  - All injuries grouped by return week, sorted ascending
- Auto-purge old messages before posting updated injury log

Bug Fixes:
- Fix BaseView interaction_check logic that incorrectly rejected command users
  - Old: Rejected if (not user_id match) OR (not in responders)
  - New: Allow if (user_id match) OR (in responders)
- Filter None values from responders list (handles missing gmid2)

Changes:
- services/injury_service.py: Add get_all_active_injuries_raw() method
- utils/injury_log.py: New utility for injury channel posting
- views/modals.py: Call injury posting after successful injury logging
- views/base.py: Fix interaction authorization logic
- config.py: Update to Season 13 Players role

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 00:08:11 -06:00
Cal Corum
8ab5e025b2 Allow IL moves to post to transaction log during freeze period
IL moves (/ilmove) are intra-team transactions that should always be
visible immediately. Only scheduled transactions (/dropadd) need to
remain hidden during the freeze period.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-16 22:19:53 -06:00
Cal Corum
7a5e85323b Fix transaction freeze bypass - respect Current.freeze before posting to #transaction-log
Bug: Transactions were being posted to #transaction-log even when Current.freeze=True.
Transactions should only be posted when Current.freeze=False.

Fix: Added freeze state checks before calling post_transaction_to_log() in both
scheduled (/dropadd) and immediate (/ilmove) submission handlers.

When frozen:
- Transactions are still saved to DB with frozen=True
- NOT posted to #transaction-log (hidden until Saturday processing)
- User sees "Transaction saved during freeze period" message

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-15 17:47:33 -06:00
Cal Corum
151cf088da Fix draft cap validation using max_zeroes logic
During the draft, teams draft 32 players and then drop to 26. The cap
calculation must account for remaining draft picks:
- max_zeroes = 32 - projected_roster_size (remaining draft picks)
- players_counted = 26 - max_zeroes (how many current players count)

This allows teams to draft expensive players mid-draft knowing they'll
drop cheap ones later. Previously the code was using min(roster_size, 26)
which didn't account for future picks, causing false cap violations.

Example: WAI with 18 players drafting 19th:
- Old (broken): players_counted = 19, sum all players
- New (fixed): max_zeroes = 13, players_counted = 13, only cheapest 13 count

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-12 21:42:42 -06:00
Cal Corum
1af7c82353 Fix off-by-one error in draft recent picks display
The get_recent_picks service method was subtracting 1 from overall_end,
but callers were already passing currentpick - 1. This caused the "Last 5
picks" list on the OnTheClock embed to skip the most recently completed
pick (showing picks 2-6 before current instead of 1-5).

Removed the extra subtraction in the service method since callers already
handle the exclusivity of the overall_end parameter.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-12 19:14:53 -06:00
Cal Corum
95d18d603e Fix /draft command to post player cards to result channel
The manual /draft command was only posting draft cards to the ping_channel,
but not to the result_channel. The auto-draft task correctly posted to both
channels. This fix ensures manual draft picks also post player cards to the
configured result channel for consistent draft result tracking.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-12 19:08:23 -06:00
Cal Corum
08fbd0a812 Fix /draft autocomplete sending display text instead of value
When users select from autocomplete dropdown, Discord sometimes sends
the display text (e.g., "Mason Miller (RP) - 2.50 sWAR") instead of
the value ("Mason Miller"). Added _parse_player_name() to strip the
position and sWAR info from the input.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 18:59:33 -06:00