We now use the right log object with prefix and return an error on GetDetails only if the error is Fatal
292 lines
7.5 KiB
Go
292 lines
7.5 KiB
Go
package movies
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"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"
|
|
"github.com/odwrtw/papi"
|
|
polochon "github.com/odwrtw/polochon/lib"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Movie represents a movie
|
|
type Movie struct {
|
|
*polochon.Movie
|
|
client *papi.Client
|
|
pMovie *papi.Movie
|
|
publicDir string
|
|
imgURLPrefix string
|
|
Wishlisted bool `json:"wishlisted"`
|
|
}
|
|
|
|
// MarshalJSON implements the Marshal interface
|
|
func (m *Movie) MarshalJSON() ([]byte, error) {
|
|
type Alias Movie
|
|
|
|
// Marshal the movie with its polochon_url
|
|
movieToMarshal := &struct {
|
|
*Alias
|
|
PolochonURL string `json:"polochon_url"`
|
|
PosterURL string `json:"poster_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"`
|
|
}{
|
|
Alias: (*Alias)(m),
|
|
PosterURL: m.PosterURL(),
|
|
Subtitles: []subtitles.Subtitle{},
|
|
}
|
|
|
|
if m.pMovie != nil {
|
|
// Get the DownloadURL
|
|
movieToMarshal.PolochonURL, _ = m.client.DownloadURL(m.pMovie)
|
|
|
|
// Get the metadata
|
|
movieToMarshal.DateAdded = m.pMovie.DateAdded
|
|
movieToMarshal.Quality = m.pMovie.Quality
|
|
movieToMarshal.AudioCodec = m.pMovie.AudioCodec
|
|
movieToMarshal.VideoCodec = m.pMovie.VideoCodec
|
|
movieToMarshal.Container = m.pMovie.Container
|
|
|
|
// Append the Subtitles
|
|
for _, l := range m.pMovie.Subtitles {
|
|
subtitleURL, _ := m.client.SubtitleURL(m.pMovie, l)
|
|
movieToMarshal.Subtitles = append(movieToMarshal.Subtitles, subtitles.Subtitle{
|
|
Language: l,
|
|
URL: subtitleURL,
|
|
VVTFile: fmt.Sprintf("/movies/%s/subtitles/%s", m.ImdbID, l),
|
|
})
|
|
}
|
|
}
|
|
|
|
return json.Marshal(movieToMarshal)
|
|
}
|
|
|
|
// New returns a new Movie with all the needed infos
|
|
func New(imdbID string, client *papi.Client, pMovie *papi.Movie, isWishlisted bool, publicDir, imgURLPrefix string) *Movie {
|
|
return &Movie{
|
|
client: client,
|
|
pMovie: pMovie,
|
|
publicDir: publicDir,
|
|
imgURLPrefix: imgURLPrefix,
|
|
Wishlisted: isWishlisted,
|
|
Movie: &polochon.Movie{
|
|
ImdbID: imdbID,
|
|
},
|
|
}
|
|
}
|
|
|
|
// GetDetails retrieves details for the movie with the given detailers
|
|
func (m *Movie) GetDetails(env *web.Env, detailers []polochon.Detailer) error {
|
|
log := env.Log.WithFields(logrus.Fields{
|
|
"imdb_id": m.ImdbID,
|
|
"function": "movies.GetDetails",
|
|
})
|
|
log.Debugf("getting details")
|
|
|
|
m.Detailers = detailers
|
|
|
|
// GetDetail
|
|
err := polochon.GetDetails(m.Movie, log)
|
|
if err != nil {
|
|
if errors.IsFatal(err) {
|
|
return err
|
|
}
|
|
}
|
|
|
|
log.Debug("got details from detailers")
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetAndFetch retrieves details for the movie with the given
|
|
// detailers 'before'
|
|
// If found, return
|
|
// If not, retrives details with the detailers 'after' and update them in
|
|
// database
|
|
func (m *Movie) GetAndFetch(env *web.Env, before []polochon.Detailer, after []polochon.Detailer) error {
|
|
log := env.Log.WithFields(logrus.Fields{
|
|
"imdb_id": m.ImdbID,
|
|
"function": "movies.GetAndFetch",
|
|
})
|
|
|
|
// Try to get details with the first batch of Detailers
|
|
err := m.GetDetails(env, before)
|
|
if err == nil {
|
|
log.Debug("movie found in first try")
|
|
return nil
|
|
}
|
|
log.Debugf("movie not found in database: %s", err)
|
|
|
|
// If not found, try the second batch and upsert
|
|
return m.Refresh(env, after)
|
|
}
|
|
|
|
// Refresh retrieves details for the movie with the given detailers
|
|
// and update them in database
|
|
func (m *Movie) Refresh(env *web.Env, detailers []polochon.Detailer) error {
|
|
log := env.Log.WithFields(logrus.Fields{
|
|
"imdb_id": m.ImdbID,
|
|
"function": "movies.Refresh",
|
|
})
|
|
|
|
// Refresh
|
|
err := m.GetDetails(env, detailers)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Download poster
|
|
err = web.Download(m.Thumb, m.imgFile(), true)
|
|
if err != nil {
|
|
log.Errorf("got error trying to download the poster %q", err)
|
|
}
|
|
|
|
// If found, update in database
|
|
return models.UpsertMovie(env.Database, m.Movie)
|
|
}
|
|
|
|
// GetTorrents retrieves torrents for the movie with the given torrenters
|
|
func (m *Movie) GetTorrents(env *web.Env, torrenters []polochon.Torrenter) error {
|
|
log := env.Log.WithFields(logrus.Fields{
|
|
"imdb_id": m.ImdbID,
|
|
"function": "movies.GetTorrents",
|
|
})
|
|
log.Debugf("getting torrents")
|
|
|
|
m.Torrenters = torrenters
|
|
|
|
err := polochon.GetTorrents(m.Movie, env.Log)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Debugf("got %d torrents from torrenters", len(m.Movie.Torrents))
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetAndFetchTorrents retrieves torrents for the movie with the given
|
|
// torrenters 'before'
|
|
// If found, return
|
|
// If not, retrives torrents with the torrenters 'after' and update them in
|
|
// database
|
|
func (m *Movie) GetAndFetchTorrents(env *web.Env, before []polochon.Torrenter, after []polochon.Torrenter) error {
|
|
log := env.Log.WithFields(logrus.Fields{
|
|
"imdb_id": m.ImdbID,
|
|
"function": "movies.GetAndFetchTorrents",
|
|
})
|
|
|
|
// Try to get torrents with the first batch of Torrenters
|
|
err := m.GetTorrents(env, before)
|
|
switch err {
|
|
case nil:
|
|
log.Debug("movie torrent's found in first try")
|
|
return nil
|
|
case sql.ErrNoRows:
|
|
log.Debug("movie's torrents not found in database")
|
|
default:
|
|
// Unexpected error
|
|
return err
|
|
}
|
|
|
|
// If not found, try the second batch and upsert
|
|
return m.RefreshTorrents(env, after)
|
|
}
|
|
|
|
// RefreshTorrents retrieves torrents for the movie with the given torrenters
|
|
// and update them in database
|
|
func (m *Movie) RefreshTorrents(env *web.Env, torrenters []polochon.Torrenter) error {
|
|
log := env.Log.WithFields(logrus.Fields{
|
|
"imdb_id": m.ImdbID,
|
|
"function": "movies.RefreshTorrents",
|
|
})
|
|
|
|
// Get torrents with de torrenters
|
|
err := m.GetTorrents(env, torrenters)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Debugf("got %d torrents from torrenters", len(m.Movie.Torrents))
|
|
|
|
// Update them in database
|
|
for _, t := range m.Movie.Torrents {
|
|
err = models.UpsertMovieTorrent(env.Database, &t, m.ImdbID)
|
|
if err != nil {
|
|
log.Error("error while adding torrent", err)
|
|
continue
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// imgURL returns the default image url
|
|
func (m *Movie) imgURL() string {
|
|
return fmt.Sprintf("movies/%s.jpg", m.ImdbID)
|
|
}
|
|
|
|
// imgFile returns the image location on disk
|
|
func (m *Movie) imgFile() string {
|
|
return filepath.Join(m.publicDir, "img", m.imgURL())
|
|
}
|
|
|
|
// PosterURL returns the image URL or the default image if the poster is not yet downloaded
|
|
func (m *Movie) PosterURL() string {
|
|
// Check if the movie image exists
|
|
if _, err := os.Stat(m.imgFile()); os.IsNotExist(err) {
|
|
return ""
|
|
}
|
|
return m.imgURLPrefix + m.imgURL()
|
|
}
|
|
|
|
// getPolochonMovies returns an array of the user's polochon movies
|
|
func getPolochonMovies(user *models.User, env *web.Env) ([]*Movie, error) {
|
|
movies := []*Movie{}
|
|
|
|
// Create a papi client
|
|
client, err := user.NewPapiClient(env.Database)
|
|
if err != nil {
|
|
return movies, err
|
|
}
|
|
|
|
// Retrieve the user's polochon movies
|
|
pmovies, err := client.GetMovies()
|
|
if err != nil {
|
|
return movies, err
|
|
}
|
|
|
|
// Get the user's wishlisted movies
|
|
moviesWishlist, err := models.GetMovieWishlist(env.Database, user.ID)
|
|
if err != nil {
|
|
return movies, err
|
|
}
|
|
|
|
// Create Movies objects from the movies retrieved
|
|
for _, pmovie := range pmovies.List() {
|
|
movie := New(
|
|
pmovie.ImdbID,
|
|
client,
|
|
pmovie,
|
|
moviesWishlist.IsMovieInWishlist(pmovie.ImdbID),
|
|
env.Config.PublicDir,
|
|
env.Config.ImgURLPrefix,
|
|
)
|
|
movies = append(movies, movie)
|
|
}
|
|
|
|
return movies, nil
|
|
}
|