EmperorFred/README.md

238 lines
8.1 KiB
Markdown
Raw Normal View History

2025-12-05 15:25:35 +00:00
# EmperorFred
2025-12-06 02:21:47 +00:00
Multi-platform moderation bot for Twitch and Discord. This repository contains two separate bots (Twitch and Discord) that can be run concurrently in a single Python process using asyncio.
The project uses:
- Python 3.13+
- discord.py (Discord bot)
- TwitchIO v3 with EventSub over WebSocket (Twitch bot)
- SQLAlchemy (database)
- python-dotenv (env config)
- requests
- uv as the package manager (pyproject.toml + uv.lock)
## Overview
Entry point: `bot.py`
`bot.py` loads environment variables (via `python-dotenv`), then starts both bots concurrently:
- Discord bot class: `discord_bot.bot.EmperorFredDiscordBot`
- Twitch bot class: `twitch_bot.bot.TwitchBot`
Both bots expose simple commands and support a controlled in-process restart via a shared `RestartController`.
## Requirements
- Python 3.13 or newer
- uv (recommended) or pip
Project dependencies are declared in `pyproject.toml`. A lockfile `uv.lock` is present.
## Setup
1) Clone the repository
```
git clone <your-fork-or-origin>
cd EmperorFred
```
2) Create a virtual environment and install dependencies
- Using uv (recommended):
```
uv venv
source .venv/bin/activate
uv pip install -r <(uv pip compile pyproject.toml)
```
- Or using pip:
```
python -m venv .venv
source .venv/bin/activate
pip install -r <(pip-compile pyproject.toml) # if you use pip-tools
# or simply
pip install -e .
```
Note: If you don't use pip-tools, you can install directly from the project metadata:
```
pip install .
```
3) Configure environment variables
Create a `.env` file in the project root (or export variables in your shell). See the full list in the next section.
## Configuration (Environment Variables)
Environment variables are read in `discord_bot/config.py` and `twitch_bot/config.py`, and shared DB settings in both.
Required/optional variables:
Discord
- `DISCORD_TOKEN` — Discord bot token (required to run Discord bot)
- `DISCORD_COMMAND_PREFIX` — e.g. `!` (optional; defaults handled by code to `!` if unset)
- `DISCORD_GUILD_ID` — guild/server ID used by the app in some contexts (optional)
Twitch
- `TWITCH_CLIENT_ID` — Twitch application client ID (required for Twitch operations)
- `TWITCH_CLIENT_SECRET` — Twitch application client secret (required)
- `TWITCH_TOKEN` — OAuth token for Twitch bot account; if missing the Twitch bot will not start
- `TWITCH_CHANNEL` — channel name (used for logs/hints)
- `TWITCH_BOT_ID` — numeric user ID for the bot account (required to subscribe to chat messages)
- `TWITCH_OWNER_ID` — numeric broadcaster (channel) user ID (required to subscribe)
- `TWITCH_COMMAND_PREFIX` — e.g. `!` (optional)
- `TWITCH_REDIRECT_URL` — redirect URI used during OAuth flows (optional)
Database
- `DB_CONN_STR` — SQLAlchemy connection string (required). Example for SQLite file DB:
- `sqlite:///data/bot.db`
Notes
- The project uses `python-dotenv`, so variables defined in `.env` are loaded automatically by `bot.py`.
- TwitchIO v3 relies on EventSub for chat subscriptions. Ensure `TWITCH_OWNER_ID` and `TWITCH_BOT_ID` are set.
- A tokens file may be referenced by the Twitch bot startup path (see `bot.py`, currently opens `.tio.tokens.json`).
TODOs
- Document the full OAuth/token provisioning flow for Twitch, including generating and storing tokens in `.tio.tokens.json` (or the expected file name) and required scopes.
## Running
Run both bots together (recommended during development):
```
python bot.py
```
Behavior:
- If `DISCORD_TOKEN` is set, the Discord bot starts.
- If `TWITCH_TOKEN` is NOT set, the Twitch bot will log a warning and skip starting.
- On successful Twitch start, the bot subscribes to EventSub ChatMessage for the configured broadcaster/user IDs.
Select which bot to run (CLI):
- Both (default):
```
python bot.py
```
- Discord only:
```
python bot.py --bot discord
```
- Twitch only:
```
python bot.py --bot twitch
```
- Short flag works too (values: `discord`, `twitch`, `both`):
```
python bot.py -b both
```
## Commands
Discord (`discord_bot/cogs`):
- `!ping` — replies with a health check message.
- `!restart` — owner-only; gracefully restarts the Discord bot instance.
Twitch (`twitch_bot/commands`):
- `!ping` — replies with a health check message including the chatter name.
- `!restart` — moderator-only; gracefully restarts the Twitch bot instance.
## Project Structure
```
.
├─ bot.py # Entry point; runs both bots concurrently
├─ pyproject.toml # Project metadata and dependencies
├─ uv.lock # Lockfile for uv (package manager)
├─ data/
│ ├─ bot.db # Example SQLite database (if used)
│ └─ models/
│ ├─ DiscordCog.py # Tracks Discord cog activation flags
│ ├─ TwitchComponent.py # Tracks Twitch command components and active flags
│ └─ TwitchLiveNotification.py
├─ libs/
│ ├─ Db.py # SQLAlchemy setup, model base, auto-create tables
│ ├─ Cog.py # Base for Discord cogs
│ ├─ RestartController.py # Simple restart signaling between loops
│ ├─ Channels.py, Guilds.py, Twitch.py, __init__.py
├─ discord_bot/
│ ├─ bot.py # Discord bot class (loads cogs dynamically)
│ ├─ config.py, config.json # Config loader + example JSON (not auto-loaded)
│ ├─ cogs/
│ │ ├─ ping.py # !ping command
│ │ └─ restart.py # !restart (owner-only)
│ └─ embeds/
│ └─ TwitchGameNotificationEmbed.py
└─ twitch_bot/
├─ bot.py # Twitch bot class (EventSub subscription; dynamic components)
├─ config.py # Twitch env config
└─ commands/
├─ ping.py # !ping command
└─ restart.py # !restart (moderator-only)
├─ tests/ # Pytest-based unit tests (offline)
│ ├─ conftest.py # Fixtures and env setup
│ ├─ test_db_and_models.py
│ ├─ test_discord_bot_load_cogs.py
│ ├─ test_twitch_bot_load_commands.py
│ └─ test_restart_controller.py
```
## Database
The project uses SQLAlchemy. `libs/Db.py`:
- Creates an engine from `DB_CONN_STR`
- Defines a `Db.Model` declarative base for models under `data/models`
- Imports all models from `data/models` and creates tables on startup
Models
- `data/models/TwitchComponent.py` maintains component activation flags for Twitch command modules. When `twitch_bot.bot.TwitchBot.load_commands()` scans `twitch_bot/commands`, it checks the DB record to decide whether to load a component.
- `data/models/DiscordCog.py` maintains activation flags for Discord cogs. When `discord_bot.bot.EmperorFredDiscordBot.load_cogs()` scans `discord_bot/cogs`, it checks the DB record to decide whether to load a cog.
- `data/models/TwitchLiveNotification.py` stores usernames for Discord-side Twitch live notifications (used by the `TwitchNotificationsCog`).
## Scripts
There are no custom CLI scripts or `tool` entries defined in `pyproject.toml`. Use `python bot.py` to run the application. Managing dependencies is done via uv/pip as described above.
## Testing
The project uses pytest.
How to run tests:
```
pip install pytest
pytest -q
```
Notes
- Tests are offline and avoid network calls. They focus on:
- `libs/RestartController` behavior
- Database/model initialization and defaults
- Discord cogs loading (registering `ping` and `restart`)
- Twitch components loading and honoring DB activation flags
- A temporary SQLite database is used per test via `DB_CONN_STR` provided by a pytest fixture.
TODOs
- Add integration tests (e.g., with mocked Discord/Twitch clients or local simulators).
## Development Notes
- Code style follows the surrounding modules; there is no configured formatter/linter in `pyproject.toml`.
- Consider adding Ruff/Black/mypy configuration and pre-commit hooks. (TODO)
## License
No license file is included in this repository.
TODO
- Choose and add a LICENSE (e.g., MIT, Apache-2.0) and update this section.