We now use the right log object with prefix and return an error on GetDetails only if the error is Fatal
241 lines
6.3 KiB
Go
241 lines
6.3 KiB
Go
package shows
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"git.quimbo.fr/odwrtw/canape/backend/models"
|
|
"git.quimbo.fr/odwrtw/canape/backend/web"
|
|
"github.com/odwrtw/errors"
|
|
"github.com/odwrtw/papi"
|
|
polochon "github.com/odwrtw/polochon/lib"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Show represents a show
|
|
type Show struct {
|
|
client *papi.Client
|
|
pShow *papi.Show
|
|
*polochon.Show
|
|
TrackedSeason *int `json:"tracked_season"`
|
|
TrackedEpisode *int `json:"tracked_episode"`
|
|
publicDir string
|
|
imgURLPrefix string
|
|
}
|
|
|
|
// MarshalJSON implements the Marshal interface
|
|
func (s *Show) MarshalJSON() ([]byte, error) {
|
|
type alias Show
|
|
// Create the structure that we want to marshal
|
|
showToMarshal := &struct {
|
|
*alias
|
|
Episodes []Episode `json:"episodes"`
|
|
BannerURL string `json:"banner_url"`
|
|
FanartURL string `json:"fanart_url"`
|
|
PosterURL string `json:"poster_url"`
|
|
}{
|
|
alias: (*alias)(s),
|
|
BannerURL: s.GetImageURL("banner"),
|
|
FanartURL: s.GetImageURL("fanart"),
|
|
PosterURL: s.GetImageURL("poster"),
|
|
}
|
|
|
|
// Create Episode obj from polochon.Episodes and add them to the object to
|
|
// marshal
|
|
for _, e := range s.Show.Episodes {
|
|
showToMarshal.Episodes = append(showToMarshal.Episodes, Episode{
|
|
ShowEpisode: e,
|
|
show: s,
|
|
})
|
|
}
|
|
return json.Marshal(showToMarshal)
|
|
}
|
|
|
|
// New returns a new Show with a polochon ShowConfig
|
|
func New(imdbID string, publicDir, imgURLPrefix string) *Show {
|
|
return &Show{
|
|
Show: &polochon.Show{
|
|
ImdbID: imdbID,
|
|
},
|
|
publicDir: publicDir,
|
|
imgURLPrefix: imgURLPrefix,
|
|
}
|
|
}
|
|
|
|
// NewWithClient returns a new Show with a polochon ShowConfig
|
|
func NewWithClient(show *polochon.Show, client *papi.Client, pShow *papi.Show, wShow *models.WishedShow, publicDir, imgURLPrefix string) *Show {
|
|
s := &Show{
|
|
Show: show,
|
|
client: client,
|
|
pShow: pShow,
|
|
publicDir: publicDir,
|
|
imgURLPrefix: imgURLPrefix,
|
|
}
|
|
if wShow != nil {
|
|
s.TrackedSeason = &wShow.Season
|
|
s.TrackedEpisode = &wShow.Episode
|
|
}
|
|
return s
|
|
}
|
|
|
|
// GetDetails retrieves details for the show with the given detailers
|
|
func (s *Show) GetDetails(env *web.Env, detailers []polochon.Detailer) error {
|
|
log := env.Log.WithFields(logrus.Fields{
|
|
"imdb_id": s.ImdbID,
|
|
"function": "shows.GetDetails",
|
|
})
|
|
var detailersName []string
|
|
for _, d := range detailers {
|
|
detailersName = append(detailersName, d.Name())
|
|
}
|
|
log.Debugf("getting details with %s", strings.Join(detailersName, ", "))
|
|
|
|
s.Detailers = detailers
|
|
|
|
// Get the details
|
|
err := polochon.GetDetails(s.Show, log)
|
|
if err != nil {
|
|
if errors.IsFatal(err) {
|
|
return err
|
|
}
|
|
}
|
|
|
|
log.Debugf("got details from detailers")
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetAndFetch retrieves details for the show with the given
|
|
// detailers 'before'
|
|
// If found, return
|
|
// If not, retrives details with the detailers 'after' and update them in
|
|
// database
|
|
func (s *Show) GetAndFetch(env *web.Env, before []polochon.Detailer, after []polochon.Detailer) error {
|
|
log := env.Log.WithFields(logrus.Fields{
|
|
"imdb_id": s.ImdbID,
|
|
"function": "shows.GetAndFetch",
|
|
})
|
|
|
|
// Try to get details with the first batch of Detailers
|
|
err := s.GetDetails(env, before)
|
|
if err == nil {
|
|
log.Debug("show found in first try")
|
|
return nil
|
|
}
|
|
log.Debugf("show not found in database: %s", err)
|
|
|
|
// If not found, try the second batch and upsert
|
|
return s.Refresh(env, after)
|
|
}
|
|
|
|
// Refresh retrieves details for the show with the given detailers
|
|
// and update them in database
|
|
func (s *Show) Refresh(env *web.Env, detailers []polochon.Detailer) error {
|
|
// Refresh
|
|
err := s.GetDetails(env, detailers)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Download show images
|
|
s.downloadImages(env)
|
|
|
|
env.Log.Debug("images downloaded")
|
|
|
|
// If found, update in database
|
|
return models.UpsertShow(env.Database, s.Show)
|
|
}
|
|
|
|
// GetImageURL returns the image URL or the default image if the poster is not yet downloaded
|
|
func (s *Show) GetImageURL(imgType string) string {
|
|
// Check if the show image exists
|
|
if _, err := os.Stat(s.imgFile(imgType)); os.IsNotExist(err) {
|
|
return ""
|
|
}
|
|
return s.imgURLPrefix + s.imgURL(imgType)
|
|
}
|
|
|
|
// downloadImages will download the show images
|
|
func (s *Show) downloadImages(env *web.Env) {
|
|
// Download the banner
|
|
err := web.Download(s.Show.Banner, s.imgFile("banner"), false)
|
|
if err != nil {
|
|
env.Log.Errorf("failed to dowload banner: %s", err)
|
|
}
|
|
err = web.Download(s.Show.Fanart, s.imgFile("fanart"), false)
|
|
if err != nil {
|
|
env.Log.Errorf("failed to dowload fanart: %s", err)
|
|
}
|
|
err = web.Download(s.Show.Poster, s.imgFile("poster"), true)
|
|
if err != nil {
|
|
env.Log.Errorf("failed to dowload poster: %s", err)
|
|
}
|
|
|
|
// Download episode thumbs
|
|
for _, e := range s.Episodes {
|
|
if e.Thumb == "" {
|
|
continue
|
|
}
|
|
|
|
err = web.Download(e.Thumb, s.imgFile(fmt.Sprintf("%d-%d", e.Season, e.Episode)), false)
|
|
if err != nil {
|
|
env.Log.Errorf("failed to dowload the thumb for season %d episode %d: %s", e.Season, e.Episode, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// imgURL returns the default image url
|
|
func (s *Show) imgURL(imgType string) string {
|
|
return fmt.Sprintf("shows/%s-%s.jpg", s.ImdbID, imgType)
|
|
}
|
|
|
|
// imgFile returns the image location on disk
|
|
func (s *Show) imgFile(imgType string) string {
|
|
return filepath.Join(s.publicDir, "img", s.imgURL(imgType))
|
|
}
|
|
|
|
// getPolochonShows returns all the Shows from the polochon of a user
|
|
func getPolochonShows(env *web.Env, user *models.User) ([]*Show, error) {
|
|
shows := []*Show{}
|
|
|
|
client, err := user.NewPapiClient(env.Database)
|
|
if err != nil {
|
|
return shows, err
|
|
}
|
|
|
|
// Get the polochon's shows
|
|
pshows, err := client.GetShows()
|
|
if err != nil {
|
|
return shows, err
|
|
}
|
|
|
|
wShows, err := models.GetShowWishlist(env.Database, user.ID)
|
|
if err != nil {
|
|
return shows, err
|
|
}
|
|
|
|
// Create Shows objects from the shows retrieved
|
|
for _, pShow := range pshows.List() {
|
|
wShow, _ := wShows.IsShowInWishlist(pShow.ImdbID)
|
|
show := NewWithClient(&polochon.Show{ImdbID: pShow.ImdbID}, client, pShow, wShow, env.Config.PublicDir, env.Config.ImgURLPrefix)
|
|
shows = append(shows, show)
|
|
}
|
|
return shows, nil
|
|
}
|
|
|
|
// LastSeasonEpisodes will return the episodes of the last season of the show
|
|
func (s *Show) LastSeasonEpisodes() []*polochon.ShowEpisode {
|
|
episodes := make(map[int][]*polochon.ShowEpisode)
|
|
lastSeason := 0
|
|
for _, e := range s.Episodes {
|
|
if lastSeason < e.Season {
|
|
lastSeason = e.Season
|
|
}
|
|
episodes[e.Season] = append(episodes[e.Season], e)
|
|
}
|
|
return episodes[lastSeason]
|
|
}
|