Commit Graph

374 Commits

Author SHA1 Message Date
Brian O'Reilly 0a2ac0c409 docker port maps leak to external interface...
Unless they are explicitly bound to loopback, which I thought was the
default, but it is not. likely related to the interface between
bridges and ip tables in the Linux kernel, but anyhow, get literal
about the portmap interface address to prevent exposing the database
to the entire internet. With thanks to the friendly heads up email
from the German Federal Republic via Hetzner.
2026-03-13 17:21:22 -04:00
Luis Pereira 5f9dc80ac8 fix: add parenscript utils file 2026-03-02 17:51:26 -05:00
Luis Pereira 8700724f81 feat: add media session API on now-playing update 2026-03-02 17:51:26 -05:00
Luis Pereira 61266647a9 feat: frontpage now playing default fill 2026-03-02 17:51:26 -05:00
Luis Pereira 6fd8071a05 fix: add favourite count to icecast stats 2026-03-02 17:51:26 -05:00
glenneth 1e5a7e75f3 Replace format t logging with log4cl in playlist-scheduler
Converts all 22 format t print statements to 7 targeted log4cl calls:
- log:info for successful operations (playlist loaded, scheduler started)
- log:warn for recoverable failures (DB fallback, save/delete errors)
- log:error for actionable failures (liquidsoap unresponsive, missing playlist)

Removes redundant startup/shutdown chatter and per-retry debug noise.
2026-02-14 08:01:13 -05:00
glenneth 0da8101f63 fix: Scheduler retry logic + comprehensive documentation update
playlist-scheduler.lisp:
- Add liquidsoap-reload-and-skip with retry mechanism (3 attempts, 2s delay)
- Add liquidsoap-command-succeeded-p to validate telnet responses
- Sends reload before skip for reliability
- Root cause: nc -q1 silently failing, handler-case never triggered

Documentation updates:
- Fix API endpoint count: 15+ → 90+ across all docs
- Fix PROJECT-HISTORY.org Phase 10 heading level (was nested incorrectly)
- Add Phase 11: Scheduler Reliability Fix (February 2026)
- Update PROJECT-HISTORY.org dates and stats to February 2026
- Add Playlist Scheduler section to STREAM-CONTROL.org
- Update Future Enhancements checklist (mark implemented features)
- Fix TEMPLATING_SYSTEM.org missed date update
- New playlists: solar-flare.m3u, ceres-rising.m3u
2026-02-10 07:16:27 -05:00
glenneth 3d595df916 docs: Add complete API endpoint documentation and tidy PROJECT-OVERVIEW
API-ENDPOINTS.org:
- Add documentation for all 90+ API endpoints
- Stream Queue, Scheduler, Track Requests, User Playlists
- Favorites, History, Profile, Account endpoints
- Frontend Partials, Utility endpoints
- Now covers 100% of define-api endpoints in codebase

PROJECT-OVERVIEW.org:
- Tidy up tables and formatting
2026-02-10 07:16:27 -05:00
glenneth 476ec64309 docs: Comprehensive documentation update January 2026
- Update all #+DATE: and Last Updated lines to 2026-01-26
- Bump documentation version to 3.1
- Standardize author metadata (Glenn → Glenn Thompson where applicable)
- Add Phase 9: Production Launch & Feature Expansion (Nov-Dec 2025)
- Add Phase 10: Documentation Overhaul (January 2026)
- Update PROJECT-HISTORY.org with accurate contributor stats:
  - 614 total commits, 88 PRs merged
  - Glenn Thompson: 354 commits, 59 PRs
  - Brian O'Reilly: 148 commits, 3 PRs
  - Luis Pereira: 109 commits, 26 PRs
- Standardize API endpoints to /api/asteroid/ base path
- Update UI routes to reflect root / mounting
- Correct template extensions from .chtml to .ctml
- Fix Docker music library paths (music/library/)
- Update stream queue location to playlists/stream-queue.m3u
- Expand API-ENDPOINTS.org with playlist, stream control, admin APIs
2026-02-10 07:16:27 -05:00
Luis Pereira d894964c20 fix: increase now-playing rate limit to 10 per second 2026-01-23 21:17:44 -05:00
Luis Pereira 6b56a17b4a fix: restore AUTHSTATE object when there is no login 2026-01-23 21:17:44 -05:00
Luis Pereira 0def454077 feat: use navbar partial on all page templates 2026-01-21 17:32:41 -05:00
Luis Pereira 7c6eaa1fe0 feat: adds templating system docs 2026-01-21 17:32:41 -05:00
Luis Pereira 2992822010 feat: replace global auth state variable with template injected object 2026-01-21 17:32:41 -05:00
Luis Pereira 6ab7489f9b feat: allows for navbar menu exclution with exclude list 2026-01-21 17:32:41 -05:00
Luis Pereira cffb3cf384 feat: reusable navbar with auth check in render 2026-01-21 17:32:41 -05:00
Luis Pereira 732ff0858e fix: hide analyzer when in frame player mode 2026-01-21 17:32:41 -05:00
glenneth 55eafa943f Fix rate limiter corruption: cleanup negative amounts on startup
The r-simple-rate library has a bug where rate limit counters can go
negative and never reset. This happens because the reset condition
only triggers when amount >= 0, so negative amounts are permanently
stuck.

