278 lines
7.1 KiB
Go
278 lines
7.1 KiB
Go
package movies
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"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"
|
|
polochon "github.com/odwrtw/polochon/lib"
|
|
"github.com/odwrtw/polochon/lib/papi"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Movie represents a movie
|
|
type Movie struct {
|
|
*polochon.Movie
|
|
client *papi.Client
|
|
pMovie *papi.Movie
|
|
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),
|
|
// TODO: remove this field to use m.Thumb
|
|
PosterURL: m.Thumb,
|
|
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 = string(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) *Movie {
|
|
return &Movie{
|
|
client: client,
|
|
pMovie: pMovie,
|
|
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, 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, 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 {
|
|
t.ImdbID = m.ImdbID
|
|
err = models.UpsertMovieTorrent(env.Database, t)
|
|
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(models.PublicDir, "img", 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),
|
|
)
|
|
movies = append(movies, movie)
|
|
}
|
|
|
|
return movies, nil
|
|
}
|