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:
-`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
├─ 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.