Skip to content

Commit

Permalink
Add queue grab and manualimport methods to all four apps. (#124)
Browse files Browse the repository at this point in the history
* Add queue grab methods

* radarr manual import

* sonarr manual import

* lidarr and readarr manual import

* add track.go and bookfile.go

* code comments

* add moviefile for radarr
  • Loading branch information
davidnewhall authored Aug 29, 2023
1 parent 2470ad3 commit e85fbe7
Show file tree
Hide file tree
Showing 16 changed files with 1,039 additions and 57 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/codetests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: 'v1.53'
version: 'v1.54'
# Runs golangci-lint on linux against linux and windows.
golangci-linux:
strategy:
Expand All @@ -67,4 +67,4 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: 'v1.53'
version: 'v1.54'
114 changes: 114 additions & 0 deletions lidarr/manualimport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package lidarr

import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/url"

"golift.io/starr"
)

// Define Base Path for Manual Import calls.
const bpManualImport = APIver + "/manualimport"

// ManualImportInput is the input data for a manual import request using a POST request.
type ManualImportInput struct {
ID int64 `json:"id"`
Path string `json:"path"`
Name string `json:"name"`
ArtistID int64 `json:"artistID"`
AlbumID int64 `json:"albumID"`
AlbumReleaseID int64 `json:"albumReleaseId"`
Tracks []*Track `json:"tracks"`
TrackIDs []int64 `json:"trackIds"`
Quality *starr.Quality `json:"quality"`
ReleaseGroup string `json:"releaseGroup"`
DownloadID string `json:"downloadId"`
AdditionalFile bool `json:"additionalFile"`
ReplaceExistingFiles bool `json:"replaceExistingFiles"`
DisableReleaseSwitching bool `json:"disableReleaseSwitching"`
Rejections []*Rejection `json:"rejections"`
}

// ManualImportOutput is the output data for a manual import request.
type ManualImportOutput struct {
ID int64 `json:"id"`
Path string `json:"path"`
Name string `json:"name"`
Size int `json:"size"`
Artist *Artist `json:"artist"`
Album *Album `json:"album"`
AlbumReleaseID int64 `json:"albumReleaseId"`
Tracks []*Track `json:"tracks"`
Quality *starr.Quality `json:"quality"`
ReleaseGroup string `json:"releaseGroup"`
QualityWeight int64 `json:"qualityWeight"`
DownloadID string `json:"downloadId"`
AudioTags *AudioTags `json:"audioTags"`
AdditionalFile bool `json:"additionalFile"`
ReplaceExistingFiles bool `json:"replaceExistingFiles"`
DisableReleaseSwitching bool `json:"disableReleaseSwitching"`
Rejections []*Rejection `json:"rejections"`
}

// Rejection is part of the manual import payload.
type Rejection struct {
Reason string `json:"reason"`
// permanent or temporary
Type string `json:"type"`
}

// ManualImportParams provides the input parameters for the GET /manualimport API.
type ManualImportParams struct {
Folder string
DownloadID string
ArtistID int64
ReplaceExistingFiles bool
FilterExistingFiles bool
}

// ManualImport initiates a manual import (GET).
func (l *Lidarr) ManualImport(params *ManualImportParams) (*ManualImportOutput, error) {
return l.ManualImportContext(context.Background(), params)
}

// ManualImportContext initiates a manual import (GET).
func (l *Lidarr) ManualImportContext(ctx context.Context, params *ManualImportParams) (*ManualImportOutput, error) {
req := starr.Request{URI: bpManualImport, Query: make(url.Values)}
req.Query.Add("folder", params.Folder)
req.Query.Add("downloadId", params.DownloadID)
req.Query.Add("artistId", fmt.Sprint(params.ArtistID))
req.Query.Add("replaceExistingFiles", fmt.Sprint(params.ReplaceExistingFiles))
req.Query.Add("filterExistingFiles", fmt.Sprint(params.FilterExistingFiles))

var output ManualImportOutput
if err := l.GetInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
}

return &output, nil
}

// ManualImportReprocess reprocesses a manual import (POST).
func (l *Lidarr) ManualImportReprocess(manualimport *ManualImportInput) error {
return l.ManualImportReprocessContext(context.Background(), manualimport)
}

// ManualImportReprocessContext reprocesses a manual import (POST).
func (l *Lidarr) ManualImportReprocessContext(ctx context.Context, manualimport *ManualImportInput) error {
var output interface{}

var body bytes.Buffer
if err := json.NewEncoder(&body).Encode(manualimport); err != nil {
return fmt.Errorf("json.Marshal(%s): %w", bpManualImport, err)
}

req := starr.Request{URI: bpManualImport, Body: &body}
if err := l.PostInto(ctx, req, &output); err != nil {
return fmt.Errorf("api.Post(%s): %w", &req, err)
}

return nil
}
30 changes: 30 additions & 0 deletions lidarr/queue.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package lidarr

