Commit graph

158 commits

Author SHA1 Message Date
safierinx-a
07179b648e Fix artist images: filter Last.fm placeholder, reorder providers, fix alias bug
Three bugs causing all artist images to be the same Last.fm placeholder:

1. Last.fm stopped serving real artist images years ago and returns a
   generic placeholder (hash 2a96cbd8b46e442fc41c2b86b821562f) for
   every artist. Added filter in selectBestImage to reject URLs
   containing this known placeholder hash.

2. Provider order had Last.fm before Deezer for artist images. Since
   Last.fm "succeeded" with the placeholder, Deezer was never reached.
   Swapped order: Deezer now checked before Last.fm.

3. FetchMissingArtistImages had inverted if/else — aliases were used
   on error, bare name on success. Fixed condition to err == nil.
2026-03-27 03:11:05 +05:30
safierinx-a
26aa3eca1f Fix track_lookup key: use unit separator instead of null byte
Postgres TEXT columns reject null bytes (\x00), causing silent insert
failures. Use U+001F (unit separator) instead.
2026-03-25 11:28:16 +05:30
safierinx-a
8ce6ec494d Add bulk import optimization: track_lookup cache, batch inserts, BulkSubmitter
Adopts ListenBrainz-inspired patterns to speed up imports from ~24h to
under 30 minutes for 49k scrobbles.

Phase 1 - track_lookup cache table:
- New migration (000006) adds persistent entity lookup cache
- Maps normalized (artist, track, album) → (artist_id, album_id, track_id)
- SubmitListen fast path: cache hit skips 18 DB queries → 2 queries
- Cache populated after entity resolution, invalidated on merge/delete
- Benefits both live scrobbles and imports

Phase 2 - SaveListensBatch:
- New batch listen insert using pgx CopyFrom → temp table → INSERT ON CONFLICT
- Thousands of inserts per second vs one-at-a-time

Phase 3 - BulkSubmitter:
- Reusable import accelerator for all importers
- Pre-deduplicates scrobbles by (artist, track, album) in memory
- Worker pool (4 goroutines) for parallel entity creation on cache miss
- Batch listen insertion via SaveListensBatch

Phase 4 - Migrate importers:
- Maloja, Spotify, LastFM, ListenBrainz importers use BulkSubmitter
- Koito importer left as-is (already fast with pre-resolved IDs)

Phase 5 - Skip image lookups during import:
- GetArtistImage/GetAlbumImage calls fully skipped when SkipCacheImage=true
- Background tasks (FetchMissingArtistImages/FetchMissingAlbumImages) backfill

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 04:17:50 +05:30
safierinx-a
c92e93484e Remove leftover console.log from rewind-picker fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 02:38:41 +05:30
safierinx-a
afd70d8857 Merge remote-tracking branch 'origin/ui/tweaks' 2026-03-25 02:38:16 +05:30
safierinx-a
51395b92d3 Merge remote-tracking branch 'origin/fix/rewind-picker' 2026-03-25 02:38:11 +05:30
safierinx-a
d986b6e30d Merge remote-tracking branch 'origin/fix/login-gate' 2026-03-25 02:38:06 +05:30
safierinx-a
67e0aac81d Merge remote-tracking branch 'origin/fix/listens-chart' 2026-03-25 02:38:01 +05:30
Apoorv Saxena
a5523d070e
Merge pull request #2 from safierinx-a/feat/mbz-search-enrichment
Add MusicBrainz search-by-name enrichment for scrobbles without IDs
2026-03-25 02:34:29 +05:30
Apoorv Saxena
3249d2164d
Merge pull request #1 from safierinx-a/fix/maloja-importer
Fix Maloja importer resilience: nil MBZ client, null album, error han…
2026-03-25 02:33:52 +05:30
safierinx-a
0855fb4bd7 Add MusicBrainz search-by-name enrichment for scrobbles without IDs
When a listen arrives with no MBZ IDs and no album title (the common
multi-scrobbler/Last.fm case), search MusicBrainz by artist+track name
to resolve recording, release, and release group IDs. This unlocks
CoverArtArchive album art, proper album association, and duration data.

