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>
46 lines
1.5 KiB
Go
46 lines
1.5 KiB
Go
package acquire
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
|
|
"git.fabledsword.com/bvandeusen/minstrel/internal/release"
|
|
)
|
|
|
|
// Build makes a Service from the settings as they stand: every enabled
|
|
// search source behind one paced Fanout, the first enabled download client,
|
|
// and the quality profile. Built afresh for each pass and each request, so a
|
|
// changed setting takes effect on the next one.
|
|
func Build(ctx context.Context, pool *pgxpool.Pool) (*Service, dbq.AcquisitionSetting, error) {
|
|
q := dbq.New(pool)
|
|
settings, err := q.GetAcquisitionSettings(ctx)
|
|
if err != nil {
|
|
return nil, settings, fmt.Errorf("acquire: read settings: %w", err)
|
|
}
|
|
sources, err := Sources(ctx, pool)
|
|
if err != nil {
|
|
return nil, settings, fmt.Errorf("acquire: read search sources: %w", err)
|
|
}
|
|
clients, err := q.ListUsableAcquisitionServices(ctx, JobDownload)
|
|
if err != nil {
|
|
return nil, settings, fmt.Errorf("acquire: read download clients: %w", err)
|
|
}
|
|
s := &Service{Profile: release.NewProfile(settings.AllowedQualities), Memory: NewMemory(pool)}
|
|
fan := &Fanout{Sources: sources, Pace: SearchPace}
|
|
if len(sources) > 0 {
|
|
s.Search = fan
|
|
}
|
|
if len(clients) > 0 {
|
|
row := clients[0]
|
|
client, err := DownloadClient(row)
|
|
if err != nil {
|
|
return nil, settings, fmt.Errorf("acquire: download client %s: %w", row.Code, err)
|
|
}
|
|
s.Grabber = &Downloader{Client: client, Code: row.Code, Landing: row.LocalPath, Fetch: fan}
|
|
}
|
|
return s, settings, nil
|
|
}
|