feat: search and grab — music release names, a quality ladder, a paced search schedule and one live grab per want (M502 #5521)
release / govulncheck (push) Successful in 21s
release / go (push) Failing after 33s
release / web (push) Successful in 56s
release / integration (push) Failing after 4m48s
release / android (push) Successful in 5m6s
release / Build signed APK (releases and dev) (push) Successful in 5m16s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Skipped
release / Verify release artifacts (tag releases only) (push) Skipped

- internal/release: reads a release name (format, bitrate, bit depth and
  sample rate, source, year, video, discography) and judges it against the
  album wanted: the artist and title must be in it; video rips,
  discographies, other versions (drumless, instrumental, karaoke, remix,
  live unless the album is live…) and singles or EPs for an album are
  refused. Quality tiers on Lidarr's ladder; a .torrent's file list is read
  for format, video files and a track count short of the album.
- internal/acquire: fan-out across every search source with a narrowed
  search kept, a process-wide pacer per source, every candidate judged and
  kept with its reasons, and the grab: one live grab per want, tie-broken
  (a person's grab beats the schedule's; a better release replaces a worse
  one unless it is nearly done). Each download lands in its own folder
  under the client's downloads folder.
- internal/wanted: the search schedule, every ten minutes, never-searched
  first, then requests, missing files and followed artists, taking the
  best release when auto-grab is on (the default).
- Migration 0082: acquisition_settings (auto-grab, interval, allowed
  qualities seeded from Lidarr's "Any"), want search columns,
  want_candidates, grabs, release_blocks.
- Web: the Wanted page shows each want's last search, a Search button and
  every release found with its verdict (Grab, Grab anyway, Never this one,
  Allow again). Integrations gains "Searching and grabbing".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-10 08:56:47 -04:00
co-authored by Claude Opus 5.5
parent 1a1646a920
commit 89b3b44779
40 changed files with 5332 additions and 49 deletions
+67
View File
@@ -217,6 +217,16 @@ type AcquisitionService struct {
UpdatedAt pgtype.Timestamptz
}
type AcquisitionSetting struct {
ID bool
AutoGrab bool
SearchIntervalHours int32
AllowedQualities []string
LastPassAt pgtype.Timestamptz
LastPass []byte
UpdatedAt pgtype.Timestamptz
}
type Album struct {
ID pgtype.UUID
Title string
@@ -420,6 +430,26 @@ type GeneralLikesArtist struct {
LikedAt pgtype.Timestamptz
}
type Grab struct {
ID pgtype.UUID
WantID pgtype.UUID
InfoHash string
Name string
Key string
Indexer string
Source string
Client string
SavePath string
Quality string
Origin string
Forced bool
GrabbedBy pgtype.UUID
GrabbedAt pgtype.Timestamptz
EndedAt pgtype.Timestamptz
EndReason string
EndDetail string
}
type LibraryChange struct {
ID int64
EntityType string
@@ -652,6 +682,16 @@ type RegistrationSetting struct {
Mode string
}
type ReleaseBlock struct {
InfoHash string
Name string
Reason string
Detail string
WantID pgtype.UUID
BlockedBy pgtype.UUID
BlockedAt pgtype.Timestamptz
}
type ReleaseTypeProfile struct {
ID pgtype.UUID
Name string
@@ -976,6 +1016,33 @@ type Want struct {
FulfilledAt pgtype.Timestamptz
CreatedAt pgtype.Timestamptz
UpdatedAt pgtype.Timestamptz
SearchedAt pgtype.Timestamptz
SearchOutcome string
SearchConsidered int32
BestRelease string
BestVerdict string
SearchError string
}
type WantCandidate struct {
WantID pgtype.UUID
Key string
Name string
InfoHash string
Indexer string
Source string
SizeBytes int64
Seeders int32
FilesCount int32
Format string
Quality string
Year int32
Verdict string
Reason string
Reasons []byte
FoldedFrom []string
Rank int32
SearchedAt pgtype.Timestamptz
}
type YouMightLikeAlbum struct {