New file: internal/mbz/search.go
- SearchRecording() method with Lucene query escaping
- Confidence filter: case-insensitive exact match on title + artist credit
- Release selection: prefer Official status, then first available
- Uses existing rate-limited queue (1 req/sec)

Integration in catalog.go:
- Only triggers when RecordingMbzID, ReleaseMbzID, AND ReleaseTitle are
  all missing — no impact on scrobbles that already have MBZ data
- Soft failure — search errors don't block the listen
- KOITO_DISABLE_MUSICBRAINZ handled automatically (MbzErrorCaller returns error)

Interface + mocks updated:
- SearchRecording added to MusicBrainzCaller interface
- MbzMockCaller: SearchResults map for test data
- MbzErrorCaller: returns error (existing pattern)

New tests:
- TestSubmitListen_SearchByName — mock search, verify album+duration resolved
- TestSubmitListen_SearchByNameNoMatch — verify graceful fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 00:01:24 +05:30
safierinx-a
c2d393aa03 Fix Maloja importer resilience: nil MBZ client, null album, error handling
Root cause of the panic at ~1,693 items: importers created
`&mbz.MusicBrainzClient{}` (nil requestQueue) instead of using the
engine's properly initialized client. When any code path called an MBZ
method, it panicked on the nil channel.

Changes:
- Pass engine's MBZ client to Maloja and Spotify importers
- Change MalojaTrack.Album to pointer type to handle null album JSON
- Continue on error instead of aborting the entire import
- Accept both Maloja export formats ("scrobbles" and "list" keys)
- Extract per-file import into importFile() with its own defer/recover
- Add progress logging every 500 items

Test fixtures:
- maloja_import_null_album_test.json (null album, valid album, empty artists)
- maloja_api_format_test.json (API "list" format)

