Commit graph

2312 commits

Author SHA1 Message Date
BoulderBadgeDad
87ea38bdd9
Merge pull request #342 from elmerohueso/plex-pin-auth
Add Plex pin-based OAuth and re-work Plex configuration dialogs
2026-04-21 20:17:12 -07:00
elmerohueso
f8dd846fea
Merge branch 'main' into plex-pin-auth 2026-04-21 16:05:40 -06:00
BoulderBadgeDad
32923e366c
Merge pull request #346 from JohnBaumb/fix/ghcr-lowercase-owner
Fix GHCR tags: lowercase repository owner for Docker compatibility
2026-04-21 12:27:02 -07:00
JohnBaumb
dee0b6e3ce Fix GHCR tags: lowercase repository owner for Docker compatibility 2026-04-21 12:25:11 -07:00
BoulderBadgeDad
1ddfa727bd
Merge pull request #340 from JohnBaumb/pipeline-update
CI/CD pipeline improvements: dev nightlies, linting, caching, cleanup
2026-04-21 12:22:16 -07:00
JohnBaumb
c91e651bcd Fix duplicate nightly tag, add date+sha pinned tags, lint dev builds, preserve nightly in cleanup 2026-04-21 11:56:08 -07:00
JohnBaumb
26ba1bdc0f Add :nightly tag, dual-push to GHCR, remove pinned dev tags 2026-04-21 11:56:08 -07:00
JohnBaumb
5edd72b6cf Add dev nightly builds, ruff linting, Docker layer caching, and GHCR cleanup 2026-04-21 11:56:08 -07:00
Broque Thomas
6314827e91 Fix test-order-dependent failures in new metadata_service tests
The _DummyConfigManager stubs in test_metadata_service_musicmap.py and
test_metadata_service_artist_image.py were missing get_active_media_server(),
which the existing test_metadata_service_discography.py dummy provides.

Both files install their dummy via sys.modules["config.settings"] with an
"if not in sys.modules" guard, so whichever test file loads first wins.
When the new files load alphabetically before discography, the limited
dummy persists and later tests hit AttributeError on get_active_media_server.

Adds the same get_active_media_server method to both dummies so all three
test files are equivalent and test ordering no longer affects outcomes.
2026-04-21 11:39:56 -07:00
BoulderBadgeDad
9eaf53630c
Merge pull request #345 from kettui/fix/get_similar_artists_stream
Refactor artist image and similar-artist lookup to use source priority
2026-04-21 11:33:38 -07:00
BoulderBadgeDad
0ebb4f9d80
Merge pull request #344 from JohnBaumb/fix/ruff-lint-errors
Fix existing ruff lint errors (F541, B007)
2026-04-21 11:20:18 -07:00
JohnBaumb
a1886ed87f Fix ruff F541 and B007 lint errors 2026-04-21 11:18:40 -07:00
Antti Kettunen
6f79214439
Route artist image lookup through metadata service
- Move /api/artist/<artist_id>/image resolution into core.metadata_service.
- Resolve artist artwork through source priority, with explicit source/plugin overrides preserved.
- Keep Spotify call tracking inside the client layer to avoid double counting.
- Update similar-artist lazy loading to pass source context and add service coverage.
2026-04-21 21:14:35 +03:00
Antti Kettunen
b022a90997
Move MusicMap similar artist matching into metadata service
- Relocate the streamed MusicMap similar-artist flow out of web_server.py and into core.metadata_service.
- Match similar artists through the configured source-priority chain instead of assuming Spotify first.
- Add iTunes artwork fallback so streamed artist payloads still carry image_url when search results are sparse.
- Cover the new service behavior with tests.
2026-04-21 21:14:35 +03:00
BoulderBadgeDad
9863c947dc
Merge pull request #343 from kettui/fix/replace-print-with-logger
Tidy up logging across the app
2026-04-21 11:05:52 -07:00
Broque Thomas
cf143f70af Batch discography completion matching against pre-fetched candidates
Artist detail pages ran check_album_exists_with_editions and check_track_exists
per discography item, each firing 5+ title variations times 3 artist variations
of fuzzy LIKE searches plus fallback broad-artist queries. For a 30-album artist
that was ~450 SQL round-trips just to answer "which of these do I own."

Hoist the artist's library albums and tracks into memory once per request via
two new helpers — get_candidate_albums_for_artist and get_candidate_tracks_for_albums —
and thread them through as optional candidate_albums / candidate_tracks params on
check_album_exists_with_editions, check_album_exists_with_completeness,
check_track_exists, check_album_completion, and check_single_completion.

Batched path scores the same _calculate_album_confidence / _calculate_track_confidence
against the in-memory list, preserving Smart Edition Matching and accuracy.
Title-only cross-artist fallback still fires for collaborative-album edge cases.
None on either param preserves legacy per-item SQL behavior for unaffected callers.

