Reflects all changes since the initial README: Bearer auth on internal endpoints, public index page and /public/* API, dashboard enhancements (announced checkbox, ping button, tabbed UI, copy-to-clipboard), .env file support, and new config variables. Made-with: Cursor
175 lines
7.3 KiB
Markdown
175 lines
7.3 KiB
Markdown
> [!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]"
|
|
cp .env.example .env # edit with your settings
|
|
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 |
|
|
|----------|--------|------|-------------|
|
|
| `/` | GET | -- | Public index page |
|
|
| `/health` | GET | -- | Service health check |
|
|
| `/public/playlist` | GET | -- | Current week's playlist (unannounced tracks censored) |
|
|
| `/public/shows` | GET | -- | List all shows (paginated) |
|
|
| `/public/shows/{show_id}` | GET | -- | Past show with full tracklist |
|
|
| `/playlist` | GET | Bearer | Current week's full playlist |
|
|
| `/playlist/{position}` | GET | Bearer | Single track by position (1-indexed) |
|
|
| `/shows` | GET | Bearer | List all shows (paginated) |
|
|
| `/shows/by-episode/{episode_number}` | GET | Bearer | Look up show by episode number |
|
|
| `/shows/{show_id}` | GET | Bearer | 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 |
|
|
| `/admin/announced` | POST | Bearer/Session | Toggle track announced state |
|
|
| `/admin/ping` | POST | Bearer/Session | Send IRC message via connected bots |
|
|
| `/ws/announce` | WS | Bearer | Bot WebSocket for announcements |
|
|
| `/ws/public` | WS | -- | Public WebSocket for live track reveals |
|
|
|
|
## Configuration
|
|
|
|
All settings are read from environment variables (prefix `NTR_`). A `.env`
|
|
file in the project root is loaded automatically. See
|
|
[`.env.example`](.env.example) for a template with all available variables.
|
|
|
|
| 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 |
|
|
| `NTR_SHOW_ROTATION_DELAY_HOURS` | `0` | Hours to wait after the show boundary before rotating to the next episode (recommended `2` for live recording window) |
|
|
| `NTR_PING_TARGET` | *(empty)* | Default nick/target for the dashboard ping feature |
|
|
| `NTR_PING_MESSAGE` | *(empty)* | Default message for the dashboard ping feature |
|
|
|
|
## Public Index Page
|
|
|
|
The root URL (`/`) serves a public-facing page showing the current show's
|
|
playlist. Unannounced tracks are hidden behind silhouette cards until the
|
|
admin announces them from the dashboard. Reveals happen in real time over
|
|
WebSocket (`/ws/public`), so listeners following along see tracks appear
|
|
as they are played.
|
|
|
|
Past episodes are browsable from the same page with their full tracklists
|
|
visible.
|
|
|
|
## Dashboard
|
|
|
|
An optional web dashboard for managing tracks during live shows. Features:
|
|
|
|
- **Tabbed show interface** -- switch between the current and previous week's
|
|
playlists in one view.
|
|
- **Announce button** -- push a track to IRC via connected bot plugins. Also
|
|
reveals the track on the public index page in real time.
|
|
- **Announced checkbox** -- persistent per-track flag, auto-checked on
|
|
announce. Can be toggled manually.
|
|
- **Copy to clipboard** -- one-click copy of a formatted track line.
|
|
- **Send IRC Message** -- ping a nick or channel with a custom message through
|
|
all connected bots. Default target and message are configurable via
|
|
`NTR_PING_TARGET` / `NTR_PING_MESSAGE`.
|
|
|
|
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 <episode> <position>` | Track from a specific episode's playlist |
|
|
| `!playlist [episode]` | Current week's playlist, or a specific episode |
|
|
| `!lastshow <position>` | 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/
|
|
```
|