Skip to content
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

Add lidarr naming and custom formats #138

Merged
merged 3 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/codetests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: stable
- name: go-test
run: go test -race -v -covermode=atomic ./...
# Runs golangci-lint on macos against freebsd and macos.
Expand All @@ -44,7 +44,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: stable
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
Expand All @@ -62,7 +62,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: '1.21'
go-version: stable
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
Expand Down
145 changes: 145 additions & 0 deletions lidarr/customformat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package lidarr

import (
"bytes"
"context"
"encoding/json"
"fmt"
"path"

"golift.io/starr"
)

const bpCustomFormat = APIver + "/customFormat"

// CustomFormatInput is the input for a new or updated CustomFormat.
type CustomFormatInput struct {
ID int64 `json:"id,omitempty"`
Name string `json:"name"`
IncludeCFWhenRenaming bool `json:"includeCustomFormatWhenRenaming"`
Specifications []*CustomFormatInputSpec `json:"specifications"`
}

// CustomFormatInputSpec is part of a CustomFormatInput.
type CustomFormatInputSpec struct {
Name string `json:"name"`
Implementation string `json:"implementation"`
Negate bool `json:"negate"`
Required bool `json:"required"`
Fields []*starr.FieldInput `json:"fields"`
}

// CustomFormatOutput is the output from the CustomFormat methods.
type CustomFormatOutput struct {
ID int64 `json:"id"`
Name string `json:"name"`
IncludeCFWhenRenaming bool `json:"includeCustomFormatWhenRenaming"`
Specifications []*CustomFormatOutputSpec `json:"specifications"`
}

// CustomFormatOutputSpec is part of a CustomFormatOutput.
type CustomFormatOutputSpec struct {
ID int64 `json:"id"`
Name string `json:"name"`
Implementation string `json:"implementation"`
ImplementationName string `json:"implementationName"`
InfoLink string `json:"infoLink"`
Negate bool `json:"negate"`
Required bool `json:"required"`
Fields []*starr.FieldOutput `json:"fields"`
}

// GetCustomFormats returns all configured Custom Formats.
func (l *Lidarr) GetCustomFormats() ([]*CustomFormatOutput, error) {
return l.GetCustomFormatsContext(context.Background())
}

// GetCustomFormatsContext returns all configured Custom Formats.
func (l *Lidarr) GetCustomFormatsContext(ctx context.Context) ([]*CustomFormatOutput, error) {
var output []*CustomFormatOutput

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

return output, nil
}

// GetCustomFormat returns a single custom format.
func (l *Lidarr) GetCustomFormat(customformatID int64) (*CustomFormatOutput, error) {
return l.GetCustomFormatContext(context.Background(), customformatID)
}

// GetCustomFormatContext returns a single custom format.
func (l *Lidarr) GetCustomFormatContext(ctx context.Context, customformatID int64) (*CustomFormatOutput, error) {
var output CustomFormatOutput

req := starr.Request{URI: path.Join(bpCustomFormat, starr.Itoa(customformatID))}
if err := l.GetInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
}

return &output, nil
}

// AddCustomFormat creates a new custom format and returns the response (with ID).
func (l *Lidarr) AddCustomFormat(format *CustomFormatInput) (*CustomFormatOutput, error) {
return l.AddCustomFormatContext(context.Background(), format)
}

// AddCustomFormatContext creates a new custom format and returns the response (with ID).
func (l *Lidarr) AddCustomFormatContext(ctx context.Context, format *CustomFormatInput) (*CustomFormatOutput, error) {
var output CustomFormatOutput

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

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

return &output, nil
}

// UpdateCustomFormat updates an existing custom format and returns the response.
func (l *Lidarr) UpdateCustomFormat(cf *CustomFormatInput) (*CustomFormatOutput, error) {
return l.UpdateCustomFormatContext(context.Background(), cf)
}

// UpdateCustomFormatContext updates an existing custom format and returns the response.
func (l *Lidarr) UpdateCustomFormatContext(ctx context.Context,
format *CustomFormatInput,
) (*CustomFormatOutput, error) {
var output CustomFormatOutput

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

req := starr.Request{URI: path.Join(bpCustomFormat, starr.Itoa(format.ID)), Body: &body}
if err := l.PutInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Put(%s): %w", &req, err)
}

return &output, nil
}

// DeleteCustomFormat deletes a custom format.
func (l *Lidarr) DeleteCustomFormat(cfID int64) error {
return l.DeleteCustomFormatContext(context.Background(), cfID)
}

// DeleteCustomFormatContext deletes a custom format.
func (l *Lidarr) DeleteCustomFormatContext(ctx context.Context, cfID int64) error {
req := starr.Request{URI: path.Join(bpCustomFormat, starr.Itoa(cfID))}
if err := l.DeleteAny(ctx, req); err != nil {
return fmt.Errorf("api.Delete(%s): %w", &req, err)
}

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

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

"golift.io/starr"
)

// Define Base Path for Naming calls.
const bpNaming = APIver + "/config/naming"

// Naming represents the config/naming endpoint in Lidarr.
type Naming struct {
RenameTracks bool `json:"renameTracks"`
ReplaceIllegalCharacters bool `json:"replaceIllegalCharacters"`
IncludeArtistName bool `json:"includeArtistName"`
IncludeAlbumTitle bool `json:"includeAlbumTitle"`
IncludeQuality bool `json:"includeQuality"`
ReplaceSpaces bool `json:"replaceSpaces"`
ColonReplacementFormat int `json:"colonReplacementFormat"`
ID int64 `json:"id"`
StandardTrackFormat string `json:"standardTrackFormat"`
MultiDiscTrackFormat string `json:"multiDiscTrackFormat"`
ArtistFolderFormat string `json:"artistFolderFormat"`
}