Applied to both /api/library/completion-stream (library artist detail page) and
iter_artist_discography_completion_events (Artists search page). Timing logs
added to confirm the pre-fetch cost and loop elapsed time.

On a Kendrick page load, per-album resolution drops from ~8 seconds to under
the 50ms streaming sleep floor. Observed ~100x SQL reduction on the happy path.
2026-04-21 10:47:47 -07:00
Broque Thomas
739d2f67c1 Fix Reorganize All sending every album to Albums folder
The reorganize endpoints built a template context without albumtype,
so ${albumtype} silently fell through to the engine's hardcoded "Album"
default — EPs, singles, and compilations all landed in Albums/.

Wires albumtype through from the albums table's record_type column
(populated by Spotify/Deezer/iTunes enrichment workers) with track-count
fallback when record_type is missing. New helper mirrors the download
pipeline's classification logic so reorganize produces the same folders
as initial placement. Also handles Deezer's raw 'compile' value which
the Deezer worker writes directly without mapping.
2026-04-21 08:59:16 -07:00
Antti Kettunen
bf31e929b5
Filter out curl healthchecks from access logs 2026-04-21 18:13:48 +03:00
Antti Kettunen
71e114b6fe
Tighten legacy logging output
- collapse old multi-line debug bursts into single structured rows
- remove leftover DEBUG-style prefixes from message text
- keep the app log readable without losing useful trace detail
2026-04-21 18:00:31 +03:00
Antti Kettunen
01d118daa6
Separate AcoustID file logging
- keep AcoustID logs out of app.log
- route client and verification to logs/acoustid.log
- align tag writer with the soulsync logger namespace
2026-04-21 18:00:31 +03:00
Antti Kettunen
8b9284f414
Tune Gunicorn log output
- keep access logs on stdout/stderr
- filter static, Socket.IO, and boot noise
- align Gunicorn rows with app log format
2026-04-21 18:00:29 +03:00
elmerohueso
e5c2513c56 remove pin auth test script 2026-04-21 07:20:52 -06:00
Antti Kettunen
9619a63e4e
Ignore hidden folders by default 2026-04-21 14:45:33 +03:00
Antti Kettunen
e3e0d46af9
Add another sanity check for api_call_history.json load 2026-04-21 14:42:22 +03:00
Antti Kettunen
5265864e1f
Store all log files under the same folder as the configured app.log
If the application was using a non-standard location for app.log, the other logs would still go to the default location. Now everything goes under the same, configured folder
2026-04-21 14:42:22 +03:00
Antti Kettunen
df18801ae5
Replace beatport scraper print logging with logger, mute it by default
web_server.py is already doing some logging with the scraped data, so we don't necessarily need to include the scraper's own logs in the output.

A new env variable was added to make it possible to surface the scraper's logs if needed, but it's expected that the web server's own logging should be sufficient here
2026-04-21 14:42:22 +03:00
Antti Kettunen
da40618818
Add the option to override log level via env variables 2026-04-21 14:42:21 +03:00
Antti Kettunen
721b721077
Apply persisted log level at startup 2026-04-21 14:42:21 +03:00
Antti Kettunen
e262b22e45
Remove hard-coded debug-level logging 2026-04-21 14:42:21 +03:00
Antti Kettunen
67a5bcb5a7
Rename logger namespace from newmusic to soulsync 2026-04-21 14:42:21 +03:00
Antti Kettunen
fe7ae29b8a
Replace more print logs with proper logger usage 2026-04-21 14:42:21 +03:00
Antti Kettunen
ac17bc8d87
Adjust severity for some web_server logs, remove redundant prefixes 2026-04-21 14:42:21 +03:00
Antti Kettunen
2b856b65a7
Replace web_server print statements with logger use
print calls only end up in stdout, so there will be no trace of them
once docker loses access to its own logs. Using the logger makes sure
that logs end up in the filesystem as well
2026-04-21 14:42:19 +03:00
Broque Thomas
14359a1f98 Add confirmation dialog to Reorganize All and fix button style
Shows standard SoulSync confirm dialog before bulk reorganize with
album count and template preview. Button now uses enhanced-sync-btn
class to match other artist header buttons.
2026-04-20 23:51:17 -07:00
Broque Thomas
95cf1eeeea Add Reorganize All Albums button, version bump to 2.35, changelogs
New "Reorganize All" button in enhanced library artist header processes
all albums sequentially using the configured path template.

