Skip to content

Add lidarr as downloader #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from

Conversation

avedor
Copy link

@avedor avedor commented May 2, 2025

Implements an MVP version of a Lidarr downloader using the lidarr-go sdk. Currently, can't seem to automatically download using slskd, but the general workflow is functional. Would probably close #16

@avedor avedor force-pushed the feat/add-lidarr-download-config branch 6 times, most recently from 4333afb to c98d43c Compare May 2, 2025 16:56
@LumePart LumePart mentioned this pull request May 2, 2025
@LumePart LumePart linked an issue May 2, 2025 that may be closed by this pull request
@LumePart
Copy link
Owner

LumePart commented May 2, 2025

I'll try running it in my test environment when I have the time. the code looks really good at the moment.

It would be nice to get a function to check the download progress of the album, and if it hasn't progressed at all, let's say in 15 minutes, then the album download will stop (and removed from Lidarr). That would allow for the track to be downloaded from another downloader.

@avedor
Copy link
Author

avedor commented May 2, 2025

sounds good! i've got the actual logic written up. how would you envision something like that running? i've added it as a goroutine for now, but if there's a different architecture you'd prefer, just name it!

@LumePart
Copy link
Owner

LumePart commented May 3, 2025

i've added it as a goroutine for now

Yeah, goroutine is what I was thinking too

I looked through and ran the code and I'm a bit confused about findArtist() and addArtistIfNeeded(), previously when I investigated Lidarr, I did a manual flow of API requests to download the album and I only used /api/v1/album endpoint.

This is the request I used for adding and sending the search to indexers:

POST http://URL:PORT/api/v1/album
Header: X-Api-Key: API_KEY
Body:

{
 "foreignAlbumId": "70bdc19f-66fb-4adf-9124-925ace531101",
 "monitored": true,
 "qualityProfileId": 1,
 "rootFolderPath": "/music",
 "monitored": true,
 "artist": {
     "foreignArtistId": "89ea85c2-c90a-46ea-93db-9bed95d5c8f8",
     "qualityProfileId": 1,         // Artist's Quality Profile ID
     "metadataProfileId": 2,        // Artist's Metadata Profile ID
     "monitored": true,
     "rootFolderPath": "/music"
     },
 "addOptions": {
     "searchForNewAlbum": true
     }
}

AlbumID and artistID came from album lookup and the ProfileID's could probably be config parameters if the SDK supports it.
I had trouble implementing the same flow with the SDK, but I can try again tomorrow.

And i fixed a small issue with track.MainArtist in the dev branch, when searching for albums it's best to use that field, track.Artist could contain all the artists on the track (i.e Justice feat. Tame Impala)

Add helper funcs; implement hour cooldown for search

Check for rejected releases

Add cleanup func and worker

Add check to artist adding

Mark track as present
@avedor avedor force-pushed the feat/add-lidarr-download-config branch from 4582a13 to 3f855d8 Compare May 3, 2025 21:42
@avedor
Copy link
Author

avedor commented May 3, 2025

Yeah! so the whole flow was a little confusing for me as well and the sdk doesn't seem to map 1:1 onto the api endpoints which is... frustrating.

my understanding is we've got the foreign (read musicbrainz) ids for everything and the internal (lidarr) ids. Lidarr ids for artist/album don't get set if the artist isn't in lidarr already, so findArtist does the lookup using a string query--though could probably be switched to use the artist mbid if we add that as a field in the track struct--then the addArtistIfNeeded is creating the artist in lidarr, if it isn't already there, using defaults pulled from the root settings.

i'll dig into the sdk a little further to see if i can bypass a lot of the lookups and just use the mbids to create the album in lidarr

@avedor
Copy link
Author

avedor commented May 4, 2025

just for complete context, between these changes, and those in #22, i've now got a new playlist in jellyfin with 33/50 tracks!

as far as the flow using sdk is concerned, i think we're roughly stuck at:

  1. look up artist using string term search and return ArtistResource
  2. pass that into addArtistIfNeeded which checks to see if a. the artist has a path set and b. has a non-zero timestamp for when the artist was added. if not, it creates a new ArtistResource with some defaults from the root settings and calls CreateArtist to add the artist to lidarr
  3. repeat the same basic flow for album and release

@LumePart
Copy link
Owner

LumePart commented May 5, 2025

Wouldn't it be more straightforward to do it without the SDK? It would reduce the amount of flows needed and would give us greater control of the request payloads. Especially when we don't need most of the API functionality (most likely 4-5 endpoints for a full workflow).

The flow would look pretty much like this:

  1. Query album to get artistID and AlbumID
  2. Request album to be downloaded/sent to indexer
  3. Periodically check if it's downloading
  4. If downloaded, mark track as Present otherwise clean Lidarr of artist/track

Feel free to debate me on this, maybe i just don't get the point of the SDK when Lidarr's API documentation is pretty good.

Add download monitor
@avedor avedor force-pushed the feat/add-lidarr-download-config branch from aa1e25b to c1be6c0 Compare May 5, 2025 22:59
@avedor
Copy link
Author

avedor commented May 5, 2025

This is the first time I've used an SDK, so I'm happy to do it either way! I just pushed up a couple squashed commits that should do all of this a little more cleanly (storing the MBIDs) in the track struct for ease. I also updated the goroutine to both clear stale downloads and mark present newly available tracks

Looking forward to your thoughts!

@avedor avedor changed the title Feat/add lidarr download config Add lidarr as downloader May 5, 2025
@LumePart
Copy link
Owner

LumePart commented May 31, 2025

Made a few changes in the dev branch, main changes include:

  • Added a MonitorDownloads([]*models.Track) function to the Downloader interface, Lidarr most likely can make use of this.
  • queryTrack() and getTrack() are asynchronous now
  • Added a few fields to Track struct, including a field to store the track size (if needed) and an field from ListenBrainz (length (in ms))

I'm also pretty much finished with implementing slskd, you can check how I implemented download monitoring there

Also, the linter fails, but that is expected atm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Lidarr Support
2 participants