media: add support for legacy tvdb api (#16)
This commit is contained in:
@@ -5,29 +5,28 @@ import (
|
|||||||
"github.com/l3uddz/nabarr/logger"
|
"github.com/l3uddz/nabarr/logger"
|
||||||
"github.com/l3uddz/nabarr/media/omdb"
|
"github.com/l3uddz/nabarr/media/omdb"
|
||||||
"github.com/l3uddz/nabarr/media/trakt"
|
"github.com/l3uddz/nabarr/media/trakt"
|
||||||
|
"github.com/l3uddz/nabarr/media/tvdb"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
trakt *trakt.Client
|
trakt *trakt.Client
|
||||||
omdb *omdb.Client
|
omdb *omdb.Client
|
||||||
|
tvdb *tvdb.Client
|
||||||
|
|
||||||
log zerolog.Logger
|
log zerolog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *Config) (*Client, error) {
|
func New(cfg *Config) (*Client, error) {
|
||||||
// trakt
|
// validate trakt configured (it is mandatory)
|
||||||
if cfg.Trakt.ClientId == "" {
|
if cfg.Trakt.ClientId == "" {
|
||||||
return nil, fmt.Errorf("trakt: no client_id specified")
|
return nil, fmt.Errorf("trakt: no client_id specified")
|
||||||
}
|
}
|
||||||
t := trakt.New(&cfg.Trakt)
|
|
||||||
|
|
||||||
// omdb
|
|
||||||
o := omdb.New(&cfg.Omdb)
|
|
||||||
|
|
||||||
return &Client{
|
return &Client{
|
||||||
trakt: t,
|
trakt: trakt.New(&cfg.Trakt),
|
||||||
omdb: o,
|
omdb: omdb.New(&cfg.Omdb),
|
||||||
|
tvdb: tvdb.New(&cfg.Tvdb),
|
||||||
|
|
||||||
log: logger.New(cfg.Verbosity).With().Logger(),
|
log: logger.New(cfg.Verbosity).With().Logger(),
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ package media
|
|||||||
import (
|
import (
|
||||||
"github.com/l3uddz/nabarr/media/omdb"
|
"github.com/l3uddz/nabarr/media/omdb"
|
||||||
"github.com/l3uddz/nabarr/media/trakt"
|
"github.com/l3uddz/nabarr/media/trakt"
|
||||||
|
"github.com/l3uddz/nabarr/media/tvdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Trakt trakt.Config `yaml:"trakt"`
|
Trakt trakt.Config `yaml:"trakt"`
|
||||||
Omdb omdb.Config `yaml:"omdb"`
|
Omdb omdb.Config `yaml:"omdb"`
|
||||||
|
Tvdb tvdb.Config `yaml:"tvdb"`
|
||||||
|
|
||||||
Verbosity string `yaml:"verbosity,omitempty"`
|
Verbosity string `yaml:"verbosity,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,5 +49,15 @@ func (c *Client) GetShowInfo(item *FeedItem) (*Item, error) {
|
|||||||
mi.Omdb = *oi
|
mi.Omdb = *oi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tvdb
|
||||||
|
if ti, err := c.tvdb.GetItem(strconv.Itoa(t.Ids.Tvdb)); err != nil {
|
||||||
|
c.log.Debug().
|
||||||
|
Err(err).
|
||||||
|
Int("tvdb_id", t.Ids.Tvdb).
|
||||||
|
Msg("Item was not found on tvdb")
|
||||||
|
} else if ti != nil {
|
||||||
|
mi.Tvdb = *ti
|
||||||
|
}
|
||||||
|
|
||||||
return mi, nil
|
return mi, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package media
|
|||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"github.com/l3uddz/nabarr/media/omdb"
|
"github.com/l3uddz/nabarr/media/omdb"
|
||||||
|
"github.com/l3uddz/nabarr/media/tvdb"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -29,6 +30,7 @@ type Item struct {
|
|||||||
|
|
||||||
// additional media provider data
|
// additional media provider data
|
||||||
Omdb omdb.Item `json:"Omdb,omitempty"`
|
Omdb omdb.Item `json:"Omdb,omitempty"`
|
||||||
|
Tvdb tvdb.Item `json:"Tvdb,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Rss struct {
|
type Rss struct {
|
||||||
|
|||||||
7
media/tvdb/config.go
Normal file
7
media/tvdb/config.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package tvdb
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
ApiKey string `yaml:"api_key"`
|
||||||
|
|
||||||
|
Verbosity string `yaml:"verbosity,omitempty"`
|
||||||
|
}
|
||||||
58
media/tvdb/media.go
Normal file
58
media/tvdb/media.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package tvdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/l3uddz/nabarr/util"
|
||||||
|
"github.com/lucperkins/rek"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrItemNotFound = errors.New("not found")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Client) GetItem(tvdbId string) (*Item, error) {
|
||||||
|
// empty item when appropriate
|
||||||
|
if c.apiKey == "" || tvdbId == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare request
|
||||||
|
reqUrl := util.JoinURL(c.apiURL, "series", tvdbId)
|
||||||
|
c.log.Trace().
|
||||||
|
Str("url", reqUrl).
|
||||||
|
Msg("Searching tvdb")
|
||||||
|
|
||||||
|
// send request
|
||||||
|
c.rl.Take()
|
||||||
|
resp, err := rek.Get(reqUrl, rek.Headers(c.apiHeaders), 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.Data.SeriesName == "" {
|
||||||
|
return nil, fmt.Errorf("item with imdbId: %v: %w", tvdbId, ErrItemNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Item{
|
||||||
|
Runtime: util.Atoi(b.Data.Runtime, 0),
|
||||||
|
Language: b.Data.Language,
|
||||||
|
Genre: b.Data.Genre,
|
||||||
|
AirsDayOfWeek: b.Data.AirsDayOfWeek,
|
||||||
|
SiteRating: b.Data.SiteRating,
|
||||||
|
SiteRatingCount: b.Data.SiteRatingCount,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
42
media/tvdb/struct.go
Normal file
42
media/tvdb/struct.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package tvdb
|
||||||
|
|
||||||
|
type lookupResponse struct {
|
||||||
|
Data struct {
|
||||||
|
Id int `json:"id,omitempty"`
|
||||||
|
SeriesId string `json:"seriesId,omitempty"`
|
||||||
|
SeriesName string `json:"seriesName,omitempty"`
|
||||||
|
Aliases []interface{} `json:"aliases,omitempty"`
|
||||||
|
Season string `json:"season,omitempty"`
|
||||||
|
Poster string `json:"poster,omitempty"`
|
||||||
|
Banner string `json:"banner,omitempty"`
|
||||||
|
Fanart string `json:"fanart,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
FirstAired string `json:"firstAired,omitempty"`
|
||||||
|
Network string `json:"network,omitempty"`
|
||||||
|
NetworkId string `json:"networkId,omitempty"`
|
||||||
|
Runtime string `json:"runtime,omitempty"`
|
||||||
|
Language string `json:"language,omitempty"`
|
||||||
|
Genre []string `json:"genre,omitempty"`
|
||||||
|
Overview string `json:"overview,omitempty"`
|
||||||
|
LastUpdated int `json:"lastUpdated,omitempty"`
|
||||||
|
AirsDayOfWeek string `json:"airsDayOfWeek,omitempty"`
|
||||||
|
AirsTime string `json:"airsTime,omitempty"`
|
||||||
|
Rating interface{} `json:"rating,omitempty"`
|
||||||
|
ImdbId string `json:"imdbId,omitempty"`
|
||||||
|
Zap2ItId string `json:"zap2itId,omitempty"`
|
||||||
|
Added string `json:"added,omitempty"`
|
||||||
|
AddedBy int `json:"addedBy,omitempty"`
|
||||||
|
SiteRating float64 `json:"siteRating,omitempty"`
|
||||||
|
SiteRatingCount int `json:"siteRatingCount,omitempty"`
|
||||||
|
Slug string `json:"slug,omitempty"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Item struct {
|
||||||
|
Runtime int `json:"Runtime,omitempty"`
|
||||||
|
Language string `json:"Language,omitempty"`
|
||||||
|
Genre []string `json:"Genre,omitempty"`
|
||||||
|
AirsDayOfWeek string `json:"AirsDayOfWeek,omitempty"`
|
||||||
|
SiteRating float64 `json:"SiteRating,omitempty"`
|
||||||
|
SiteRatingCount int `json:"SiteRatingCount,omitempty"`
|
||||||
|
}
|
||||||
33
media/tvdb/tvdb.go
Normal file
33
media/tvdb/tvdb.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package tvdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"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
|
||||||
|
apiHeaders map[string]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://api.thetvdb.com",
|
||||||
|
apiHeaders: map[string]string{
|
||||||
|
"Authorization": fmt.Sprintf("Bearer %s", cfg.ApiKey),
|
||||||
|
},
|
||||||
|
apiTimeout: 30 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user