Version bumped to 2.35. Updated What's New modal with major features
(Discography Backfill, Multi-Artist Tagging, Enriched Downloads,
Template Delimiters, Reorganize All). Updated helper.js changelog
with all April 20 fixes and features.
2026-04-20 23:46:37 -07:00
Broque Thomas
e39a3f2af7 Add multi-artist tagging options: separator, multi-value tags, feat-in-title
Three new settings in Paths & Organization:
- Artist Tag Separator: choose comma, semicolon, or slash between artists
- Write multi-value ARTISTS tag: each artist as separate tag value for
  Navidrome/Jellyfin multi-artist linking (FLAC ARTISTS key, ID3 TPE1
  multi-value, MP4 multi-entry)
- Move featured artists to title: keep only primary artist in ARTIST
  tag, append others as (feat. ...) in track title

All opt-in with defaults matching current behavior. Raw artist list
stored on metadata dict for tag writers to access without re-parsing.
2026-04-20 23:18:10 -07:00
Broque Thomas
fd014e2745 Use parent folder name as artist override in auto-import
When staging files are organized as Artist/Albums/AlbumFolder or
Artist/AlbumFolder, the auto-import now uses the parent folder name
as the artist instead of trusting embedded file tags.

Uses relative path from staging root to determine folder depth, so
albums directly in staging root don't accidentally pick up container
paths as artist names. Common category subfolder names (Albums,
Singles, EPs, Mixtapes, etc.) are recognized and skipped.

Fixes mixtapes and compilations where file tags have DJ names or
incorrect artists (e.g. files tagged as "Slim" in a 2Pac folder).
2026-04-20 22:56:34 -07:00
Broque Thomas
9c15d00128 Enrich downloads page cards with artwork, artist, album, and source badges
The downloads page previously showed only title and source per download.
Now shows album artwork thumbnail, artist name, album name, source badge,
and quality badge (after post-processing). All metadata comes from the
existing matched_downloads_context — no extra API calls needed.

Falls back gracefully to title-only display when context metadata is
not available (e.g. orphaned Soulseek transfers with no task mapping).
2026-04-20 22:18:20 -07:00
Broque Thomas
ed97fecc31 Add Discography Backfill maintenance job
New repair job that scans each artist in the library, fetches their
full discography from metadata sources, and creates findings for any
tracks not already owned. Users review findings and click "Add to
Wishlist" to queue missing tracks for download.

Respects content filters (live/remix/acoustic/instrumental/compilation)
and release type filters (album/EP/single). Opt-in, disabled by default,
runs weekly, processes up to 50 artists per run with rate limiting.
2026-04-20 22:04:38 -07:00
Broque Thomas
7287a9d184 Fix test using old deezer_track_id column name
The unknown_artist_fixer was updated to use deezer_id (matching the
actual tracks table column) but the test still passed deezer_track_id
in the track dict, causing the deezer lookup to miss and fall back
to Spotify.
2026-04-20 21:11:45 -07:00
Broque Thomas
dad915dc2c Add ${var} hint text to single, playlist, and video template hints 2026-04-20 21:07:16 -07:00
elmerohueso
e3dd5727d8 Cancel button when manually configuring plex 2026-04-20 22:00:18 -06:00
elmerohueso
3e90de7a47 clean up buttons for manually configuring plex 2026-04-20 21:57:21 -06:00
elmerohueso
d36f18f5d7 pin auth should disable fields and show library 2026-04-20 21:34:29 -06:00
elmerohueso
6a27e7930c plex oauth via pin/code 2026-04-20 21:22:44 -06:00
elmerohueso
6344f250fc buttons to configure plex or view the current configuration 2026-04-20 20:54:10 -06:00
elmerohueso
919cd1a2b2 update gitignore 2026-04-20 20:02:41 -06:00
Broque Thomas
93e036848b Add ${var} delimiter syntax for path templates
Users can now append literal text to template variables using curly
braces: ${albumtype}s produces "Albums", "Singles", "EPs". Without
braces, $albumtypes was rejected as an unknown variable by validation.

Both syntaxes work: $albumtype (plain) and ${albumtype} (delimited).
Bracket vars are resolved first to prevent partial matching conflicts.
Validation updated for album, single, and playlist templates.
2026-04-20 18:03:11 -07:00
Broque Thomas
c3f88a713a Fix unknown_artist_fixer crash on missing deezer_track_id column
The tracks table uses 'deezer_id' not 'deezer_track_id'. The query
and source field mapping both referenced the wrong column name.
2026-04-20 16:29:38 -07:00
Broque Thomas
e1819186e4 Add fix action prompt for AcoustID mismatch findings
AcoustID findings had no Fix button and bulk "Fix Selected" silently
defaulted to retag with no user choice. Now shows a 3-option prompt
(Retag / Re-download / Delete) for both individual and bulk fix,
matching the pattern used by orphan files and dead files.
2026-04-20 16:22:26 -07:00