7
media/omdb/config.go
Normal file
7
media/omdb/config.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package omdb
|
||||
|
||||
type Config struct {
|
||||
ApiKey string `yaml:"api_key"`
|
||||
|
||||
Verbosity string `yaml:"verbosity,omitempty"`
|
||||
}
|
||||
72
media/omdb/media.go
Normal file
72
media/omdb/media.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package omdb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/l3uddz/nabarr/util"
|
||||
"github.com/lucperkins/rek"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrItemNotFound = errors.New("not found")
|
||||
)
|
||||
|
||||
func (c *Client) GetItem(imdbId string) (*Item, error) {
|
||||
// empty item when appropriate
|
||||
if c.apiKey == "" || imdbId == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// prepare request
|
||||
reqUrl, err := util.URLWithQuery(c.apiURL, url.Values{
|
||||
"apikey": []string{c.apiKey},
|
||||
"i": []string{imdbId}})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate lookup request url: %w", err)
|
||||
}
|
||||
|
||||
c.log.Trace().
|
||||
Str("url", reqUrl).
|
||||
Msg("Searching omdb")
|
||||
|
||||
// send request
|
||||
c.rl.Take()
|
||||
resp, err := rek.Get(reqUrl, rek.Timeout(c.apiTimeout))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request lookup: %w", err)
|
||||
}
|
||||
defer resp.Body().Close()
|
||||
|
||||
// validate response
|
||||
if resp.StatusCode() != 200 {
|
||||
return nil, fmt.Errorf("validate lookup response: %s", resp.Status())
|
||||
}
|
||||
|
||||
// decode response
|
||||
b := new(lookupResponse)
|
||||
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
||||
return nil, fmt.Errorf("decode lookup response: %w", err)
|
||||
}
|
||||
|
||||
if b.Title == "" {
|
||||
return nil, fmt.Errorf("item with imdbId: %v: %w", imdbId, ErrItemNotFound)
|
||||
}
|
||||
|
||||
// transform response
|
||||
rt := 0
|
||||
for _, rating := range b.Ratings {
|
||||
if strings.EqualFold(rating.Source, "Rotten Tomatoes") {
|
||||
rt = util.Atoi(strings.TrimSuffix(rating.Value, "%"), 0)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return &Item{
|
||||
Metascore: util.Atoi(b.Metascore, 0),
|
||||
RottenTomatoes: rt,
|
||||
ImdbRating: util.Atof64(b.ImdbRating, 0.0),
|
||||
}, nil
|
||||
}
|
||||
28
media/omdb/omdb.go
Normal file
28
media/omdb/omdb.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package omdb
|
||||
|
||||
import (
|
||||
"github.com/l3uddz/nabarr/logger"
|
||||
"github.com/rs/zerolog"
|
||||
"go.uber.org/ratelimit"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
apiKey string
|
||||
log zerolog.Logger
|
||||
rl ratelimit.Limiter
|
||||
|
||||
apiURL string
|
||||
apiTimeout time.Duration
|
||||
}
|
||||
|
||||
func New(cfg *Config) *Client {
|
||||
return &Client{
|
||||
apiKey: cfg.ApiKey,
|
||||
log: logger.New(cfg.Verbosity).With().Logger(),
|
||||
rl: ratelimit.New(1, ratelimit.WithoutSlack),
|
||||
|
||||
apiURL: "https://www.omdbapi.com",
|
||||
apiTimeout: 30 * time.Second,
|
||||
}
|
||||
}
|
||||
40
media/omdb/struct.go
Normal file
40
media/omdb/struct.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package omdb
|
||||
|
||||
type rating struct {
|
||||
Source string `json:"Source,omitempty"`
|
||||
Value string `json:"Value,omitempty"`
|
||||
}
|
||||
|
||||
type lookupResponse struct {
|
||||
Title string `json:"Title,omitempty"`
|
||||
Year string `json:"Year,omitempty"`
|
||||
Rated string `json:"Rated,omitempty"`
|
||||
Released string `json:"Released,omitempty"`
|
||||
Runtime string `json:"Runtime,omitempty"`
|
||||
Genre string `json:"Genre,omitempty"`
|
||||
Director string `json:"Director,omitempty"`
|
||||
Writer string `json:"Writer,omitempty"`
|
||||
Actors string `json:"Actors,omitempty"`
|
||||
Plot string `json:"Plot,omitempty"`
|
||||
Language string `json:"Language,omitempty"`
|
||||
Country string `json:"Country,omitempty"`
|
||||
Awards string `json:"Awards,omitempty"`
|
||||
Poster string `json:"Poster,omitempty"`
|
||||
Ratings []rating `json:"Ratings,omitempty"`
|
||||
Metascore string `json:"Metascore,omitempty"`
|
||||
ImdbRating string `json:"imdbRating,omitempty"`
|
||||
ImdbVotes string `json:"imdbVotes,omitempty"`
|
||||
ImdbID string `json:"imdbID,omitempty"`
|
||||
Type string `json:"Type,omitempty"`
|
||||
DVD string `json:"DVD,omitempty"`
|
||||
BoxOffice string `json:"BoxOffice,omitempty"`
|
||||
Production string `json:"Production,omitempty"`
|
||||
Website string `json:"Website,omitempty"`
|
||||
Response string `json:"Response,omitempty"`
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
Metascore int `json:"Metascore,omitempty"`
|
||||
RottenTomatoes int `json:"RottenTomatoes,omitempty"`
|
||||
ImdbRating float64 `json:"ImdbRating,omitempty"`
|
||||
}
|
||||
Reference in New Issue
Block a user