2026-04-03 22:49:02 -04:00
2026-04-03 22:49:02 -04:00
2026-03-28 12:10:21 -04:00
2026-04-03 22:36:21 -04:00

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.

SongRequest — Limnoria IRC Song Request Plugin

A Limnoria (Supybot) plugin that watches IRC channels for song requests, validates them against the iTunes Search API, and streams them in real time to an HTMX web dashboard via WebSocket.

Features

  • Passive detection — recognizes Artist - Title patterns in chat and validates against Apple Music
  • Explicit command!request Artist - Title for direct requests
  • Disambiguation — presents top matches when multiple results found; user picks by number
  • Feeling Lucky mode — auto-select the first match, store the rest as alternates (per-channel)
  • Explicit/clean filtering — prefer explicit tracks, filter out clean duplicates, or vice versa (configurable per-channel)
  • Last.fm spell correction — optionally correct misspelled artist/track names before searching iTunes
  • Smart search — dual-strategy iTunes queries with attribute-targeted searches and increased result limits
  • Web dashboard — HTMX-powered UI with album art, Apple Music links, and moderation controls
  • Real-time updates — WebSocket pushes new requests and status changes to all connected dashboards
  • Moderation — approve, reject, or mark requests as played from the web UI
  • Bulk actions — select multiple requests and approve, reject, or mark played in one action
  • Alternate matches — when disambiguating, unchosen tracks appear as collapsible sub-cards with approve and mark-played buttons
  • Clickable cards — the entire request card links to Apple Music
  • Session management — start/stop named sessions, archive them, rename/clear/delete archived sessions
  • Channel grouping — requests grouped by channel with tab filtering; URL-based channel routing
  • Auth system — per-admin login via IRC-managed accounts (addSongAdmin), admin presence indicator
  • Theme support — dark/light/system theme toggle
  • Rate limiting — configurable per-user request limits
  • Ignore list — block specific users from making requests
  • Auto-approve — skip the pending queue and auto-approve requests (per-channel)
  • Persistence — SQLite-backed; survives bot restarts
  • IRC announcements — configurable delivery: channel, private message, or NOTICE
  • Quiet mode — suppress the "Queued" IRC confirmation per-channel
  • Export history — download request history as a Markdown file
  • Open/close requests — global toggle (with per-channel override) from IRC or the web panel
  • Clear history — wipe played/rejected entries from IRC or the web panel
  • Mobile responsive — optimized layout for phones and tablets

Dependencies

  • aiohttp — standalone async web server for the dashboard
pip install aiohttp

Installation

  1. Copy the SongRequest/ directory into your Limnoria plugins directory (or add its parent to config directories.plugins).

  2. Load the plugin:

    @load SongRequest
    
  3. Configure enabled channels:

    @config plugins.SongRequest.enabledChannels #music #requests
    
  4. Add a web dashboard admin (from IRC, requires bot admin):

    @addsongadmin alice s3cretK3y
    
  5. (Optional) Set a Last.fm API key for spell correction:

    @config plugins.SongRequest.lastfmApiKey YOUR_LASTFM_KEY
    
  6. Access the dashboard at http://<bot-host>:8888/ (default port, configurable via webPort).

Configuration

Global Settings

Setting Type Default Description
enabledChannels Space-separated list (empty) Channels for passive detection
ignoredUsers Space-separated list (empty) Nicks/hostmasks to ignore
maxRequestsPerUser Integer 10 Max requests per rate limit window (0 = unlimited)
rateLimitWindow Integer 3600 Rate limit window in seconds
webAuthToken String (private) (empty) (Deprecated) Legacy shared auth token; prefer per-admin accounts
lastfmApiKey String (private) (empty) Last.fm API key for spell correction; empty to disable
announceStatus Boolean True Master switch for all IRC status announcements
maxChoices Integer 3 Disambiguation choices shown
webPort Integer 8888 Port for the web dashboard server
webHost String 0.0.0.0 Bind address for the web dashboard server
requestsOpen Boolean True Global toggle — accept or reject new requests

