# Discord Bot v2.0 SBA fantasy league Discord bot. discord.py with async Python, Pydantic models, FastAPI backend. ## Commands - Run: `python bot.py` - Test: `python -m pytest --tb=short -q` - Test specific: `python -m pytest tests/test_services.py -v` ## IMPORTANT: Patterns That Prevent Real Bugs ### Docker Hub Repository Name ``` manticorum67/major-domo-discordapp ``` There is NO DASH between "discord" and "app". Not `discord-app`, not `discordapp-v2`. ### Git Workflow NEVER commit directly to `main`. Always use feature branches. ```bash git checkout -b feature/name origin/main # or fix/name, refactor/name ``` PRs go to `main`. CI builds the Docker image and creates a CalVer tag on merge. ### Double Emoji in Embeds `EmbedTemplate.success/error/warning/info/loading()` auto-add emoji prefixes. - Do NOT put emoji in the `title` parameter of these methods (causes double emoji) - Use `EmbedTemplate.create_base_embed()` when you want custom emoji in titles ### Autocomplete Functions Define autocomplete as standalone functions OUTSIDE the class, not as methods. - See `commands/players/info.py:20-67` for canonical example ### Model Requirements - Database entities require `id` fields: `Player(id=123, ...)`, `Team(id=456, ...)` - Use explicit None checks (`if obj is None:`) not `if not obj:` - Use "Raise or Return" pattern - don't return Optional unless specifically required ### New Commands Must Use ```python from utils.decorators import logged_command from utils.logging import get_contextual_logger class MyCog(commands.Cog): def __init__(self, bot): self.bot = bot self.logger = get_contextual_logger(f'{__name__}.MyCog') # Required @discord.app_commands.command(name="example") @logged_command("/example") async def example(self, interaction, param: str): # Business logic only - decorator handles logging, timing, errors ``` ## Deployment & Troubleshooting ### Production - **Host**: `ssh akamai` → `cd container-data/major-domo` - **Container**: `major-domo-discord-app-1` - **Image**: `manticorum67/major-domo-discordapp` (no dash between discord and app) - **Health**: Process liveness only (no HTTP endpoint) - **CI/CD**: Gitea Actions — tag-triggered Docker builds (push a CalVer tag to release) ### Release Workflow 1. Create feature/fix branches off `main` (e.g., `fix/scorebug-bugs`) 2. Open a PR to `main` when ready — merging does NOT trigger a build 3. When ready to release: `git tag YYYY.M.BUILD && git push --tags` 4. CI builds Docker image, tags it with the version + `production`, notifies Discord 5. Deploy the new image to production (see `/deploy` skill) - **Other services on same host**: `sba_db_api`, `sba_postgres`, `sba_redis`, `sba-website-sba-web-1`, `pd_api` ### Logs - **Container logs**: `ssh akamai "docker logs --since 1h major-domo-discord-app-1"` - **Log file (in container)**: `/app/logs/discord_bot_v2.json` (JSON structured, rotating, 10MB max) - **Host mount**: `./logs/discord_bot_v2.json` ### Key Env Vars `BOT_TOKEN`, `API_TOKEN`, `DB_URL`, `GUILD_ID`, `LOG_LEVEL`, `ENVIRONMENT`, `REDIS_URL` (optional) ### Common Issues - Bot not responding → check `docker logs`, verify `BOT_TOKEN` and `GUILD_ID` - API errors → verify `DB_URL` points to correct database API and `API_TOKEN` matches - Redis errors are non-fatal (graceful fallback when `REDIS_URL` is empty) ## Dependencies ### Pinning Policy All dependencies are pinned to exact versions (`==`). This ensures every Docker build produces an identical image — a `git revert` actually rolls back to the previous working state. - **`requirements.txt`** — production runtime deps only (used by Dockerfile) - **`requirements-dev.txt`** — includes `-r requirements.txt` plus dev/test tools When installing for local development or running tests: ```bash pip install -r requirements-dev.txt ``` When upgrading a dependency, update BOTH the `==` pin and (if applicable) the comment in the file. Test before committing. Never use `>=` or `~=` constraints. ## API Reference - OpenAPI spec: https://sba.manticorum.com/api/openapi.json (use WebFetch for current endpoints) ## Sub-directory Documentation Each package has its own CLAUDE.md with detailed patterns: `commands/`, `services/`, `models/`, `views/`, `tasks/`, `tests/`, `utils/`