This fix adds:
- cleanup-corrupted-rate-limits function to delete corrupted entries
- db:connected trigger to run cleanup automatically on startup

This prevents the 429 error loops that occurred when counters became
corrupted with large negative values.
2026-01-18 12:58:35 -05:00
glenneth a9c48e59c9 Increase rate limits to 180 req/min for polling endpoints 2026-01-18 10:55:33 -05:00
glenneth 4622ae2440 Fix notification icon path to use existing asteroid.png 2026-01-18 10:21:21 -05:00
glenneth 849c1c2716 Increase rate limits on polling endpoints
Fix 429 errors caused by aggressive rate limiting on now-playing APIs.
Changed from 2-3 req/sec to 60 req/min for:
- asteroid/partial/now-playing
- asteroid/partial/now-playing-inline
- asteroid/partial/now-playing-json
- asteroid/channel-name

This fixes notifications not working and may resolve auto-reconnect issues.
2026-01-18 10:09:52 -05:00
glenneth 6d4169b707 Add system notifications for track changes
- Implement Web Notifications API in ParenScript
- Add notification toggle button (🔔/🔕) to player frame
- Show 'Artist - Track' notification when track changes
- Store notification preference in localStorage
- Auto-close notifications after 5 seconds
- Click notification to focus browser window
2026-01-18 08:55:53 -05:00
glenneth 7ed11ae2f4 Add sort dropdown for admin geo stats (minutes vs listeners)
- Add dropdown to admin template to choose sort order
- Update get-geo-stats to accept order-by parameter
- Update API endpoint to pass sort-by parameter
- Update ParenScript to read dropdown and pass to API
- Default sort is by minutes (engagement time)
2026-01-18 08:48:34 -05:00
glenneth b68fce817d Fix geo stats ordering to sort by total_minutes instead of total_listeners
Countries with high engagement (listen time) should appear at the top,
not countries with just high unique listener counts.
2026-01-18 08:48:34 -05:00
Luis Pereira ff651e6a36 fix: merged status and status-content 2026-01-15 12:58:45 -05:00
Luis Pereira 2118f4ed5a fix: merged about and about-content 2026-01-15 12:58:45 -05:00
Luis Pereira b862097ca2 fix: merged player and player-content 2026-01-15 12:58:45 -05:00
Luis Pereira 01cb0366c0 fix: merged frontend and frontend-content 2026-01-15 12:58:45 -05:00
Glenn Thompson 151f6c5569 Replace Autechre tracks with flow-state alternatives, add Underworld
- Replace jarring Autechre tracks with smoother ambient alternatives:
  - Labradford, Biosphere, Tycho, Marconi Union, arovane, Four Tet, Brian Eno, Alva Noto, Proem
- Add Underworld - Everything, Everything to all updated playlists
- Improves listener experience for coding/hacking flow state

Affected playlists:
- afternoon-orbit.m3u
- Asteroid-Low-Orbit.m3u
- Asteroid-Low-Orbit-DOCKER.m3u
- escape-velocity.m3u
- geostationary_stream_queue.m3u
- midnight-ambient.m3u
- new-years-eve-2025.m3u
2026-01-12 20:31:46 -05:00
glenneth 249844160f Fix listener minutes tracking for accurate geo stats
- Add register-web-listener to now-playing-json API endpoint
  This keeps listeners registered during continuous playback instead of
  timing out after 5 minutes of inactivity

- Fix listen_minutes calculation to increment by listener_count per poll
  Previously incremented by 1 regardless of how many listeners, now properly
  tracks listener-minutes (1 minute per listener per 60s poll interval)

- Add migration 009 documenting the calculation fix
2026-01-11 13:25:55 -05:00
glenneth 8b6209e4e0 Add mini spectrum analyzer to player frame with theme/style sync
- Remove cross-frame audio access that was breaking audio on navigation
- Add mini spectrum visualizer to persistent player frame
- Mini analyzer syncs theme and style with main analyzer via localStorage
- Add MusicBrainz search link to player frame (updates with track changes)
- Reduce quality selector width from 140px to 55px
- Add search_url to now-playing-json API response

The main analyzer is disabled in frameset mode due to browser restrictions
on cross-frame MediaElementSource, but the mini analyzer in the player
frame provides visualization that persists across content navigation.
2026-01-11 13:25:55 -05:00
Luis Pereira bad9d4294b fix: add api catch all route with 404 2026-01-07 17:39:26 -05:00
glenneth 8e60563e9d Fix stream stall reconnection failure
- Reset *is-reconnecting* flag before play attempt so error handler can
  catch failures and trigger retry with exponential backoff
- Always reconnect on stall event - ready-state check was unreliable
- Add retry logic with backoff when reconnect fails (up to 5 attempts)
- Store stalled timeout reference for proper cancellation

