Files
polaris/pkg/jackett/jackett.go
2024-07-01 11:34:54 +08:00

169 lines
3.6 KiB
Go

package jackett
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
var (
apiURL string
apiKey string
)
type Settings struct {
ApiURL string
ApiKey string
Client *http.Client
}
type FetchRequest struct {
Query string
Trackers []string
Categories []uint
}
type FetchResponse struct {
Results []Result
Indexers []Indexer
}
type jackettTime struct {
time.Time
}
func (jt *jackettTime) UnmarshalJSON(b []byte) (err error) {
str := strings.Trim(string(b), `"`)
if str == "0001-01-01T00:00:00" {
} else if len(str) == 19 {
jt.Time, err = time.Parse(time.RFC3339, str+"Z")
} else {
jt.Time, err = time.Parse(time.RFC3339, str)
}
return
}
type Result struct {
BannerUrl string
BlackholeLink string
Category []uint
CategoryDesc string
Comments string
Description string
DownloadVolumeFactor float32
Files uint
FirstSeen jackettTime
Gain float32
Grabs uint
Guid string
Imdb uint
InfoHash string
Link string
MagnetUri string
MinimumRatio float32
MinimumSeedTime uint
Peers uint
PublishDate jackettTime
RageID uint
Seeders uint
Size uint
TMDb uint
TVDBId uint
Title string
Tracker string
TrackerId string
UploadVolumeFactor float32
}
type Indexer struct {
Error string
ID string
Name string
Results uint
Status uint
}
type Jackett struct {
settings *Settings
}
func NewJackett(s *Settings) *Jackett {
if s.ApiURL == "" && apiURL != "" {
s.ApiURL = apiURL
}
if s.ApiKey == "" && apiKey != "" {
s.ApiKey = apiKey
}
if s.Client == nil {
s.Client = http.DefaultClient
}
return &Jackett{settings: s}
}
func (j *Jackett) generateFetchURL(fr *FetchRequest) (string, error) {
u, err := url.Parse(j.settings.ApiURL)
if err != nil {
return "", errors.Wrapf(err, "failed to parse apiURL %q", j.settings.ApiURL)
}
u.Path = "/api/v2.0/indexers/all/results"
q := u.Query()
q.Set("apikey", j.settings.ApiKey)
for _, t := range fr.Trackers {
q.Add("Tracker[]", t)
}
for _, c := range fr.Categories {
q.Add("Category[]", fmt.Sprintf("%v", c))
}
if fr.Query != "" {
q.Add("Query", fr.Query)
}
u.RawQuery = q.Encode()
return u.String(), nil
}
func (j *Jackett) Fetch(ctx context.Context, fr *FetchRequest) (*FetchResponse, error) {
u, err := j.generateFetchURL(fr)
if err != nil {
return nil, errors.Wrap(err, "failed to generate fetch url")
}
req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to make fetch request")
}
res, err := j.settings.Client.Do(req)
if err != nil {
return nil, errors.Wrap(err, "failed to invoke fetch request")
}
defer res.Body.Close()
data, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, errors.Wrap(err, "failed to read fetch data")
}
var fres FetchResponse
err = json.Unmarshal(data, &fres)
if err != nil {
return nil, errors.Wrapf(err, "failed to unmarshal fetch data with url=%v and data=%v", u, string(data))
}
return &fres, nil
}
func SearchTvWithJacket(q string, url, apiKey string) (*FetchResponse, error) {
j := NewJackett(&Settings{
ApiURL: url,
ApiKey: apiKey,
})
resp, err := j.Fetch(context.TODO(), &FetchRequest{
//Categories: []uint{uint(CategoryTV.ID)},
Query: q,
})
return resp, err
}