Add method to fetch ratings from imdb every day Create a new table and a new view to fetch directly the movies and shows with their imdb ratings
281 lines
7.0 KiB
Go
281 lines
7.0 KiB
Go
package movies
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"git.quimbo.fr/odwrtw/canape/backend/backend"
|
|
"git.quimbo.fr/odwrtw/canape/backend/subtitles"
|
|
"git.quimbo.fr/odwrtw/canape/backend/users"
|
|
"git.quimbo.fr/odwrtw/canape/backend/web"
|
|
"github.com/odwrtw/papi"
|
|
"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
|
|
|
|
var downloadURL string
|
|
var subs []subtitles.Subtitle
|
|
// If the episode is present, fill the downloadURL
|
|
if m.pMovie != nil {
|
|
// Get the DownloadURL
|
|
downloadURL, _ = m.client.DownloadURL(m.pMovie)
|
|
// Append the Subtitles
|
|
for _, l := range m.pMovie.Subtitles {
|
|
subtitleURL, _ := m.client.SubtitleURL(m.pMovie, l)
|
|
subs = append(subs, subtitles.Subtitle{
|
|
Language: l,
|
|
URL: subtitleURL,
|
|
VVTFile: fmt.Sprintf("/movies/%s/subtitles/%s", m.ImdbID, l),
|
|
})
|
|
}
|
|
}
|
|
|
|
// 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"`
|
|
}{
|
|
Alias: (*Alias)(m),
|
|
PolochonURL: downloadURL,
|
|
PosterURL: m.PosterURL(),
|
|
Subtitles: subs,
|
|
}
|
|
|
|
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, env.Log)
|
|
if err != nil {
|
|
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())
|
|
if err != nil {
|
|
log.Errorf("got error trying to download the poster %q", err)
|
|
}
|
|
|
|
// If found, update in database
|
|
return backend.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 = backend.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) {
|
|
// TODO image in the config ?
|
|
return m.imgURLPrefix + "noimage.png"
|
|
}
|
|
return m.imgURLPrefix + m.imgURL()
|
|
}
|
|
|
|
// getPolochonMovies returns an array of the user's polochon movies
|
|
func getPolochonMovies(user *users.User, env *web.Env) ([]*Movie, error) {
|
|
movies := []*Movie{}
|
|
|
|
// Create a papi client
|
|
client, err := user.NewPapiClient()
|
|
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 := backend.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
|
|
}
|