Closes#147
Adds a "Refractor Progress" field to the game summary embed showing:
- Cards that tiered up during this game (⬆ Name → Tier Name)
- Cards currently ≥80% toward their next tier on either team (◈ Name (pct%))
The field is omitted entirely when there is nothing to show.
Implementation:
- _run_post_game_refractor_hook() now returns evo_result (or None on failure)
- New _build_refractor_progress_text() fetches close-to-tier cards from both
teams via refractor/cards?progress=close and formats the combined output
- complete_game() adds the field between Rewards and Highlights sections
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#144
- build_tier_up_embed() accepts optional image_url and calls set_image() when provided
- notify_tier_completion() accepts optional image_url and passes it through
- _trigger_variant_renders() now captures the render response image_url per player and returns a player_id->image_url dict
- _run_post_game_refractor_hook() triggers renders first (to obtain image URLs), then sends notifications with card art included
- Updated test_post_game_refractor_hook.py to reflect new render-before-notify ordering and image_url kwarg in notify calls
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract _run_post_game_refractor_hook() from complete_game() so the hook
logic can be tested directly without a live game session. Add 13 tests
covering endpoint ordering, tier-up notification dispatch, variant render
triggers, and non-fatal error handling.
Closes#148
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#98
Replace sequential await-in-list-comprehension with asyncio.gather() so
all card embed fetches run concurrently. Cuts 50 sequential DB round-trips
(5 packs × 5 cards × 2 calls each) down to ~2 concurrent batches.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#101
Replace sequential for-loop with asyncio.gather() so all scout
opportunities are created concurrently. Remove asyncio.sleep(2) that
added ~8s of post-display delay for multi-pack opens. create_scout_opportunity()
already guards against empty pack_cards with an early return.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces bare `except Exception: pass` with `logging.debug(..., exc_info=True)`
so badge lookup failures are traceable in logs without affecting card display.
Closes#150
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix incorrect command names (/card→/player, /roster→/team, /buy→/buy card-by-name,
/openpack→/open-packs, /scout→/scout-tokens). Update execution checklist with full
Playwright test session results — API tests, filter tests, pagination, edge cases
all passing. Note badge propagation design gap and REF-22 fix (discord#141).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adminer is exposed on host port 8080, shadowing the bot health endpoint.
Change health server default to 8081 to avoid the conflict.
Closes#130
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When page exceeds total pages, API returns empty items but non-zero
count. Now detects this case and re-fetches the last valid page.
Closes#141
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes#138
The test suite passes `team` to _build_refractor_response but the
function signature did not accept it. Adds `team: dict = None` so
tests for the refractor card image collection view pass without
changing any existing behavior.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use `variant is None` instead of `not variant` to avoid skipping
variant 0 tier-ups (0 is falsy in Python)
- Remove unused `team` parameter from _build_refractor_response
- Update tests to match
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds optional refractor_tier parameter to the /player slash command.
When provided: looks up the user's team refractor data, shows the
evolved card image if available, triggers on-demand render if image
not yet generated, or shows top 5 refractor cards as fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After refractor tier-ups, the bot hits the card render URL for each
variant card to trigger Playwright render + S3 upload as a side
effect. Fire-and-forget — failures are logged but never raised.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tier boosts shipped in Phase 2 — the teaser field in the T4 tier-up
embed was outdated. Remove it and update tests + test plan to match.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
docker-compose.yml contains hardcoded credentials (BOT_TOKEN, API_TOKEN,
RESTART_WEBHOOK_URL) and should never be committed. The *compose.yml gitignore
rule already excluded it but docker-compose.example.yml was not provided as a
reference for contributors.
- Add !docker-compose.example.yml negation to .gitignore so example is tracked
- Add docker-compose.example.yml with placeholder values for all secrets
Closes paper-dynasty-database#9
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Document all required environment variables for running the Discord bot,
including bot token, API credentials, database config, and webhook URL.
References paper-dynasty-database#9
Port the Check-In Player pack fix from the hotfix branch to the legacy
economy.py cog (which production currently loads instead of economy_new).
- Filter auto-open pack types from the manual open-packs menu
- Add pretty_name fallback for hyphenated pack type names
- Add ruff noqa for pre-existing star import warnings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Check-In Player packs (auto-opened by daily check-in) could end up orphaned
in inventory if roll_for_cards failed. The open-packs command crashed because:
1. The hyphenated pack type name bypassed the pretty_name logic, producing an
empty select menu that Discord rejected (400 Bad Request)
2. Even if displayed, selecting it would raise KeyError in the callback since
"Check-In Player".split("-") doesn't match any known pack type token
Fixes:
- Filter auto-open pack types out of the manual open-packs menu
- Add fallback for hyphenated pack type names in pretty_name logic
- Replace KeyError with graceful user-facing message for unknown pack types
- Change "contact an admin" to "contact Cal" in all user-facing messages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Tier labels as suffix tags: **Name** — Base Chrome [T1] (T0 gets no suffix)
- Compact progress line: bar value/threshold (pct) — removed formula and tier arrow
- Fully evolved shows `MAX` instead of FULLY EVOLVED
- Deleted unused FORMULA_LABELS dict
- Added _FULL_BAR constant, moved T0-branch lookups into else
- Fixed mock API shape in test (cards → items)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Unicode symbols (○ ◈ ◆ ✦ ★) were too similar to distinguish at a glance.
Now uses T1/T2/T3/T4★ prefixes with no prefix for base cards (T0).
Summary header reads "Base: 1 T1: 9 — 64 total" instead of cryptic symbols.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When filters are active and return 0 results, show which filters were
applied and suggest removing them, instead of the misleading
"No refractor data found for your team."
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>