package models import ( "database/sql" "fmt" "time" "github.com/jmoiron/sqlx" "github.com/lib/pq" polochon "github.com/odwrtw/polochon/lib" ) const ( upsertMovieQuery = ` INSERT INTO movies (imdb_id, title, rating, votes, plot, tmdb_id, year, genres, original_title, runtime, sort_title, tagline) VALUES (:imdb_id, :title, :rating, :votes, :plot, :tmdb_id, :year, :genres, :original_title, :runtime, :sort_title, :tagline) ON CONFLICT (imdb_id) DO UPDATE SET imdb_id=:imdb_id, title=:title, rating=:rating, votes=:votes, plot=:plot, tmdb_id=:tmdb_id, year=:year, genres=:genres, original_title=:original_title, runtime=:runtime, sort_title=:sort_title, tagline=:tagline RETURNING id;` getMovieQueryByImdbID = ` SELECT * FROM movies_with_rating WHERE imdb_id=$1;` ) // movieDB represents the Movie in the DB type movieDB struct { ID string `db:"id"` ImdbID string `db:"imdb_id"` TmdbID int `db:"tmdb_id"` Title string `db:"title"` OriginalTitle string `db:"original_title"` SortTitle string `db:"sort_title"` Rating float32 `db:"rating"` Votes int `db:"votes"` Plot string `db:"plot"` Year int `db:"year"` Runtime int `db:"runtime"` Tagline string `db:"tagline"` Genres pq.StringArray `db:"genres"` Created time.Time `db:"created_at"` Updated time.Time `db:"updated_at"` } func getMovieDB(db *sqlx.DB, movie *polochon.Movie) (*movieDB, error) { var mDB movieDB err := db.QueryRowx(getMovieQueryByImdbID, movie.ImdbID).StructScan(&mDB) if err != nil { return &mDB, err } return &mDB, nil } // GetMovie fills show details of a polochon.Movie func GetMovie(db *sqlx.DB, pMovie *polochon.Movie) error { if pMovie.ImdbID == "" { return fmt.Errorf("can't get movie details, you have to specify an ImdbID") } // Get the movie from the DB movie, err := getMovieDB(db, pMovie) if err != nil { return err } // Fills the polochon.Movie from the movieDB FillMovieFromDB(movie, pMovie) return nil } // FillMovieFromDB fills a Movie from a movieDB extracted from the DB func FillMovieFromDB(mDB *movieDB, pMovie *polochon.Movie) { pMovie.ImdbID = mDB.ImdbID pMovie.Title = mDB.Title pMovie.Rating = mDB.Rating pMovie.Votes = mDB.Votes pMovie.Plot = mDB.Plot pMovie.TmdbID = mDB.TmdbID pMovie.Year = mDB.Year pMovie.OriginalTitle = mDB.OriginalTitle pMovie.Runtime = mDB.Runtime pMovie.Genres = mDB.Genres pMovie.SortTitle = mDB.SortTitle pMovie.Tagline = mDB.Tagline pMovie.Thumb = imageURL("movies/" + mDB.ImdbID + ".jpg") pMovie.Fanart = imageURL("movies/" + mDB.ImdbID + "-fanart.jpg") } // updateFromMovie will update the movieDB from a Movie // We just make sure to never update the movieDB with empty value func (m *movieDB) updateFromMovie(movie *polochon.Movie) { updateIfNonEmpty(&m.ImdbID, movie.ImdbID) updateIfNonEmpty(&m.Title, movie.Title) updateIfNonEmpty(&m.OriginalTitle, movie.OriginalTitle) updateIfNonEmpty(&m.SortTitle, movie.SortTitle) updateIfNonEmpty(&m.Plot, movie.Plot) updateIfNonEmpty(&m.Tagline, movie.Tagline) updateIfNonZeroInt(&m.TmdbID, movie.TmdbID) updateIfNonZeroInt(&m.Votes, movie.Votes) updateIfNonZeroInt(&m.Year, movie.Year) updateIfNonZeroInt(&m.Runtime, movie.Runtime) updateIfNonZeroFloat(&m.Rating, movie.Rating) if movie.Genres != nil { m.Genres = movie.Genres } } // UpsertMovie upsert a polochon Movie in the database func UpsertMovie(db *sqlx.DB, pMovie *polochon.Movie) error { // Try to get the movie movieDB, err := getMovieDB(db, pMovie) // Return only if the error is != sql.ErrNoRows if err != nil { if err != sql.ErrNoRows { return err } } // Update the movieDB from the movie we have movieDB.updateFromMovie(pMovie) r, err := db.NamedQuery(upsertMovieQuery, movieDB) if err != nil { return err } defer r.Close() return nil }