initial code (#6)

* initial code commit
This commit is contained in:
l3uddz
2021-02-14 16:18:26 +00:00
committed by GitHub
parent 3f55336fbd
commit ce3807b819
53 changed files with 3694 additions and 0 deletions

7
media/trakt/config.go Normal file
View 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
View 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
View 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
View 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",
}
}