7
media/trakt/config.go
Normal file
7
media/trakt/config.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package trakt
|
||||
|
||||
type Config struct {
|
||||
ClientId string `yaml:"client_id"`
|
||||
|
||||
Verbosity string `yaml:"verbosity,omitempty"`
|
||||
}
|
||||
96
media/trakt/media.go
Normal file
96
media/trakt/media.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package trakt
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/l3uddz/nabarr/util"
|
||||
"github.com/lucperkins/rek"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrItemNotFound = errors.New("not found")
|
||||
)
|
||||
|
||||
func (c *Client) GetShow(tvdbId string) (*Show, error) {
|
||||
// prepare request
|
||||
reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, fmt.Sprintf("/search/tvdb/%s", tvdbId)),
|
||||
url.Values{
|
||||
"type": []string{"show"},
|
||||
"extended": []string{"full"}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate lookup show request url: %w", err)
|
||||
}
|
||||
|
||||
c.log.Trace().
|
||||
Str("url", reqUrl).
|
||||
Msg("Searching trakt")
|
||||
|
||||
// send request
|
||||
c.rl.Take()
|
||||
resp, err := rek.Get(reqUrl, rek.Headers(c.getAuthHeaders()), rek.Timeout(c.apiTimeout))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request show: %w", err)
|
||||
}
|
||||
defer resp.Body().Close()
|
||||
|
||||
// validate response
|
||||
if resp.StatusCode() != 200 {
|
||||
return nil, fmt.Errorf("validate show response: %s", resp.Status())
|
||||
}
|
||||
|
||||
// decode response
|
||||
b := new([]struct{ Show Show })
|
||||
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
||||
return nil, fmt.Errorf("decode show response: %w", err)
|
||||
}
|
||||
|
||||
if len(*b) < 1 {
|
||||
return nil, ErrItemNotFound
|
||||
}
|
||||
|
||||
// translate response
|
||||
return &(*b)[0].Show, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetMovie(imdbId string) (*Movie, error) {
|
||||
// prepare request
|
||||
reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, fmt.Sprintf("/search/imdb/%s", imdbId)),
|
||||
url.Values{
|
||||
"type": []string{"movie"},
|
||||
"extended": []string{"full"}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate lookup movie request url: %w", err)
|
||||
}
|
||||
|
||||
c.log.Trace().
|
||||
Str("url", reqUrl).
|
||||
Msg("Searching trakt")
|
||||
|
||||
// send request
|
||||
c.rl.Take()
|
||||
resp, err := rek.Get(reqUrl, rek.Headers(c.getAuthHeaders()), rek.Timeout(c.apiTimeout))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request movie: %w", err)
|
||||
}
|
||||
defer resp.Body().Close()
|
||||
|
||||
// validate response
|
||||
if resp.StatusCode() != 200 {
|
||||
return nil, fmt.Errorf("validate movie response: %s", resp.Status())
|
||||
}
|
||||
|
||||
// decode response
|
||||
b := new([]struct{ Movie Movie })
|
||||
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
||||
return nil, fmt.Errorf("decode movie response: %w", err)
|
||||
}
|
||||
|
||||
if len(*b) < 1 {
|
||||
return nil, ErrItemNotFound
|
||||
}
|
||||
|
||||
// translate response
|
||||
return &(*b)[0].Movie, nil
|
||||
}
|
||||
67
media/trakt/struct.go
Normal file
67
media/trakt/struct.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package trakt
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ShowIds struct {
|
||||
Trakt int `json:"trakt"`
|
||||
Slug string `json:"slug"`
|
||||
Tvdb int `json:"tvdb"`
|
||||
Imdb string `json:"imdb"`
|
||||
Tmdb int `json:"tmdb"`
|
||||
}
|
||||
|
||||
type MovieIds struct {
|
||||
Trakt int `json:"trakt"`
|
||||
Slug string `json:"slug"`
|
||||
Imdb string `json:"imdb"`
|
||||
Tmdb int `json:"tmdb"`
|
||||
}
|
||||
|
||||
type Show struct {
|
||||
Type string `json:"type"`
|
||||
Title string `json:"title"`
|
||||
Year int `json:"year"`
|
||||
Ids ShowIds `json:"ids"`
|
||||
Overview string `json:"overview"`
|
||||
FirstAired time.Time `json:"first_aired"`
|
||||
Runtime int `json:"runtime"`
|
||||
Certification string `json:"certification"`
|
||||
Network string `json:"network"`
|
||||
Country string `json:"country"`
|
||||
Trailer string `json:"trailer"`
|
||||
Homepage string `json:"homepage"`
|
||||
Status string `json:"status"`
|
||||
Rating float64 `json:"rating"`
|
||||
Votes int `json:"votes"`
|
||||
CommentCount int `json:"comment_count"`
|
||||
Language string `json:"language"`
|
||||
AvailableTranslations []string `json:"available_translations"`
|
||||
Genres []string `json:"genres"`
|
||||
AiredEpisodes int `json:"aired_episodes"`
|
||||
Character string `json:"character"`
|
||||
}
|
||||
|
||||
type Movie struct {
|
||||
Type string `json:"type"`
|
||||
Title string `json:"title"`
|
||||
Year int `json:"year"`
|
||||
Ids MovieIds `json:"ids"`
|
||||
Tagline string `json:"tagline"`
|
||||
Overview string `json:"overview"`
|
||||
Released string `json:"released"`
|
||||
Runtime int `json:"runtime"`
|
||||
Country string `json:"country"`
|
||||
Trailer string `json:"trailer"`
|
||||
Homepage string `json:"homepage"`
|
||||
Status string `json:"status"`
|
||||
Rating float64 `json:"rating"`
|
||||
Votes int `json:"votes"`
|
||||
CommentCount int `json:"comment_count"`
|
||||
Language string `json:"language"`
|
||||
AvailableTranslations []string `json:"available_translations"`
|
||||
Genres []string `json:"genres"`
|
||||
Certification string `json:"certification"`
|
||||
Character string `json:"character"`
|
||||
}
|
||||
35
media/trakt/trakt.go
Normal file
35
media/trakt/trakt.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package trakt
|
||||
|
||||
import (
|
||||
"github.com/l3uddz/nabarr/logger"
|
||||
"github.com/rs/zerolog"
|
||||
"go.uber.org/ratelimit"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
clientId string
|
||||
log zerolog.Logger
|
||||
rl ratelimit.Limiter
|
||||
|
||||
apiURL string
|
||||
apiTimeout time.Duration
|
||||
}
|
||||
|
||||
func New(cfg *Config) *Client {
|
||||
return &Client{
|
||||
clientId: cfg.ClientId,
|
||||
log: logger.New(cfg.Verbosity).With().Logger(),
|
||||
rl: ratelimit.New(1, ratelimit.WithoutSlack),
|
||||
|
||||
apiURL: "https://api.trakt.tv",
|
||||
apiTimeout: 30 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) getAuthHeaders() map[string]string {
|
||||
return map[string]string{
|
||||
"trakt-api-key": c.clientId,
|
||||
"trakt-api-version": "2",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user