Remember unavailable movies and auto-grab them later (wishlist)

When Smart Search finds no good copy of a movie (unreleased / only CAMs), we
now record it instead of dropping it:
- New Wanted model + migration (dedup by tmdbId, status wanted|fulfilled).
- POST /__api/search/releases remembers a movie when it returns no options,
  and the UI confirms it was added to the wishlist.
- controller/wantedWatcher re-runs Smart Search for wishlisted items every 6h
  (and on boot); when a good copy appears it queues the recommended release,
  which then flows through the normal download + organize pipeline, and marks
  the item fulfilled.
- GET/DELETE /__api/search/wanted to view/remove the wishlist.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 00:51:48 -04:00
parent 2046e5080b
commit b166403309
9 changed files with 152 additions and 6 deletions
+6 -1
View File
@@ -396,7 +396,12 @@
// Step 3: render the release cards; a tap feeds the existing add dialog.
function tbpRenderReleases(data){
if(!data.options.length){ tbpSearchBody('<p>No good-quality copy of <b>'+ tbpEsc(data.title) +'</b> found — it may not be released yet, or only low-quality (CAM) copies exist.</p>'); return; }
if(!data.options.length){
var msg = '<p>No good-quality copy of <b>'+ tbpEsc(data.title) +'</b> found — it may not be released yet, or only low-quality (CAM) copies exist.</p>';
if(data.remembered) msg += '<p style="color:#2a2">✓ Added to your wishlist — we\'ll grab it automatically when a good copy appears.</p>';
tbpSearchBody(msg);
return;
}
var header = '<h3>'+ tbpEsc(data.title +' ('+ (data.year || '?') +')') +'</h3>';
if(data.library && data.library.owned) header += '<p style="color:#2a2">✓ Already in your library ('+ tbpEsc(data.library.quality) +') — only upgrades are offered.</p>';
tbpSearchBody(header);