Commit Graph

363 Commits

Author SHA1 Message Date
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
Luis Pereira 2effe3bdef fix: listening history using integers 2025-12-27 17:02:31 -05:00
Luis Pereira 554f23ac40 fix: move playlist functions to data-model 2025-12-27 17:02:31 -05:00
Brian O'Reilly 4a79558c75 Merge branch 'glenneth1-glenneth/user-profile-enhancements'
Summary

This PR fixes several issues with the favorites feature:
Fixes

    Favorites star UI - Star now stays solid after favoriting a track (both main player and frame player)
        Fixed race condition where cache was checked before reload completed
        Cache now calls check-favorite-status after loading

    Track-id lookup - find-track-by-title now parses 'Artist - Title' format from Icecast metadata and searches both artist and title columns

    NIL user-id guards - All favorites functions now return early if user-id is NIL, preventing PostgreSQL errors when API is called without authentication

    Favorites API alist keys - Fixed Postmodern key names (TRACK-TITLE not TRACK_TITLE)

Files Changed

    user-profile.lisp - NIL guards and aget-profile helper
    frontend-partials.lisp - find-track-by-title improvement
    parenscript/front-page.lisp - Cache loading fix
    parenscript/stream-player.lisp - Cache loading fix for frame player
2025-12-27 14:00:02 -05:00
glenneth 9a767a7550 Merge remote-tracking branch 'upstream/main' into glenneth/user-profile-enhancements 2025-12-27 21:37:35 +03:00
Luis Pereira 820228bac1 feat: set bigger rate limit for now-playing api route 2025-12-27 13:28:10 -05:00
Luis Pereira b32e0bdbb0 fix: include http error code on json api format 2025-12-27 13:28:10 -05:00
Luis Pereira 6499c0a9ab feat: move routes to use rate-limit macros 2025-12-27 13:28:10 -05:00
Luis Pereira 8ae905a2c1 feat: add limit extension macros for define-page and define-api 2025-12-27 13:28:10 -05:00
Luis Pereira 1a39e0c6d2 fix: move copy files to admin role 2025-12-27 13:28:10 -05:00
glenneth 753ff822ce fix: Add NIL user-id guards to favorites functions
Prevents PostgreSQL errors when favorites API is called without
authentication. Functions now return early (nil or 0) instead of
generating invalid SQL with NIL in WHERE clause.
2025-12-27 20:33:40 +03:00
glenneth 25a6341a7b Merge upstream/main into glenneth/user-profile-enhancements
Resolved conflicts keeping our fixes:
- find-track-by-title: parses 'Artist - Title' format
- favorites cache: calls check-favorite-status after load
- toggle-favorite: uses load-favorites-cache instead of update-now-playing
- aget-profile: uses correct Postmodern key names (TRACK-TITLE, -ID)
2025-12-27 20:19:06 +03:00