169 lines
5.1 KiB
Go
169 lines
5.1 KiB
Go
package models
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"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 s.title show_title, e.*
|
|
FROM shows s , episodes e
|
|
WHERE s.imdb_id = e.show_imdb_id
|
|
AND e.show_imdb_id=$1
|
|
AND e.season=$2
|
|
AND e.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"`
|
|
ShowTitle string `db:"show_title"`
|
|
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
|
|
updateIfNonEmpty(&pEpisode.EpisodeImdbID, eDB.ImdbID)
|
|
updateIfNonEmpty(&pEpisode.ShowImdbID, eDB.ShowImdbID)
|
|
updateIfNonEmpty(&pEpisode.ShowTitle, eDB.ShowTitle)
|
|
updateIfNonZeroInt(&pEpisode.TvdbID, eDB.TvdbID)
|
|
updateIfNonZeroInt(&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.Runtime = eDB.Runtime
|
|
pEpisode.Aired = eDB.Aired
|
|
pEpisode.Thumb = imageURL(fmt.Sprintf(
|
|
"shows/%s/%d-%d.jpg",
|
|
eDB.ShowImdbID,
|
|
eDB.Season,
|
|
eDB.Episode,
|
|
))
|
|
}
|
|
|
|
// 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) {
|
|
updateIfNonEmpty(&e.ImdbID, showEpisode.EpisodeImdbID)
|
|
updateIfNonEmpty(&e.ShowImdbID, showEpisode.ShowImdbID)
|
|
updateIfNonEmpty(&e.Title, showEpisode.Title)
|
|
updateIfNonEmpty(&e.Plot, showEpisode.Plot)
|
|
updateIfNonEmpty(&e.Thumb, showEpisode.Thumb)
|
|
updateIfNonEmpty(&e.Aired, showEpisode.Aired)
|
|
updateIfNonZeroInt(&e.TvdbID, showEpisode.TvdbID)
|
|
updateIfNonZeroInt(&e.ShowTvdbID, showEpisode.ShowTvdbID)
|
|
updateIfNonZeroInt(&e.Season, showEpisode.Season)
|
|
updateIfNonZeroInt(&e.Episode, showEpisode.Episode)
|
|
updateIfNonZeroInt(&e.Runtime, showEpisode.Runtime)
|
|
updateIfNonZeroFloat(&e.Rating, showEpisode.Rating)
|
|
}
|
|
|
|
// 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
|
|
}
|