From 227d467600816f46e0e0c7ceec9bb8c00fc943e2 Mon Sep 17 00:00:00 2001 From: David Newhall II Date: Wed, 18 Feb 2026 22:03:11 -0800 Subject: [PATCH 1/2] update xrtractr --- go.mod | 3 +-- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c96edef..ff3d8fe 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( golift.io/rotatorr v0.0.0-20260217050959-f6ac6fc7b38e golift.io/starr v1.3.0 golift.io/version v0.0.2 - golift.io/xtractr v0.3.1-0.20260218060125-b814a941badb + golift.io/xtractr v0.3.1-0.20260219054943-e6f0434c2d7a gopkg.in/yaml.v3 v3.0.1 ) @@ -84,4 +84,3 @@ require ( golift.io/udf v0.0.1 // indirect google.golang.org/protobuf v1.36.11 // indirect ) - diff --git a/go.sum b/go.sum index eaa777f..3be9cd4 100644 --- a/go.sum +++ b/go.sum @@ -242,8 +242,6 @@ golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golift.io/cnfg v0.2.4 h1:AfSueg0p6DTCufZjxRWlMSeSAL2eMJ6lN/ySmvpTl50= -golift.io/cnfg v0.2.4/go.mod h1:iMzXYjvZI7iZphzY75hkFR/VShYeuZznXiQtFsBOSCU= golift.io/cnfg v0.2.5 h1:NwhQ+REL9BSTiHYU4MKMawCEzvtjmhE8RlNiE7XroqE= golift.io/cnfg v0.2.5/go.mod h1:iMzXYjvZI7iZphzY75hkFR/VShYeuZznXiQtFsBOSCU= golift.io/cnfgfile v0.0.0-20240713024420-a5436d84eb48 h1:c7cJWRr0cUnFHKtq072esKzhQHKlFA5YRY/hPzQrdko= @@ -256,8 +254,8 @@ golift.io/udf v0.0.1 h1:kEcJVzqqR+IEWGMuPjuVPT9DzXRDukEgsizKAKn1LF8= golift.io/udf v0.0.1/go.mod h1:ndK7AlWOh+u+nW9tNsQR95dfHsfASG5Y3dMyzVqmPjw= golift.io/version v0.0.2 h1:i0gXRuSDHKs4O0sVDUg4+vNIuOxYoXhaxspftu2FRTE= golift.io/version v0.0.2/go.mod h1:76aHNz8/Pm7CbuxIsDi97jABL5Zui3f2uZxDm4vB6hU= -golift.io/xtractr v0.3.1-0.20260218060125-b814a941badb h1:03V2/jDBm5QJTAFB6NxF0esrOJ85u6Vo0DIzQUk069Q= -golift.io/xtractr v0.3.1-0.20260218060125-b814a941badb/go.mod h1:+eMxkIVQjwJENgn9XCSqmsPGuzWOPvn3Ez5YSRM2Dgw= +golift.io/xtractr v0.3.1-0.20260219054943-e6f0434c2d7a h1:GvHGPVvHxogdT4Jf6v4t85tQ5+VULd0gX4kYHh3dsJ8= +golift.io/xtractr v0.3.1-0.20260219054943-e6f0434c2d7a/go.mod h1:bDBgCgojMc0HncBUMD29MYIaupCq9enUbeAYeB8AuNY= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E= From 9dedda519f05e0c08069aa5c500efea2f2a68c77 Mon Sep 17 00:00:00 2001 From: David Newhall II Date: Thu, 19 Feb 2026 22:23:02 -0800 Subject: [PATCH 2/2] Import FLAC tracks into Lidarr manually --- go.mod | 4 +-- go.sum | 4 +-- pkg/unpackerr/handlers.go | 8 ++++- pkg/unpackerr/lidarr.go | 70 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index ff3d8fe..a081815 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/Unpackerr/unpackerr go 1.26.0 -//nolint:gomoddirectives // we need to use our own iso9660 package until we fix the issue with the original package. +// we need to use our own iso9660 package until we fix the issue with the original package. replace github.com/kdomanski/iso9660 => github.com/Unpackerr/iso9660 v0.0.1 require ( @@ -22,7 +22,7 @@ require ( golift.io/cnfg v0.2.5 golift.io/cnfgfile v0.0.0-20240713024420-a5436d84eb48 golift.io/rotatorr v0.0.0-20260217050959-f6ac6fc7b38e - golift.io/starr v1.3.0 + golift.io/starr v1.3.1-0.20260220055600-a1399516cfeb golift.io/version v0.0.2 golift.io/xtractr v0.3.1-0.20260219054943-e6f0434c2d7a gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 3be9cd4..f88cea9 100644 --- a/go.sum +++ b/go.sum @@ -248,8 +248,8 @@ golift.io/cnfgfile v0.0.0-20240713024420-a5436d84eb48 h1:c7cJWRr0cUnFHKtq072esKz golift.io/cnfgfile v0.0.0-20240713024420-a5436d84eb48/go.mod h1:zHm9o8SkZ6Mm5DfGahsrEJPsogyR0qItP59s5lJ98/I= golift.io/rotatorr v0.0.0-20260217050959-f6ac6fc7b38e h1:FgfNgbg2EUhFzAWPycsbh1dYiFJNLJFDDkn+E298DFQ= golift.io/rotatorr v0.0.0-20260217050959-f6ac6fc7b38e/go.mod h1:l/fgYTDxyEw15tRLjAtc13M3is1SXMU4hAIE0tdduAQ= -golift.io/starr v1.3.0 h1:dmIt27th+LWIPWHdiHXvDeG8H1h9TT+PQE1ID3DssFY= -golift.io/starr v1.3.0/go.mod h1:W8A/49qhVfoU0HgZyJla4NKRCM5eUHuhSesc+buPIBU= +golift.io/starr v1.3.1-0.20260220055600-a1399516cfeb h1:sRpFSdVj+mb3/ZG57GVDwEzWZlF0UdhGZqFtPrwgaxs= +golift.io/starr v1.3.1-0.20260220055600-a1399516cfeb/go.mod h1:W8A/49qhVfoU0HgZyJla4NKRCM5eUHuhSesc+buPIBU= golift.io/udf v0.0.1 h1:kEcJVzqqR+IEWGMuPjuVPT9DzXRDukEgsizKAKn1LF8= golift.io/udf v0.0.1/go.mod h1:ndK7AlWOh+u+nW9tNsQR95dfHsfASG5Y3dMyzVqmPjw= golift.io/version v0.0.2 h1:i0gXRuSDHKs4O0sVDUg4+vNIuOxYoXhaxspftu2FRTE= diff --git a/pkg/unpackerr/handlers.go b/pkg/unpackerr/handlers.go index 7fca19b..c00ed9b 100644 --- a/pkg/unpackerr/handlers.go +++ b/pkg/unpackerr/handlers.go @@ -215,7 +215,8 @@ func (u *Unpackerr) checkExtractDone(now time.Time) { // handleXtractrCallback handles callbacks from the xtractr library for starr apps (not folders). // This takes the provided info and logs it then sends it the queue update method. func (u *Unpackerr) handleXtractrCallback(resp *xtractr.Response) { - if item := u.Map[resp.X.Name]; resp.Done && item != nil { + item := u.Map[resp.X.Name] + if resp.Done && item != nil { u.updateMetrics(resp, item.App, item.URL) } else if item != nil { item.XProg.Archives = resp.Archives.Count() + resp.Extras.Count() @@ -235,6 +236,11 @@ func (u *Unpackerr) handleXtractrCallback(resp *xtractr.Response) { resp.Archives.Count(), resp.Extras.Count(), len(resp.NewFiles), bytefmt.ByteSize(resp.Size)) u.Debugf("Extraction Finished: %d files in path: %s", len(files), files) u.updateQueueStatus(&newStatus{Name: resp.X.Name, Status: EXTRACTED, Resp: resp}, now, true) + + if item != nil && item.App == starr.Lidarr && item.SplitFlac && + extractionHasFlacFiles(resp.NewFiles) { + go u.importSplitFlacTracks(item, u.lidarrServerByURL(item.URL)) + } } } diff --git a/pkg/unpackerr/lidarr.go b/pkg/unpackerr/lidarr.go index 84e13d7..1ba9715 100644 --- a/pkg/unpackerr/lidarr.go +++ b/pkg/unpackerr/lidarr.go @@ -2,6 +2,7 @@ package unpackerr import ( "errors" + "strings" "time" "golift.io/starr" @@ -136,3 +137,72 @@ func (u *Unpackerr) haveLidarrQitem(name string) bool { return false } + +// lidarrServerByURL returns the Lidarr server config that matches the given URL, or nil. +func (u *Unpackerr) lidarrServerByURL(url string) *LidarrConfig { + for _, server := range u.Lidarr { + if server.URL == url { + return server + } + } + + return nil +} + +// extractionHasFlacFiles returns true if any path in files has a .flac extension. +// Used to only trigger manual import after a FLAC+CUE split, not for e.g. zip-of-mp3s. +func extractionHasFlacFiles(files []string) bool { + for _, p := range files { + if strings.HasSuffix(strings.ToLower(p), ".flac") { + return true + } + } + + return false +} + +// importSplitFlacTracks runs in a goroutine after a Lidarr FLAC+CUE split extraction completes. +// It asks Lidarr for the manual import list for the extract folder and sends the ManualImport command +// so Lidarr imports the split track files. +func (u *Unpackerr) importSplitFlacTracks(item *Extract, server *LidarrConfig) { + if server == nil { + u.Printf("[Lidarr] No Lidarr server found for manual import, this might be a bug: %s", item.Path) + return + } + + downloadID, _ := item.IDs["downloadId"].(string) + artistID, _ := item.IDs["artistId"].(int64) + + params := &lidarr.ManualImportParams{ + Folder: item.Path, + DownloadID: downloadID, + ArtistID: artistID, + FilterExistingFiles: false, + ReplaceExistingFiles: true, + } + + outputs, err := server.ManualImport(params) + if err != nil { + u.Errorf("[Lidarr] Manual import list failed for %s: %v", item.Path, err) + return + } + + if len(outputs) == 0 { + u.Printf("[Lidarr] No files returned for manual import (folder: %s); import manually in Lidarr", item.Path) + return + } + + cmd := lidarr.ManualImportCommandFromOutputs(outputs, true) + if cmd == nil { + u.Printf("[Lidarr] No importable files for manual import: %s", item.Path) + return + } + + _, err = server.SendManualImportCommand(cmd) + if err != nil { + u.Errorf("[Lidarr] Manual import command failed for %s: %v", item.Path, err) + return + } + + u.Printf("[Lidarr] Manual import triggered for %d files: %s", len(cmd.Files), item.Path) +}