package models import ( "database/sql" "time" "github.com/jmoiron/sqlx" polochon "github.com/odwrtw/polochon/lib" "github.com/sirupsen/logrus" ) const ( upsertEpisodeQuery = ` INSERT INTO episodes (show_imdb_id, show_tvdb_id, title, season, episode, tvdb_id, aired, plot, runtime, rating, imdb_id) VALUES (:show_imdb_id, :show_tvdb_id, :title, :season, :episode, :tvdb_id, :aired, :plot, :runtime, :rating, :imdb_id) ON CONFLICT (show_imdb_id, season, episode) DO UPDATE SET show_imdb_id=:show_imdb_id, show_tvdb_id=:show_tvdb_id, title=:title, season=:season, episode=:episode, tvdb_id=:tvdb_id, aired=:aired, plot=:plot, runtime=:runtime, rating=:rating, imdb_id=:imdb_id RETURNING id;` getEpisodesQuery = ` SELECT * FROM episodes WHERE show_imdb_id=$1;` getEpisodeQuery = ` SELECT * FROM episodes WHERE show_imdb_id=$1 AND season=$2 AND episode=$3;` ) // episodeDB represents the Episode in the DB type episodeDB struct { ID string `db:"id"` TvdbID int `db:"tvdb_id"` ImdbID string `db:"imdb_id"` ShowImdbID string `db:"show_imdb_id"` ShowTvdbID int `db:"show_tvdb_id"` Season int `db:"season"` Episode int `db:"episode"` Title string `db:"title"` Rating float32 `db:"rating"` Plot string `db:"plot"` Thumb string `db:"thumb"` Runtime int `db:"runtime"` Aired string `db:"aired"` Created time.Time `db:"created_at"` Updated time.Time `db:"updated_at"` } // getEpisodeDB returns an episodeDB from a polochon.ShowEpisode func getEpisodeDB(db *sqlx.DB, episode *polochon.ShowEpisode) (*episodeDB, error) { var episodeDB episodeDB err := db.QueryRowx(getEpisodeQuery, episode.ShowImdbID, episode.Season, episode.Episode).StructScan(&episodeDB) if err != nil { return &episodeDB, err } return &episodeDB, nil } // NewEpisodeFromDB returns a new polochon ShowEpisode from an episodeDB func NewEpisodeFromDB(eDB *episodeDB) *polochon.ShowEpisode { pEpisode := polochon.ShowEpisode{} FillEpisodeFromDB(eDB, &pEpisode) return &pEpisode } // FillEpisodeFromDB fills a ShowEpisode from an episodeDB func FillEpisodeFromDB(eDB *episodeDB, pEpisode *polochon.ShowEpisode) { // Keep the data that never changes but only if we have it if eDB.TvdbID != 0 { pEpisode.TvdbID = eDB.TvdbID } if eDB.ImdbID != "" { pEpisode.EpisodeImdbID = eDB.ImdbID } if eDB.ShowImdbID != "" { pEpisode.ShowImdbID = eDB.ShowImdbID } if eDB.ShowTvdbID != 0 { pEpisode.ShowTvdbID = eDB.ShowTvdbID } pEpisode.Season = eDB.Season pEpisode.Episode = eDB.Episode pEpisode.Title = eDB.Title pEpisode.Rating = eDB.Rating pEpisode.Plot = eDB.Plot pEpisode.Thumb = eDB.Thumb pEpisode.Runtime = eDB.Runtime pEpisode.Aired = eDB.Aired } // GetEpisode gets an episode and fills the polochon episode func GetEpisode(db *sqlx.DB, pEpisode *polochon.ShowEpisode) error { episodeDB, err := getEpisodeDB(db, pEpisode) if err != nil { return err } FillEpisodeFromDB(episodeDB, pEpisode) return nil } // GetEpisodes gets show's episodes and fills the polochon show func GetEpisodes(db *sqlx.DB, pShow *polochon.Show, log *logrus.Entry) error { // Get the episodes var episodesDB = []*episodeDB{} err := db.Select(&episodesDB, getEpisodesQuery, pShow.ImdbID) if err != nil { return err } if len(episodesDB) == 0 { log.Debug("got no episodes") return nil } log.Debugf("got %d episodes", len(episodesDB)) for _, episodeDB := range episodesDB { episode := NewEpisodeFromDB(episodeDB) pShow.Episodes = append(pShow.Episodes, episode) } return nil } // updateFromEpisode will update the episodeDB from a ShowEpisode // We just make sure to never update the episodeDB with empty value func (e *episodeDB) updateFromEpisode(showEpisode *polochon.ShowEpisode) { if showEpisode.TvdbID != 0 { e.TvdbID = showEpisode.TvdbID } if showEpisode.EpisodeImdbID != "" { e.ImdbID = showEpisode.EpisodeImdbID } if showEpisode.ShowImdbID != "" { e.ShowImdbID = showEpisode.ShowImdbID } if showEpisode.ShowTvdbID != 0 { e.ShowTvdbID = showEpisode.ShowTvdbID } if showEpisode.Season != 0 { e.Season = showEpisode.Season } if showEpisode.Episode != 0 { e.Episode = showEpisode.Episode } if showEpisode.Title != "" { e.Title = showEpisode.Title } if showEpisode.Rating != 0 { e.Rating = showEpisode.Rating } if showEpisode.Plot != "" { e.Plot = showEpisode.Plot } if showEpisode.Thumb != "" { e.Thumb = showEpisode.Thumb } if showEpisode.Runtime != 0 { e.Runtime = showEpisode.Runtime } if showEpisode.Aired != "" { e.Aired = showEpisode.Aired } } // UpsertEpisode upserts the episode func UpsertEpisode(db *sqlx.DB, showEpisode *polochon.ShowEpisode) error { // Try to get the episode episodeDB, err := getEpisodeDB(db, showEpisode) // Return only if the error is != sql.ErrNoRows if err != nil { if err != sql.ErrNoRows { return err } } // Update the episodeDB from the showEpisode we have episodeDB.updateFromEpisode(showEpisode) r, err := db.NamedQuery(upsertEpisodeQuery, episodeDB) if err != nil { return err } defer r.Close() return nil }