package shows import ( "encoding/json" "fmt" "time" "git.quimbo.fr/odwrtw/canape/backend/models" "git.quimbo.fr/odwrtw/canape/backend/subtitles" "git.quimbo.fr/odwrtw/canape/backend/web" "github.com/odwrtw/errors" polochon "github.com/odwrtw/polochon/lib" "github.com/odwrtw/polochon/lib/papi" "github.com/sirupsen/logrus" ) // Episode represents an episode type Episode struct { show *Show *polochon.ShowEpisode } // MarshalJSON implements the Marshal interface func (e *Episode) MarshalJSON() ([]byte, error) { type alias Episode var downloadURL string var subs []subtitles.Subtitle var dateAdded time.Time var quality string var audioCodec string var videoCodec string var container string // If the episode is present, fill the downloadURL if e.show.pShow != nil { pEpisode := e.show.pShow.GetEpisode(e.Season, e.Episode) if pEpisode != nil { // Get the DownloadURL downloadURL, _ = e.show.client.DownloadURL( &papi.Episode{ ShowEpisode: &polochon.ShowEpisode{ ShowImdbID: e.ShowImdbID, Episode: e.Episode, Season: e.Season, }, }, ) dateAdded = pEpisode.DateAdded quality = string(pEpisode.Quality) audioCodec = pEpisode.AudioCodec videoCodec = pEpisode.VideoCodec container = pEpisode.Container // Append the Subtitles for _, l := range pEpisode.Subtitles { subtitleURL, _ := e.show.client.SubtitleURL(pEpisode, l) subs = append(subs, subtitles.Subtitle{ Language: l, URL: subtitleURL, VVTFile: fmt.Sprintf("/shows/%s/seasons/%d/episodes/%d/subtitles/%s", e.ShowImdbID, e.Season, e.Episode, l), }) } } } // Marshal the episode with its polochon_url episodeToMarshal := &struct { *alias PolochonURL string `json:"polochon_url"` Subtitles []subtitles.Subtitle `json:"subtitles"` DateAdded time.Time `json:"date_added"` Quality string `json:"quality"` AudioCodec string `json:"audio_codec"` VideoCodec string `json:"video_codec"` Container string `json:"container"` Thumb string `json:"thumb"` }{ alias: (*alias)(e), PolochonURL: downloadURL, Subtitles: subs, DateAdded: dateAdded, Quality: quality, AudioCodec: audioCodec, VideoCodec: videoCodec, Container: container, Thumb: e.Thumb, } return json.Marshal(episodeToMarshal) } // NewEpisode returns an Episode func NewEpisode(show *Show, season, episode int) *Episode { return &Episode{ show: show, ShowEpisode: &polochon.ShowEpisode{ ShowImdbID: show.ImdbID, Season: season, Episode: episode, }, } } // GetAndFetchTorrents retrieves torrents for the episode with the given // torrenters 'before' // If found, return // If not, retrives torrents with the torrenters 'after' and update them in // database func (e *Episode) GetAndFetchTorrents(env *web.Env, before []polochon.Torrenter, after []polochon.Torrenter) error { log := env.Log.WithFields(logrus.Fields{ "imdb_id": e.ShowImdbID, "season": e.Season, "episode": e.Episode, "function": "episodes.GetAndFetchTorrents", }) // Try to get details with the first batch of Detailers err := e.GetTorrents(env, before) if err == nil { log.Debug("episode torrents found in first try") return nil } log.Debugf("episode torrent not found in database: %s", err) // If not found, try the second batch and upsert return e.RefreshTorrents(env, after) } // GetTorrents retrieves torrents for the episode with the given torrenters func (e *Episode) GetTorrents(env *web.Env, torrenters []polochon.Torrenter) error { return GetTorrents(env, e.ShowEpisode, torrenters) } // GetTorrents retrieves torrents for the episode with the given torrenters func GetTorrents(env *web.Env, showEpisode *polochon.ShowEpisode, torrenters []polochon.Torrenter) error { log := env.Log.WithFields(logrus.Fields{ "imdb_id": showEpisode.ShowImdbID, "season": showEpisode.Season, "episode": showEpisode.Episode, "function": "episodes.GetTorrents", }) log.Debugf("getting torrents") showEpisode.Torrenters = torrenters err := polochon.GetTorrents(showEpisode, env.Log) if err != nil { return err } log.Debugf("got %d torrents from torrenters", len(showEpisode.Torrents)) return nil } // RefreshTorrents refresh the episode torrents func (e *Episode) RefreshTorrents(env *web.Env, torrenters []polochon.Torrenter) error { return RefreshTorrents(env, e.ShowEpisode, torrenters) } // RefreshTorrents refresh the episode torrents func RefreshTorrents(env *web.Env, showEpisode *polochon.ShowEpisode, torrenters []polochon.Torrenter) error { log := env.Log.WithFields(logrus.Fields{ "imdb_id": showEpisode.ShowImdbID, "season": showEpisode.Season, "episode": showEpisode.Episode, "function": "episodes.RefreshTorrents", }) log.Debugf("refreshing torrents") // Refresh err := GetTorrents(env, showEpisode, torrenters) if err != nil { return err } // Upsert all the torrents we got for _, t := range showEpisode.Torrents { t.ImdbID = showEpisode.ShowImdbID t.Season = showEpisode.Season t.Episode = showEpisode.Episode err = models.UpsertEpisodeTorrent(env.Database, t) if err != nil { log.Errorf("error while adding torrent : %s", err) continue } } return nil } // Refresh retrieves details for the episode with the given detailers // and update them in database func (e *Episode) Refresh(env *web.Env, detailers []polochon.Detailer) error { // Refresh err := e.GetEpisodeDetails(env, detailers) if err != nil { return err } return models.UpsertEpisode(env.Database, e.ShowEpisode) } // GetEpisodeDetails retrieves details for the episode with the given detailers func (e *Episode) GetEpisodeDetails(env *web.Env, detailers []polochon.Detailer) error { log := env.Log.WithFields(logrus.Fields{ "imdb_id": e.ShowImdbID, "function": "episodes.GetDetails", }) log.Debugf("getting details") e.ShowEpisode.Detailers = detailers // Get the details err := polochon.GetDetails(e.ShowEpisode, log) if err != nil { if errors.IsFatal(err) { return err } } log.Debug("got details from detailers") return nil }