package movies import ( "database/sql" "encoding/json" "fmt" "os" "path/filepath" "github.com/Sirupsen/logrus" "github.com/odwrtw/papi" "github.com/odwrtw/polochon/lib" "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/backend" "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/users" "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web" ) // Movie represents a movie type Movie struct { *polochon.Movie client *papi.Client pMovie *papi.Movie publicDir string Wishlisted bool `json:"wishlisted"` } // MarshalJSON implements the Marshal interface func (m *Movie) MarshalJSON() ([]byte, error) { type Alias Movie var downloadURL string // If the episode is present, fill the downloadURL if m.pMovie != nil { downloadURL, _ = m.client.DownloadURL(m.pMovie) } // Marshal the movie with its polochon_url movieToMarshal := &struct { *Alias PolochonURL string `json:"polochon_url"` PosterURL string `json:"poster_url"` }{ Alias: (*Alias)(m), PolochonURL: downloadURL, PosterURL: m.PosterURL(), } 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 string) *Movie { return &Movie{ client: client, pMovie: pMovie, publicDir: publicDir, 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 := m.Movie.GetDetails(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 { // Refresh err := m.GetDetails(env, detailers) if err != nil { return err } // Download poster err = web.Download(m.Thumb, m.imgFile()) if err != nil { return err } env.Log.Debug("poster downloaded") // 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 := m.Movie.GetTorrents(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("img/movies/%s.jpg", m.ImdbID) } // imgFile returns the image location on disk func (m *Movie) imgFile() string { return filepath.Join(m.publicDir, 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 "img/noimage.png" } return 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, ) movies = append(movies, movie) } return movies, nil }