> [!IMPORTANT] > This project was developed entirely with AI coding assistance (Claude Opus 4.6 via Cursor IDE) and has not undergone rigorous review. It is provided as-is and may require adjustments for other environments. # NtR SoundCloud Fetcher Fetches SoundCloud likes from NicktheRat's profile, builds weekly playlists aligned to the Wednesday 22:00 ET show schedule, and serves them via a JSON API. ## Quick Start ```bash pip install -e ".[dev]" export NTR_ADMIN_TOKEN="your-secret-here" ntr-fetcher ``` The API starts at `http://127.0.0.1:8000`. ## Historical Backfill Seed the database with past shows by providing an anchor episode and its air date: ```bash NTR_ADMIN_TOKEN=token ntr-fetcher --init --show 521 --aired 2026-01-07 ``` This computes every weekly show from the anchor forward to today, batch-fetches the corresponding likes from SoundCloud, and populates the database. Episode numbers are assigned automatically (521, 522, ...). After backfill completes, the normal server mode will auto-increment from the latest episode. ## API Full documentation: [`docs/api.md`](docs/api.md) | Endpoint | Method | Auth | Description | |----------|--------|------|-------------| | `/health` | GET | -- | Service health check | | `/playlist` | GET | -- | Current week's playlist | | `/playlist/{position}` | GET | -- | Single track by position (1-indexed) | | `/shows` | GET | -- | List all shows (paginated) | | `/shows/by-episode/{episode_number}` | GET | -- | Look up show by episode number | | `/shows/{show_id}` | GET | -- | Specific show by internal ID | | `/login` | GET/POST | -- | Login page | | `/logout` | GET | Session | Clear session | | `/dashboard` | GET | Session | Live playlist dashboard | | `/admin/refresh` | POST | Bearer | Trigger immediate SoundCloud fetch | | `/admin/tracks` | POST | Bearer | Add track to current show | | `/admin/tracks/{track_id}` | DELETE | Bearer | Remove track from current show | | `/admin/tracks/{track_id}/position` | PUT | Bearer | Move track to new position | | `/admin/announce` | POST | Bearer/Session | Announce track to IRC | ## Configuration Environment variables (prefix `NTR_`): | Variable | Default | Description | |----------|---------|-------------| | `NTR_PORT` | `8000` | API port | | `NTR_HOST` | `127.0.0.1` | Bind address | | `NTR_DB_PATH` | `./ntr_fetcher.db` | SQLite database path | | `NTR_POLL_INTERVAL_SECONDS` | `3600` | How often to check SoundCloud (seconds) | | `NTR_ADMIN_TOKEN` | *(required)* | Bearer token for admin endpoints | | `NTR_SOUNDCLOUD_USER` | `nicktherat` | SoundCloud username to track | | `NTR_SHOW_DAY` | `2` | Day of week for show (0=Mon, 2=Wed) | | `NTR_SHOW_HOUR` | `22` | Hour (Eastern Time) when the show starts | ## Dashboard An optional web dashboard for announcing tracks to IRC during live shows. Nick opens the dashboard, sees the current and previous week's playlist, and clicks "Announce" next to a track to push it to the configured IRC channel via connected bot plugins. Enable by setting these environment variables: | Variable | Default | Description | |----------|---------|-------------| | `NTR_WEB_USER` | *(required)* | Dashboard login username | | `NTR_WEB_PASSWORD` | *(required)* | Dashboard login password | | `NTR_SECRET_KEY` | *(required)* | Secret key for cookie signing | ## IRC Commands Both Sopel and Limnoria plugins expose the same commands: | Command | Description | |---------|-------------| | `!1`, `!2`, ... `!N` | Track by position in the current week's playlist | | `!song ` | Track from a specific episode's playlist | | `!playlist [episode]` | Current week's playlist, or a specific episode | | `!lastshow ` | Track from the previous week's show | | `!status` | API health, poller status, and track count | | `!refresh` | Trigger a manual SoundCloud fetch (admin only) | ## IRC Plugin Setup Both plugins require the `websocket-client` package for live announcements: ```bash pip install websocket-client ``` ### Sopel Copy `plugins/sopel/ntr_playlist.py` into your Sopel plugins directory (typically `~/.sopel/plugins/`). Add a `[ntr_playlist]` section to your Sopel config: | Setting | Default | Description | |---------|---------|-------------| | `api_base_url` | `http://127.0.0.1:8000` | NtR API base URL | | `admin_token` | *(empty)* | Bearer token for admin commands | | `admin_nicks` | *(empty)* | Comma-separated list of admin nicknames | | `display_timezone` | `America/New_York` | Timezone for displayed timestamps | | `ws_url` | `ws://127.0.0.1:8000/ws/announce` | WebSocket endpoint for announcements | | `announce_channel` | `#sewerchat` | Channel to send announcements to | | `client_id` | `sopel` | Identifier for this bot in status messages | ### Limnoria Copy the `plugins/limnoria/NtrPlaylist/` directory into your Limnoria bot's plugins folder. Configure via the Limnoria registry: | Registry Value | Default | Description | |----------------|---------|-------------| | `apiBaseUrl` | `http://127.0.0.1:8000` | NtR API base URL | | `adminToken` | *(empty)* | Bearer token for admin commands | | `adminNicks` | *(empty)* | Space-separated list of admin nicknames | | `displayTimezone` | `America/New_York` | Timezone for displayed timestamps | | `wsUrl` | `ws://127.0.0.1:8000/ws/announce` | WebSocket endpoint for announcements | | `announceChannel` | `#sewerchat` | Channel to send announcements to | | `clientId` | `limnoria` | Identifier for this bot in status messages | ## Development ```bash pip install -e ".[dev]" pytest ruff check src/ tests/ ```