import (
"bytes"
"context"
"encoding/json"
"fmt"
"path"
"time"
Expand Down Expand Up @@ -120,3 +122,31 @@ func (l *Lidarr) DeleteQueueContext(ctx context.Context, queueID int64, opts *st

return nil
}

// QueueGrab tells the app to grab an item that's in queue.
// Most often used on items with a delay set from a delay profile.
func (l *Lidarr) QueueGrab(ids ...int64) error {
return l.QueueGrabContext(context.Background(), ids...)
}

// QueueGrabContext tells the app to grab an item that's in queue, probably set to a delay.
// Most often used on items with a delay set from a delay profile.
func (l *Lidarr) QueueGrabContext(ctx context.Context, ids ...int64) error {
idList := struct {
IDs []int64 `json:"ids"`
}{IDs: ids}

var body bytes.Buffer
if err := json.NewEncoder(&body).Encode(idList); err != nil {
return fmt.Errorf("json.Marshal(%s): %w", bpQueue, err)
}

var output interface{} // any ok

req := starr.Request{URI: path.Join(bpQueue, "grab", "bulk"), Body: &body}
if err := l.PostInto(ctx, req, &output); err != nil {
return fmt.Errorf("api.Post(%s): %w", &req, err)
}

return nil
}
106 changes: 106 additions & 0 deletions lidarr/track.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package lidarr

import (
"context"
"fmt"
"net/url"

"golift.io/starr"
)

const bpTrack = APIver + "/track"

// Track is an album track.
type Track struct {
ArtistID int64 `json:"artistId"`
ForeignTrackID string `json:"foreignTrackId"`
ForeignRecordingID string `json:"foreignRecordingId"`
TrackFileID int64 `json:"trackFileId"`
AlbumID int64 `json:"albumId"`
Explicit bool `json:"explicit"`
AbsoluteTrackNumber int `json:"absoluteTrackNumber"`
TrackNumber string `json:"trackNumber"`
Title string `json:"title"`
Duration int `json:"duration"`
MediumNumber int `json:"mediumNumber"`
HasFile bool `json:"hasFile"`
Ratings *starr.Ratings `json:"ratings"`
Grabbed bool `json:"grabbed"`
ID int64 `json:"id"`
Artist *Artist `json:"artist"` // probably empty.
TrackFile *TrackFile `json:"trackFile"` // probably empty.
}

// GetTracks by their IDs.
func (l *Lidarr) GetTracks(trackID ...int64) ([]*Track, error) {
return l.GetTracksContext(context.Background(), trackID...)
}

// GetTracksContext gets track files by their IDs using a provided context.
func (l *Lidarr) GetTracksContext(ctx context.Context, trackID ...int64) ([]*Track, error) {
req := starr.Request{URI: bpTrack, Query: make(url.Values)}
for _, id := range trackID {
req.Query.Add("trackIds", fmt.Sprint(id))
}

var output []*Track
if err := l.GetInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
}

return output, nil
}

// GetTracksByAlbum gets track files using an album ID.
func (l *Lidarr) GetTracksByAlbum(albumID int64) ([]*Track, error) {
return l.GetTracksByAlbumContext(context.Background(), albumID)
}

// GetTracksByAlbumContext gets track files using an album ID.
func (l *Lidarr) GetTracksByAlbumContext(ctx context.Context, albumID int64) ([]*Track, error) {
req := starr.Request{URI: bpTrack, Query: make(url.Values)}
req.Query.Add("albumId", fmt.Sprint(albumID))

var output []*Track
if err := l.GetInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
}

return output, nil
}

// GetTracksByArtist gets track files using an artist ID.
func (l *Lidarr) GetTracksByArtist(artistID int64) ([]*Track, error) {
return l.GetTracksByArtistContext(context.Background(), artistID)
}

// GetTracksByAlbumRelease gets track files using an artist ID.
func (l *Lidarr) GetTracksByArtistContext(ctx context.Context, artistID int64) ([]*Track, error) {
req := starr.Request{URI: bpTrack, Query: make(url.Values)}
req.Query.Add("artistId", fmt.Sprint(artistID))

var output []*Track
if err := l.GetInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
}

return output, nil
}

// GetTracksByAlbumRelease gets track files using an album release ID.
func (l *Lidarr) GetTracksByAlbumRelease(albumID int64) ([]*Track, error) {
return l.GetTracksByAlbumContext(context.Background(), albumID)
}

// GetTracksByAlbumReleaseContext gets track files using an album release ID.
func (l *Lidarr) GetTracksByAlbumReleaseContext(ctx context.Context, albumReleaseID int64) ([]*Track, error) {
req := starr.Request{URI: bpTrack, Query: make(url.Values)}
req.Query.Add("albumReleaseId", fmt.Sprint(albumReleaseID))

var output []*Track
if err := l.GetInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
}

return output, nil
}
17 changes: 1 addition & 16 deletions lidarr/trackfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,29 +60,14 @@ type AudioTags struct {
Label string `json:"label"`
CatalogNumber string `json:"catalogNumber"`
Disambiguation string `json:"disambiguation"`
Duration *TrackDuration `json:"duration"`
Duration *starr.TimeSpan `json:"duration"`
Quality *starr.Quality `json:"quality"`
MediaInfo *AudioMediaInfo `json:"mediaInfo"`
TrackNumbers []int `json:"trackNumbers"`
ReleaseGroup string `json:"releaseGroup"`
ReleaseHash string `json:"releaseHash"`
}

// TrackDuration is part of AudioTags.
type TrackDuration struct {
Ticks int64 `json:"ticks"`
Days int64 `json:"days"`
Hours int64 `json:"hours"`
Milliseconds int64 `json:"milliseconds"`
Minutes int64 `json:"minutes"`
Seconds int64 `json:"seconds"`
TotalDays int64 `json:"totalDays"`
TotalHours int64 `json:"totalHours"`
TotalMilliseconds int64 `json:"totalMilliseconds"`
TotalMinutes int64 `json:"totalMinutes"`
TotalSeconds int64 `json:"totalSeconds"`
}

// AudioMediaInfo is part of AudioTags.
type AudioMediaInfo struct {
AudioFormat string `json:"audioFormat"`
Expand Down
Loading

0 comments on commit e85fbe7

Please sign in to comment.