New tests: TestImportMaloja_NullAlbum, TestImportMaloja_ApiFormat

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 23:58:45 +05:30
Gabe Farrell
0ec7b458cc
ui: tweaks and fixes (#194)
* reduce min width of top chart on mobile

* adjust error page style

* adjust h1 line height
2026-02-04 13:41:12 -05:00
15d38cffaa adjust h1 line height 2026-02-04 13:31:36 -05:00
0956e5868c adjust error page style 2026-02-04 13:27:03 -05:00
7ae3089f30 reduce min width of top chart on mobile 2026-02-04 13:13:20 -05:00
Gabe Farrell
531c72899c
fix: add null check for top charts bg gradient (#193) 2026-02-03 11:23:30 -05:00
37809bfc49 fix: add null check for top charts bg gradient 2026-02-03 11:17:42 -05:00
Gabe Farrell
b06685c1af
fix: rewind navigation (#191) 2026-02-02 15:06:13 -05:00
66cdf9f5ab fix: rewind navigation 2026-02-02 14:58:27 -05:00
Gabe Farrell
64236c99c9
fix: invalid json response when login gate is disabled (#184) 2026-01-26 14:49:30 -05:00
2356e75a3b fix: invalid json response when login gate is disabled 2026-01-26 14:44:07 -05:00
Gabe Farrell
42b32c7920
feat: add api key auth to web api (#183) 2026-01-26 13:48:43 -05:00
PythonGermany
bf1c03e9fd
docs: fix typo in index.mdx (#182) 2026-01-26 13:43:01 -05:00
Gabe Farrell
35e104c97e
fix: gradient background on top charts (#181) 2026-01-26 13:03:27 -05:00
Gabe Farrell
c8a11ef018
fix: ensure mbids in mbidmapping are discovered (#180) 2026-01-25 15:51:07 -05:00
Gabe Farrell
937f9062b5
fix: include time zone name overrides and add KOITO_FORCE_TZ cfg option (#176)
* timezone overrides and force_tz option

* docs for force_tz

* add link to time zone names in docs
2026-01-24 13:19:04 -05:00
Gabe Farrell
1ed055d098
fix: ui tweaks and fixes (#170)
* add subtle gradient to home page

* tweak autumn theme primary color

* reduce home page top margin on mobile

* use focus-active instead of focus for outline

* fix gradient on rewind page

* align checkbox on login form

* i forgot what the pseudo class was called
2026-01-22 21:31:14 -05:00
Gabe Farrell
08fc9eed86
fix: correct interest bucket queries (#169) 2026-01-22 17:01:46 -05:00
Gabe Farrell
cb4d177875
fix: release associations and add cleanup migration (#168)
* fix: release associations and add cleanup migration

* fix: incorrect test
2026-01-22 15:33:38 -05:00
Gabe Farrell
16cee8cfca
fix: speedup top-artists and top-albums queries (#167) 2026-01-21 17:30:59 -05:00
onespaceman
c59c6c3baa
QOL changes to client (#165) 2026-01-21 16:03:27 -05:00
Gabe Farrell
e7ba34710c
feat: lastfm image support (#166)
* feat: lastfm image support

* docs
2026-01-21 16:03:05 -05:00
Gabe Farrell
56ac73d12b
fix: improve subsonic image searching (#164) 2026-01-21 14:54:52 -05:00
Gabe Farrell
1a8099e902
feat: refetch missing images on startup (#160)
* artist image refetching

* album image refetching

* remove unused var
2026-01-20 12:10:54 -05:00
Gabe Farrell
5e294b839c
feat: all time rank display (#149)
* add all time rank to item pages

* fix artist albums component

* add no rows check

* fix rewind page
2026-01-16 01:03:23 -05:00
d08e05220f docs: add disclaimer about subsonic config 2026-01-15 22:01:25 -05:00
c0de721a7c chore: ignore README for docker workflow 2026-01-15 21:27:59 -05:00
Gabe Farrell
d2d6924e05
fix: use sql rank (#148) 2026-01-15 21:08:30 -05:00
Gabe Farrell
aa7fddd518
fix: a couple ui fixes (#147)
* fix: reduce loading component width

* improve theme selector for mobile

* match interest graph width to activity grid
2026-01-15 20:21:05 -05:00
Gabe Farrell
1eb1cd0fd5
chore: call relay early to prevent missed relays (#145)
* chore: call relay early to prevent missed relays

* fix: get current time in tz for listen activity (#146)

* fix: get current time in tz for listen activity

* fix: adjust test to prevent timezone errors
2026-01-15 19:40:38 -05:00
Gabe Farrell
92648167f0
fix: get current time in tz for listen activity (#146)
* fix: get current time in tz for listen activity

* fix: adjust test to prevent timezone errors
2026-01-15 19:36:48 -05:00
Gabe Farrell
9dbdfe5e41
update README 2026-01-15 18:21:51 -05:00
Gabe Farrell
94108953ec
fix: conditional rendering on artist and album pages (#140) 2026-01-14 22:12:57 -05:00
Gabe Farrell
d87ed2eb97
fix: ensure listen activity correctly sums listen activity in step (#139)
* remove impossible nil check

* fix listen activity not correctly aggregating step

* remove stray log

* fix test
2026-01-14 21:35:01 -05:00
Gabe Farrell
3305ad269e
Add Star History section to README
Added Star History section with visualization.
2026-01-14 17:21:52 -05:00
Gabe Farrell
20bbf62254
update README
Added logo and Ko-Fi badge to README.
2026-01-14 14:47:21 -05:00
Gabe Farrell
a94584da23
create FUNDING.yml 2026-01-14 14:06:14 -05:00
Gabe Farrell
8223a29be6
fix: correctly cycle tracks in backfill (#138) 2026-01-14 12:46:17 -05:00
231e751be3 docs: add navidrome quickstart guide 2026-01-14 01:26:01 -05:00