// GetNaming returns the file naming rules.
func (l *Lidarr) GetNaming() (*Naming, error) {
return l.GetNamingContext(context.Background())
}

// GetNamingContext returns the file naming rules.
func (l *Lidarr) GetNamingContext(ctx context.Context) (*Naming, error) {
var output Naming

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

return &output, nil
}

// UpdateNaming updates the file naming rules.
func (l *Lidarr) UpdateNaming(naming *Naming) (*Naming, error) {
return l.UpdateNamingContext(context.Background(), naming)
}

// UpdateNamingContext updates the file naming rules.
func (l *Lidarr) UpdateNamingContext(ctx context.Context, naming *Naming) (*Naming, error) {
var output Naming

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

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

return &output, nil
}
93 changes: 82 additions & 11 deletions lidarr/qualitydefinition.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package lidarr

import (
"bytes"
"context"
"encoding/json"
"fmt"
"path"

"golift.io/starr"
)
Expand All @@ -11,21 +14,22 @@ const bpQualityDefinition = APIver + "/qualitydefinition"

// QualityDefinition is the /api/v1/qualitydefinition endpoint.
type QualityDefinition struct {
ID int64 `json:"id"`
Quality *starr.Value `json:"quality"`
Title string `json:"title"`
Weight int64 `json:"weight"`
MinSize float64 `json:"minSize"`
MaxSize float64 `json:"maxSize,omitempty"`
ID int64 `json:"id"`
Quality *starr.Value `json:"quality"`
Title string `json:"title"`
Weight int64 `json:"weight"`
MinSize float64 `json:"minSize"`
MaxSize float64 `json:"maxSize,omitempty"`
PreferredSize float64 `json:"preferredSize"`
}

// GetQualityDefinition returns the Quality Definitions.
func (l *Lidarr) GetQualityDefinition() ([]*QualityDefinition, error) {
return l.GetQualityDefinitionContext(context.Background())
// GetQualityDefinitions returns all configured quality definitions.
func (l *Lidarr) GetQualityDefinitions() ([]*QualityDefinition, error) {
return l.GetQualityDefinitionsContext(context.Background())
}

// GetQualityDefinitionContext returns the Quality Definitions.
func (l *Lidarr) GetQualityDefinitionContext(ctx context.Context) ([]*QualityDefinition, error) {
// GetQualityDefinitionsContext returns all configured quality definitions.
func (l *Lidarr) GetQualityDefinitionsContext(ctx context.Context) ([]*QualityDefinition, error) {
var output []*QualityDefinition

req := starr.Request{URI: bpQualityDefinition}
Expand All @@ -35,3 +39,70 @@ func (l *Lidarr) GetQualityDefinitionContext(ctx context.Context) ([]*QualityDef

return output, nil
}

// GetQualityDefinition returns a single quality definition.
func (l *Lidarr) GetQualityDefinition(qualityDefinitionID int64) (*QualityDefinition, error) {
return l.GetQualityDefinitionContext(context.Background(), qualityDefinitionID)
}

// GetQualityDefinitionContext returns a single quality definition.
func (l *Lidarr) GetQualityDefinitionContext(ctx context.Context, qdID int64) (*QualityDefinition, error) {
var output QualityDefinition

req := starr.Request{URI: path.Join(bpQualityDefinition, starr.Itoa(qdID))}
if err := l.GetInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
}

return &output, nil
}

// UpdateQualityDefinition updates a quality definition.
func (l *Lidarr) UpdateQualityDefinition(definition *QualityDefinition) (*QualityDefinition, error) {
return l.UpdateQualityDefinitionContext(context.Background(), definition)
}

// UpdateQualityDefinitionContext updates a quality definition.
func (l *Lidarr) UpdateQualityDefinitionContext(
ctx context.Context,
definition *QualityDefinition,
) (*QualityDefinition, error) {
var output QualityDefinition

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

req := starr.Request{URI: path.Join(bpQualityDefinition, starr.Itoa(definition.ID)), Body: &body}
if err := l.PutInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Put(%s): %w", &req, err)
}

return &output, nil
}

// UpdateQualityDefinitions updates all quality definitions.
func (l *Lidarr) UpdateQualityDefinitions(definition []*QualityDefinition) ([]*QualityDefinition, error) {
return l.UpdateQualityDefinitionsContext(context.Background(), definition)
}

// UpdateQualityDefinitionsContext updates all quality definitions.
func (l *Lidarr) UpdateQualityDefinitionsContext(
ctx context.Context,
definition []*QualityDefinition,
) ([]*QualityDefinition, error) {
var output []*QualityDefinition

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

req := starr.Request{URI: path.Join(bpQualityDefinition, "update"), Body: &body}
if err := l.PutInto(ctx, req, &output); err != nil {
return nil, fmt.Errorf("api.Put(%s): %w", &req, err)
}

return output, nil
}
6 changes: 6 additions & 0 deletions shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,9 @@ type TimeSpan struct {
TotalMinutes int64 `json:"totalMinutes"`
TotalSeconds int64 `json:"totalSeconds"`
}

// Itoa converts an int64 to a string.
func Itoa(val int64) string {
const base10 = 10
return strconv.FormatInt(val, base10)
}
Loading