mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-06 23:21:00 +08:00
169 lines
3.6 KiB
Go
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
|
|
}
|