Fixes issue where stream would show 'Stream stalled - reconnecting...'
but never actually reconnect, requiring manual intervention.
2026-01-05 08:35:50 -05:00
glenneth f476b83cbe fix: Preserve playlist selection in scheduler dropdown on refresh 2026-01-04 14:11:15 -05:00
Brian O'Reilly f0f2dd93a4 patch bad change to Makefile to restore build.
take 2.
2026-01-02 19:07:43 -05:00
Luis Pereira f4468212de fix: docker image build configured with posgres 2026-01-02 07:43:47 -05:00
Luis Pereira abb6d97a61 fix: update db seed to match current schema 2026-01-02 07:43:47 -05:00
glenneth be0b622901 fix: Use head/cat instead of sed for multi-line YP snippet insertion 2026-01-02 07:42:11 -05:00
glenneth a52602afda feat: Address PR feedback - rename XML files and add STATION_URL config
- Rename icecast.xml.base -> icecast-base.xml for editor highlighting
- Rename icecast-yp.xml.snippet -> icecast-yp-snippet.xml for editor highlighting
- Add STATION_URL env var to Liquidsoap for YP directory station link
- Production sets STATION_URL=https://asteroid.radio
- Update docker-compose.yml to pass both ICECAST_HOSTNAME and STATION_URL
- Update environment.sh.template with STATION_URL documentation
2026-01-02 07:42:11 -05:00
glenneth 821352edb7 feat: Add ICECAST_HOSTNAME config for YP directory registration
- Add hostname substitution in icecast-entrypoint.sh
- Update environment.sh.template with ICECAST_HOSTNAME option
- Defaults to localhost for dev, production sets ice.asteroid.radio
- Fixes YP directories showing localhost:8000 as stream URL
2026-01-02 07:42:11 -05:00
glenneth 1760fa5768 feat: Make YP directory publishing configurable via ICECAST_ENABLE_YP env var
- Add Dockerfile.icecast with custom entrypoint
- Add icecast-entrypoint.sh to conditionally insert YP config
- Add icecast.xml.base (without YP blocks)
- Add icecast-yp.xml.snippet (YP directory blocks)
- Update docker-compose.yml to build custom icecast image
- Update environment.sh.template with documentation

Dev environments default to YP disabled.
Production sets ICECAST_ENABLE_YP=true to publish to internet-radio.com
2026-01-02 07:42:11 -05:00
Brian O'Reilly 8cbdaef217 we are at a point where there's lots of interstitial files...
ignore them.
2025-12-30 15:26:09 -05:00
Brian O'Reilly 6721d57550 Unneeded things...
no need for the postgres/docker env, and we don't track
playlists/stream-queue.m3u because it is dynamically generated.
2025-12-30 15:24:13 -05:00
Brian O'Reilly 3851857787 update our ignorance. 2025-12-30 15:20:44 -05:00
Brian O'Reilly a8bf864499 Lets institute some operations around here
A directory for ops scripts, plus a script to backup the posgres
database that holds up asteroid.radio.
2025-12-30 13:07:30 -05:00
Glenn Thompson de70fbde5a refactor: Address PR review feedback for timestamp handling
- Rename format-timestamp-for-postgres to format-timestamp-iso8601 (database-agnostic)
- Reuse format-timestamp-iso8601 in authenticate-user instead of inline formatting
- Change listened_at field type from integer to timestamp for consistency
2025-12-29 09:39:51 -05:00
Glenn Thompson debf47c9c7 fix: Use correct table name user_listening_history in user-profile.lisp
- Update all references from listening_history to user_listening_history
- Use correct column names: user_id, listened_at, duration_seconds, track_artist
- Update database.lisp collection definition to match PostgreSQL schema
2025-12-29 09:39:51 -05:00
Glenn Thompson 4b49f63991 fix: Normalize USERS table timestamps before dm:save to prevent PostgreSQL type errors
- Add format-timestamp-for-postgres and normalize-user-timestamps functions in database.lisp
- data-model-save now normalizes timestamp fields for USERS table before saving
- Fix authenticate-user to use data-model-save instead of dm:save directly
- Add global auth state in auth-ui.lisp for other scripts to check login status
- Add auth checks in front-page.lisp and stream-player.lisp to skip API calls when not logged in
- Fix ParenScript parentheses structure in stream-player.lisp DOMContentLoaded handler

Fixes password reset, role update, and last-login update failures caused by
integer timestamps being sent to PostgreSQL TIMESTAMP columns.
2025-12-29 09:39:51 -05:00
glenneth eb03947f7f refactor: Listening history to data-model + frame player favorites sync
- Refactor listening history functions to use data-model interface:
  - record-listen, get-listening-history, get-listening-stats
  - get-top-artists, clear-listening-history, get-listening-activity
  - Updated API endpoints to use dm:field
- Refactor get-user-avatar to use data-model
- Add postMessage sync between front page and frame player for favorites
- Add credentials:include to frame player fetch calls for session cookies
2025-12-28 09:58:33 -05:00
glenneth ccce10db50 feat: Sync favorites between front page and frame player via postMessage 2025-12-28 09:58:33 -05:00