-
-
Notifications
You must be signed in to change notification settings - Fork 122
/
readarr.go
162 lines (128 loc) · 4.04 KB
/
readarr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright (c) 2021 - 2024, Ludvig Lundgren and the autobrr contributors.
// SPDX-License-Identifier: GPL-2.0-or-later
package readarr
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"log"
"github.com/autobrr/autobrr/pkg/errors"
"github.com/autobrr/autobrr/pkg/sharedhttp"
)
type Config struct {
Hostname string
APIKey string
// basic auth username and password
BasicAuth bool
Username string
Password string
Log *log.Logger
}
type Client interface {
Test(ctx context.Context) (*SystemStatusResponse, error)
Push(ctx context.Context, release Release) ([]string, error)
}
type client struct {
config Config
http *http.Client
Log *log.Logger
}
// New create new readarr client
func New(config Config) Client {
httpClient := &http.Client{
Timeout: time.Second * 120,
Transport: sharedhttp.Transport,
}
c := &client{
config: config,
http: httpClient,
Log: log.New(io.Discard, "", log.LstdFlags),
}
if config.Log != nil {
c.Log = config.Log
}
return c
}
type Release struct {
Title string `json:"title"`
InfoUrl string `json:"infoUrl,omitempty"`
DownloadUrl string `json:"downloadUrl,omitempty"`
MagnetUrl string `json:"magnetUrl,omitempty"`
Size int64 `json:"size"`
Indexer string `json:"indexer"`
DownloadProtocol string `json:"downloadProtocol"`
Protocol string `json:"protocol"`
PublishDate string `json:"publishDate"`
DownloadClientId int `json:"downloadClientId,omitempty"`
DownloadClient string `json:"downloadClient,omitempty"`
}
type PushResponse struct {
Approved bool `json:"approved"`
Rejected bool `json:"rejected"`
TempRejected bool `json:"temporarilyRejected"`
Rejections []string `json:"rejections"`
}
type BadRequestResponse struct {
PropertyName string `json:"propertyName"`
ErrorMessage string `json:"errorMessage"`
ErrorCode string `json:"errorCode"`
AttemptedValue string `json:"attemptedValue"`
Severity string `json:"severity"`
}
func (r *BadRequestResponse) String() string {
return fmt.Sprintf("[%s: %s] %s: %s - got value: %s", r.Severity, r.ErrorCode, r.PropertyName, r.ErrorMessage, r.AttemptedValue)
}
type SystemStatusResponse struct {
AppName string `json:"appName"`
Version string `json:"version"`
}
func (c *client) Test(ctx context.Context) (*SystemStatusResponse, error) {
status, res, err := c.get(ctx, "system/status")
if err != nil {
return nil, errors.Wrap(err, "could not make Test")
}
if status == http.StatusUnauthorized {
return nil, errors.New("unauthorized: bad credentials")
}
c.Log.Printf("readarr system/status status: (%v) response: %v\n", status, string(res))
response := SystemStatusResponse{}
if err = json.Unmarshal(res, &response); err != nil {
return nil, errors.Wrap(err, "could not unmarshal data")
}
return &response, nil
}
func (c *client) Push(ctx context.Context, release Release) ([]string, error) {
status, res, err := c.postBody(ctx, "release/push", release)
if err != nil {
return nil, errors.Wrap(err, "could not push release to readarr")
}
c.Log.Printf("readarr release/push status: (%v) response: %v\n", status, string(res))
if status == http.StatusBadRequest {
badRequestResponses := make([]*BadRequestResponse, 0)
if err = json.Unmarshal(res, &badRequestResponses); err != nil {
return nil, errors.Wrap(err, "could not unmarshal data")
}
rejections := []string{}
for _, response := range badRequestResponses {
rejections = append(rejections, response.String())
}
return rejections, nil
}
// pushResponse := make([]PushResponse, 0)
var pushResponse PushResponse
if err = json.Unmarshal(res, &pushResponse); err != nil {
return nil, errors.Wrap(err, "could not unmarshal data")
}
// log and return if rejected
if pushResponse.Rejected {
rejections := strings.Join(pushResponse.Rejections, ", ")
c.Log.Printf("readarr release/push rejected %v reasons: %q\n", release.Title, rejections)
return pushResponse.Rejections, nil
}
// successful push
return nil, nil
}