Per-Channel Settings

Setting Type Default Description
requestsOpenOverride String (empty) open, closed, or empty for global default
quietQueued Boolean False Suppress the "Queued: ..." IRC confirmation
queuedReplyMode String channel Queued confirmation delivery: channel, private, or notice
autoApprove Boolean False Auto-approve requests (skip pending queue)
feelingLucky Boolean False Auto-select first match; store rest as alternates
explicitMode String filter off, prefer, filter, or clean (see below)
announceApproved Boolean True Announce approved requests in IRC
announceRejected Boolean True Announce rejected requests in IRC
announceNowPlaying Boolean True Announce now-playing requests in IRC
announceReplyMode String channel Status announcement delivery: channel, private, or notice
passiveDetection Boolean True Enable passive pattern matching
requestCommand Boolean True Enable the !request command

Explicit Mode

Controls how explicit/clean track versions are handled in search results:

  • off — return results as-is from iTunes
  • prefer — sort explicit tracks first, keep all results
  • filter (default) — drop cleaned versions when an explicit version of the same track exists, sort explicit first
  • clean — drop explicit versions when a clean version exists, sort clean first

Commands

Command Description Permission
request <text> Request a song by artist/title Anyone
pick <number> Pick from disambiguation choices Anyone
ignore <nick> Add a nick to the ignore list Admin
unignore <nick> Remove a nick from the ignore list Admin
requeststats Show queue statistics Anyone
openrequests [channel] Open requests globally or per-channel Admin
closerequests [channel] Close requests globally or per-channel Admin
clearhistory Clear all played/rejected requests Admin
startsession [name] Start a new request session Admin
stopsession Stop and archive the active session Admin
addsongadmin <user> <key> Add a web dashboard admin account Admin
removesongadmin <user> Remove a web dashboard admin account Admin
listsongadmins List all web dashboard admin accounts Admin

Web Dashboard

The dashboard runs on a standalone aiohttp server at the configured webPort (default 8888).

Authentication

Admins are managed via IRC commands (addsongadmin/removesongadmin). The dashboard has a login page at /login. Non-admins can view the queue and history read-only; admin controls (moderation buttons, session management, export, etc.) are only visible to logged-in admins.

A floating presence indicator shows which admins are currently online.

Queue View

  • Pending requests awaiting moderation
  • Approved requests ready to play
  • Bulk select mode for mass approve/reject/mark-played
  • Action buttons (approve/reject/mark played) positioned in the top-right corner of each card

History View

  • History of played/rejected requests with Export .md and Clear History buttons
  • Session archives — previous sessions listed with expand-to-view, plus rename/clear/delete actions

Other Features

  • Channel filter tabs with URL-based routing (/#channelName or /channelName)
  • Dark/light/system theme toggle
  • Toast notifications for new requests when viewing history
  • Custom themed modals (no native browser prompts)
  • Real-time WebSocket connection with auto-reconnect

How Passive Detection Works

  1. The bot watches messages in enabledChannels for lines matching Something - Something
  2. Lines starting with bot command prefixes (!, ., @, etc.) or URLs are skipped
  3. If a Last.fm API key is configured, artist/track names are spell-corrected
  4. The extracted text is searched against the iTunes Search API (dual-strategy: combined + attribute-targeted)
  5. Results are filtered/sorted based on explicitMode
  6. If no song matches, the message is silently ignored
  7. If one match (or feelingLucky is on), it's queued automatically
  8. If multiple matches, the user is presented with choices

Running Tests

pip install limnoria aiohttp pytest
python -m pytest SongRequest/test.py -v
Description
Limnoria plugin with simple web interface to monitor IRC channels for song requests.
Readme MIT 206 KiB
Languages
Python 59.4%
HTML 40.6%