commit
aaf3ca4213
@ -42,13 +42,14 @@ CREATE TABLE shows (
|
||||
first_aired timestamp with time zone,
|
||||
LIKE base INCLUDING DEFAULTS
|
||||
);
|
||||
CREATE INDEX ON shows (imdb_id);
|
||||
CREATE UNIQUE INDEX ON shows (imdb_id);
|
||||
CREATE TRIGGER update_shows_updated_at BEFORE UPDATE ON shows FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column();
|
||||
|
||||
CREATE TABLE episodes (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
imdb_id text NOT NULL,
|
||||
show_id uuid REFERENCES shows (id) ON DELETE CASCADE,
|
||||
show_imdb_id text REFERENCES shows (imdb_id) ON DELETE CASCADE,
|
||||
show_tvdb_id text NOT NULL,
|
||||
title text NOT NULL,
|
||||
season smallint NOT NULL,
|
||||
episode smallint NOT NULL,
|
||||
@ -57,19 +58,20 @@ CREATE TABLE episodes (
|
||||
plot text NOT NULL,
|
||||
runtime smallint NOT NULL,
|
||||
rating real NOT NULL,
|
||||
LIKE base INCLUDING DEFAULTS
|
||||
LIKE base INCLUDING DEFAULTS
|
||||
);
|
||||
CREATE INDEX ON episodes (show_id, season);
|
||||
CREATE INDEX ON episodes (show_id, season, episode);
|
||||
|
||||
CREATE INDEX ON episodes (show_imdb_id, season);
|
||||
CREATE UNIQUE INDEX ON episodes (show_imdb_id, season, episode);
|
||||
CREATE TRIGGER update_episodes_updated_at BEFORE UPDATE ON episodes FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column();
|
||||
|
||||
CREATE TABLE shows_tracked (
|
||||
show_id uuid NOT NULL REFERENCES shows (id) ON DELETE CASCADE,
|
||||
show_imdb_id text NOT NULL REFERENCES shows (imdb_id) ON DELETE CASCADE,
|
||||
user_id uuid NOT NULL REFERENCES users (id) ON DELETE CASCADE,
|
||||
season smallint NOT NULL,
|
||||
episode smallint NOT NULL
|
||||
);
|
||||
CREATE INDEX ON shows_tracked (show_id, user_id);
|
||||
CREATE INDEX ON shows_tracked (show_imdb_id, user_id);
|
||||
CREATE INDEX ON shows_tracked (user_id);
|
||||
|
||||
CREATE TABLE movies (
|
||||
|
@ -1,6 +1,6 @@
|
||||
CREATE TYPE media_type AS ENUM ('movie', 'show');
|
||||
CREATE TYPE media_category AS ENUM ('trending', 'popular', 'anticipated', 'box_office');
|
||||
CREATE TYPE media_source AS ENUM ('trakttv', 'yts');
|
||||
CREATE TYPE media_source AS ENUM ('trakttv', 'yts', 'eztv');
|
||||
|
||||
CREATE TABLE external_medias (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
@ -23,7 +23,7 @@ INHERITS (torrents_abstract);
|
||||
CREATE INDEX ON movie_torrents (imdb_id);
|
||||
CREATE UNIQUE INDEX ON movie_torrents (imdb_id, source, quality);
|
||||
CREATE INDEX ON episode_torrents (imdb_id);
|
||||
CREATE INDEX ON episode_torrents (imdb_id, season, episode);
|
||||
CREATE UNIQUE INDEX ON episode_torrents (imdb_id, season, episode, source, quality);
|
||||
CREATE INDEX ON torrents_abstract (imdb_id);
|
||||
|
||||
CREATE TRIGGER update_movie_torrents_updated_at BEFORE UPDATE ON movie_torrents FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column();
|
||||
|
@ -5,7 +5,9 @@ import (
|
||||
"os"
|
||||
|
||||
polochon "github.com/odwrtw/polochon/lib"
|
||||
"github.com/odwrtw/polochon/modules/eztv"
|
||||
"github.com/odwrtw/polochon/modules/tmdb"
|
||||
"github.com/odwrtw/polochon/modules/tvdb"
|
||||
"github.com/odwrtw/polochon/modules/yts"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
@ -22,6 +24,9 @@ type Config struct {
|
||||
TmdbAPIKey string `yaml:"tmdb_api_key"`
|
||||
MovieDetailers []polochon.Detailer
|
||||
MovieTorrenters []polochon.Torrenter
|
||||
MovieSearchers []polochon.Searcher
|
||||
ShowDetailers []polochon.Detailer
|
||||
ShowTorrenters []polochon.Torrenter
|
||||
}
|
||||
|
||||
type AuthorizerConfig struct {
|
||||
@ -67,5 +72,29 @@ func Load(path string) (*Config, error) {
|
||||
}
|
||||
cf.MovieTorrenters = append(cf.MovieTorrenters, d)
|
||||
|
||||
// Default searchers
|
||||
cf.MovieSearchers = []polochon.Searcher{}
|
||||
s, err := yts.NewSearcher()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cf.MovieSearchers = append(cf.MovieSearchers, s)
|
||||
|
||||
// Default detailers
|
||||
cf.ShowDetailers = []polochon.Detailer{}
|
||||
showDetailer, err := tvdb.NewDetailer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cf.ShowDetailers = append(cf.ShowDetailers, showDetailer)
|
||||
|
||||
// Default torrenters
|
||||
cf.ShowTorrenters = []polochon.Torrenter{}
|
||||
showTorrenter, err := eztv.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cf.ShowTorrenters = append(cf.ShowTorrenters, showTorrenter)
|
||||
|
||||
return cf, nil
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// addExternalMediaQuery = `INSERT INTO external_medias (type, source, category, ids) VALUES ($1, $2, $3, $4) RETURNING id;`
|
||||
upsertExternalMediaQuery = `
|
||||
INSERT INTO external_medias (type, source, category, ids)
|
||||
VALUES (:type, :source, :category, :ids)
|
||||
|
@ -6,11 +6,13 @@ import (
|
||||
"net/http"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/movies"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/shows"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
polochon "github.com/odwrtw/polochon/lib"
|
||||
eztvExplorer "github.com/odwrtw/polochon/modules/eztv"
|
||||
traktExplorer "github.com/odwrtw/polochon/modules/trakttv"
|
||||
ytsExplorer "github.com/odwrtw/polochon/modules/yts"
|
||||
)
|
||||
@ -28,13 +30,13 @@ func GetMediaIDs(env *web.Env, mediaType string, source string, category string,
|
||||
media, err := Get(env.Database, mediaType, source, category)
|
||||
switch err {
|
||||
case nil:
|
||||
log.Debug("medias found in database")
|
||||
log.Debugf("%s medias found in database", mediaType)
|
||||
if !force {
|
||||
log.Debug("returning medias from db")
|
||||
return media.IDs, nil
|
||||
}
|
||||
case sql.ErrNoRows:
|
||||
log.Debug("medias not found in database")
|
||||
log.Debugf("%s medias not found in database", mediaType)
|
||||
default:
|
||||
// Unexpected error
|
||||
return nil, err
|
||||
@ -46,9 +48,25 @@ func GetMediaIDs(env *web.Env, mediaType string, source string, category string,
|
||||
}
|
||||
|
||||
var ids []string
|
||||
movies, err := explorer.GetMovieList(polochon.ExploreByRate, log)
|
||||
for _, movie := range movies {
|
||||
ids = append(ids, movie.ImdbID)
|
||||
if mediaType == "movie" {
|
||||
medias, err := explorer.GetMovieList(polochon.ExploreByRate, log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, media := range medias {
|
||||
ids = append(ids, media.ImdbID)
|
||||
}
|
||||
} else {
|
||||
medias, err := explorer.GetShowList(polochon.ExploreByRate, log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i, media := range medias {
|
||||
if i > 5 {
|
||||
break
|
||||
}
|
||||
ids = append(ids, media.ImdbID)
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("got %d medias from %s", len(ids), source)
|
||||
@ -60,7 +78,6 @@ func GetMediaIDs(env *web.Env, mediaType string, source string, category string,
|
||||
IDs: ids,
|
||||
}
|
||||
|
||||
log.Debugf("Inserting int to DB %+v", media)
|
||||
err = media.Upsert(env.Database)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -71,8 +88,8 @@ func GetMediaIDs(env *web.Env, mediaType string, source string, category string,
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// GetMedias get some movies
|
||||
func GetMedias(env *web.Env, source string, category string, force bool) ([]*movies.Movie, error) {
|
||||
// GetMovies get some movies
|
||||
func GetMovies(env *web.Env, source string, category string, force bool) ([]*movies.Movie, error) {
|
||||
movieIds, err := GetMediaIDs(env, "movie", source, category, force)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -83,12 +100,12 @@ func GetMedias(env *web.Env, source string, category string, force bool) ([]*mov
|
||||
movie := movies.New(id)
|
||||
err := movie.GetDetails(env, force)
|
||||
if err != nil {
|
||||
env.Log.Error(err)
|
||||
env.Log.Errorf("error while getting movie details : %s", err)
|
||||
continue
|
||||
}
|
||||
err = movie.GetTorrents(env, force)
|
||||
if err != nil {
|
||||
env.Log.Error(err)
|
||||
env.Log.Errorf("error while getting movie torrents : %s", err)
|
||||
continue
|
||||
}
|
||||
movieList = append(movieList, movie)
|
||||
@ -96,6 +113,31 @@ func GetMedias(env *web.Env, source string, category string, force bool) ([]*mov
|
||||
return movieList, nil
|
||||
}
|
||||
|
||||
// GetShows get some shows
|
||||
func GetShows(env *web.Env, source string, category string, force bool) ([]*shows.Show, error) {
|
||||
showIds, err := GetMediaIDs(env, "show", source, category, force)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
showList := []*shows.Show{}
|
||||
for _, id := range showIds {
|
||||
show := shows.New(id)
|
||||
err := show.GetDetails(env, force)
|
||||
if err != nil {
|
||||
env.Log.Errorf("error while getting show details : %s", err)
|
||||
continue
|
||||
}
|
||||
err = show.GetTorrents(env, force)
|
||||
if err != nil {
|
||||
env.Log.Errorf("error while getting show torrents : %s", err)
|
||||
continue
|
||||
}
|
||||
showList = append(showList, show)
|
||||
}
|
||||
return showList, nil
|
||||
}
|
||||
|
||||
// Explore will explore some movies
|
||||
func Explore(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
err := r.ParseForm()
|
||||
@ -116,7 +158,7 @@ func Explore(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
}
|
||||
|
||||
// Get the medias without trying to refresh them
|
||||
movies, err := GetMedias(env, source, category, false)
|
||||
movies, err := GetMovies(env, source, category, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -124,12 +166,45 @@ func Explore(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
return env.RenderJSON(w, movies)
|
||||
}
|
||||
|
||||
// ExploreShows will explore some shows
|
||||
func ExploreShows(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source := r.FormValue("source")
|
||||
// Default source
|
||||
if source == "" {
|
||||
source = "eztv"
|
||||
}
|
||||
|
||||
category := r.FormValue("category")
|
||||
// Default category
|
||||
if category == "" {
|
||||
category = "popular"
|
||||
}
|
||||
|
||||
// Get the medias without trying to refresh them
|
||||
shows, err := GetShows(env, source, category, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return env.RenderJSON(w, shows)
|
||||
}
|
||||
|
||||
// MediaSources represents the implemented media sources
|
||||
var MediaSources = []string{
|
||||
"trakttv",
|
||||
"yts",
|
||||
}
|
||||
|
||||
// ShowMediaSources represents the implemented media sources for shows
|
||||
var ShowMediaSources = []string{
|
||||
"eztv",
|
||||
}
|
||||
|
||||
// Refresh will refresh the movie list
|
||||
func Refresh(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
env.Log.Debugf("refreshing infos ...")
|
||||
@ -147,7 +222,33 @@ func Refresh(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
for _, source := range MediaSources {
|
||||
env.Log.Debugf("refreshing %s", source)
|
||||
// GetMedias and refresh them
|
||||
_, err := GetMedias(env, source, category, true)
|
||||
_, err := GetMovies(env, source, category, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return env.RenderJSON(w, map[string]string{"message": "Refresh is done"})
|
||||
}
|
||||
|
||||
// RefreshShows will refresh the movie list
|
||||
func RefreshShows(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
env.Log.Debugf("refreshing shows ...")
|
||||
source := r.FormValue("source")
|
||||
if source == "" {
|
||||
source = "eztv"
|
||||
}
|
||||
|
||||
category := r.FormValue("category")
|
||||
if category == "" {
|
||||
category = "popular"
|
||||
}
|
||||
|
||||
// We'll refresh the medias for each sources
|
||||
for _, source := range ShowMediaSources {
|
||||
env.Log.Debugf("refreshing %s", source)
|
||||
// GetMedias and refresh them
|
||||
_, err := GetShows(env, source, category, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -165,6 +266,8 @@ func NewExplorer(env *web.Env, source string) (polochon.Explorer, error) {
|
||||
})
|
||||
case "yts":
|
||||
return ytsExplorer.NewExplorer()
|
||||
case "eztv":
|
||||
return eztvExplorer.NewExplorer()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown explorer")
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package movies
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@ -109,3 +110,41 @@ func GetDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) err
|
||||
|
||||
return env.RenderJSON(w, m)
|
||||
}
|
||||
|
||||
// SearchMovie will search movie
|
||||
func SearchMovie(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
key := r.FormValue("key")
|
||||
if key == "" {
|
||||
return env.RenderError(w, errors.New("no given key"))
|
||||
}
|
||||
|
||||
var movies []*polochon.Movie
|
||||
searchers := env.Config.MovieSearchers
|
||||
for _, searcher := range searchers {
|
||||
result, err := searcher.SearchMovie(key, env.Log)
|
||||
if err != nil {
|
||||
env.Log.Errorf("error while searching movie : %s", err)
|
||||
continue
|
||||
}
|
||||
movies = append(movies, result...)
|
||||
}
|
||||
|
||||
env.Log.Debugf("got %d movies doing search %q", len(movies), key)
|
||||
movieList := []*Movie{}
|
||||
for _, m := range movies {
|
||||
movie := New(m.ImdbID)
|
||||
err := movie.GetDetails(env, false)
|
||||
if err != nil {
|
||||
env.Log.Errorf("error while getting movie details : %s", err)
|
||||
continue
|
||||
}
|
||||
err = movie.GetTorrents(env, false)
|
||||
if err != nil {
|
||||
env.Log.Errorf("error while getting movie torrents : %s", err)
|
||||
continue
|
||||
}
|
||||
movieList = append(movieList, movie)
|
||||
}
|
||||
|
||||
return env.RenderJSON(w, movieList)
|
||||
}
|
||||
|
180
src/internal/shows/episodes.go
Normal file
180
src/internal/shows/episodes.go
Normal file
@ -0,0 +1,180 @@
|
||||
package shows
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/jmoiron/sqlx"
|
||||
polochon "github.com/odwrtw/polochon/lib"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/sqly"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/torrents"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
|
||||
)
|
||||
|
||||
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;`
|
||||
)
|
||||
|
||||
// Episode represents an episode
|
||||
type Episode struct {
|
||||
sqly.BaseModel
|
||||
polochon.ShowEpisode
|
||||
}
|
||||
|
||||
// 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"`
|
||||
ReleaseGroup string `db:"release_group"`
|
||||
Created time.Time `db:"created_at"`
|
||||
Updated time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
// NewEpisode returns an Episode
|
||||
func NewEpisode() *Episode {
|
||||
return &Episode{}
|
||||
}
|
||||
|
||||
// NewEpisodeDB returns an Episode ready to be put in DB from an
|
||||
// Episode
|
||||
func NewEpisodeDB(e *Episode) EpisodeDB {
|
||||
return EpisodeDB{
|
||||
ID: e.ID,
|
||||
TvdbID: e.TvdbID,
|
||||
ImdbID: e.EpisodeImdbID,
|
||||
ShowImdbID: e.ShowImdbID,
|
||||
ShowTvdbID: e.ShowTvdbID,
|
||||
Season: e.Season,
|
||||
Episode: e.Episode,
|
||||
Title: e.Title,
|
||||
Rating: e.Rating,
|
||||
Plot: e.Plot,
|
||||
Thumb: e.Thumb,
|
||||
Runtime: e.Runtime,
|
||||
Aired: e.Aired,
|
||||
ReleaseGroup: e.ReleaseGroup,
|
||||
Created: e.Created,
|
||||
Updated: e.Updated,
|
||||
}
|
||||
}
|
||||
|
||||
// FillFromDB returns a Show from a ShowDB extracted from the DB
|
||||
func (e *Episode) FillFromDB(eDB *EpisodeDB) {
|
||||
e.ID = eDB.ID
|
||||
e.TvdbID = eDB.TvdbID
|
||||
e.EpisodeImdbID = eDB.ImdbID
|
||||
e.ShowImdbID = eDB.ShowImdbID
|
||||
e.ShowTvdbID = eDB.ShowTvdbID
|
||||
e.Season = eDB.Season
|
||||
e.Episode = eDB.Episode
|
||||
e.Title = eDB.Title
|
||||
e.Rating = eDB.Rating
|
||||
e.Plot = eDB.Plot
|
||||
e.Thumb = eDB.Thumb
|
||||
e.Runtime = eDB.Runtime
|
||||
e.Aired = eDB.Aired
|
||||
e.Created = eDB.Created
|
||||
e.Updated = eDB.Updated
|
||||
}
|
||||
|
||||
// Upsert episode to the database
|
||||
func (e *Episode) Upsert(db *sqlx.DB) error {
|
||||
eDB := NewEpisodeDB(e)
|
||||
var id string
|
||||
r, err := db.NamedQuery(upsertEpisodeQuery, eDB)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for r.Next() {
|
||||
r.Scan(&id)
|
||||
}
|
||||
e.ID = id
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTorrents retrieves torrents for the show, first try to get info from db,
|
||||
// if not exists, use polochon.Torrenter and save informations in the database
|
||||
// for future use
|
||||
//
|
||||
// If force is used, the torrenter will be used even if the torrent is found in
|
||||
// database
|
||||
func (e *Episode) GetTorrents(env *web.Env, force bool) error {
|
||||
log := env.Log.WithFields(logrus.Fields{
|
||||
"imdb_id": e.ShowEpisode.ShowImdbID,
|
||||
"season": e.ShowEpisode.Season,
|
||||
"episode": e.ShowEpisode.Episode,
|
||||
"function": "shows.GetTorrents",
|
||||
})
|
||||
log.Debugf("getting torrents")
|
||||
|
||||
if len(e.Torrenters) == 0 {
|
||||
e.Torrenters = env.Config.ShowTorrenters
|
||||
}
|
||||
|
||||
episodeTorrents, err := torrents.GetEpisodeTorrents(
|
||||
env.Database,
|
||||
e.ShowEpisode.ShowImdbID,
|
||||
e.ShowEpisode.Season,
|
||||
e.ShowEpisode.Episode,
|
||||
)
|
||||
switch err {
|
||||
case nil:
|
||||
log.Debug("torrents found in database")
|
||||
case sql.ErrNoRows:
|
||||
log.Debug("torrent not found in database")
|
||||
// We'll need to GetTorrents from torrenters
|
||||
default:
|
||||
// Unexpected error
|
||||
return err
|
||||
}
|
||||
if !force {
|
||||
log.Debugf("returning %d torrents from db", len(episodeTorrents))
|
||||
// Add the torrents to the episode
|
||||
for _, t := range episodeTorrents {
|
||||
e.Torrents = append(e.Torrents, t.Torrent)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
err = e.ShowEpisode.GetTorrents(env.Log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("got %d torrents from torrenters", len(e.ShowEpisode.Torrents))
|
||||
|
||||
for _, t := range e.ShowEpisode.Torrents {
|
||||
torrent := torrents.NewEpisodeFromPolochon(e.ShowEpisode, t)
|
||||
err = torrent.Upsert(env.Database)
|
||||
if err != nil {
|
||||
log.Errorf("error while adding torrent : %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
24
src/internal/shows/handlers.go
Normal file
24
src/internal/shows/handlers.go
Normal file
@ -0,0 +1,24 @@
|
||||
package shows
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
|
||||
)
|
||||
|
||||
// GetDetailsHandler retrieves details for a movie
|
||||
func GetDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
||||
s := New(id)
|
||||
if err := s.GetDetails(env, false); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.GetEpisodes(env); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return env.RenderJSON(w, s)
|
||||
}
|
@ -1,10 +1,15 @@
|
||||
package shows
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/sqly"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/users"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/jmoiron/sqlx"
|
||||
@ -12,70 +17,57 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
addShowQuery = `
|
||||
upsertShowQuery = `
|
||||
INSERT INTO shows (imdb_id, title, rating, plot, tvdb_id, year, first_aired)
|
||||
VALUES (:imdbid, :title, :rating, :plot, :tvdbid, :year, :firstaired) RETURNING id;`
|
||||
VALUES (:imdb_id, :title, :rating, :plot, :tvdb_id, :year, :first_aired)
|
||||
ON CONFLICT (imdb_id)
|
||||
DO UPDATE
|
||||
SET imdb_id=:imdb_id, title=:title, rating=:rating, plot=:plot,
|
||||
tvdb_id=:tvdb_id, year=:year, first_aired=:first_aired
|
||||
RETURNING id;`
|
||||
|
||||
getShowQueryByImdbID = `
|
||||
SELECT
|
||||
id, imdb_id AS imdbid,
|
||||
title, rating, plot,
|
||||
tvdb_id AS tvdbid,
|
||||
year, first_aired AS firstaired,
|
||||
created_at, updated_at
|
||||
SELECT *
|
||||
FROM shows WHERE imdb_id=$1;`
|
||||
|
||||
getShowQueryByID = `
|
||||
SELECT
|
||||
id, imdb_id AS imdbid,
|
||||
title, rating, plot,
|
||||
tvdb_id AS tvdbid,
|
||||
year, first_aired AS firstaired,
|
||||
created_at, updated_at
|
||||
SELECT *
|
||||
FROM shows WHERE id=$1;`
|
||||
|
||||
deleteShowQuery = `DELETE FROM shows WHERE id=$1;`
|
||||
|
||||
addEpisodeQuery = `
|
||||
INSERT INTO episodes (show_id, title, season, episode, tvdb_id, aired, plot, runtime, rating, imdb_id)
|
||||
VALUES (:showid, :title, :season, :episode, :tvdbid, :aired, :plot, :runtime, :rating, :episodeimdbid) RETURNING id;`
|
||||
|
||||
getEpisodesQuery = `
|
||||
SELECT title, season, episode, tvdb_id AS tvdbid, aired, plot, runtime, rating, imdb_id AS episodeimdbid, show_id AS showid
|
||||
FROM episodes WHERE show_id=$1;`
|
||||
deleteShowQueryByID = `DELETE FROM shows WHERE id=$1;`
|
||||
|
||||
getShowWithUserQueryByImdbID = `
|
||||
SELECT
|
||||
shows.id,
|
||||
shows.imdb_id AS imdbid,
|
||||
shows.imdb_id,
|
||||
shows.title,
|
||||
shows.rating,
|
||||
shows.plot,
|
||||
shows.tvdb_id AS tvdbid,
|
||||
shows.tvdb_id,
|
||||
shows.year,
|
||||
shows.first_aired AS firstaired,
|
||||
shows.first_aired,
|
||||
shows.created_at,
|
||||
shows.updated_at,
|
||||
COALESCE(shows_tracked.season,0) AS trackedseason,
|
||||
COALESCE(shows_tracked.season,0),
|
||||
COALESCE(shows_tracked.episode,0) AS trackedepisode
|
||||
FROM shows LEFT JOIN shows_tracked ON shows.id=shows_tracked.show_id AND shows_tracked.user_id=$2
|
||||
FROM shows LEFT JOIN shows_tracked ON shows.id=shows_tracked.show_imdb_id AND shows_tracked.user_id=$2
|
||||
WHERE shows.imdb_id=$1;`
|
||||
|
||||
getShowWithUserQueryByID = `
|
||||
SELECT
|
||||
shows.id,
|
||||
shows.imdb_id AS imdbid,
|
||||
shows.imdb_id,
|
||||
shows.title,
|
||||
shows.rating,
|
||||
shows.plot,
|
||||
shows.tvdb_id AS tvdbid,
|
||||
shows.tvdb_id,
|
||||
shows.year,
|
||||
shows.first_aired AS firstaired,
|
||||
shows.first_aired,
|
||||
shows.created_at,
|
||||
shows.updated_at,
|
||||
COALESCE(shows_tracked.season,0) AS trackedseason,
|
||||
COALESCE(shows_tracked.episode,0) AS trackedepisode
|
||||
FROM shows LEFT JOIN shows_tracked ON shows.id=shows_tracked.show_id AND shows_tracked.user_id=$2
|
||||
COALESCE(shows_tracked.season,0),
|
||||
COALESCE(shows_tracked.episode,0)
|
||||
FROM shows LEFT JOIN shows_tracked ON shows.id=shows_tracked.show_imdb_id AND shows_tracked.user_id=$2
|
||||
WHERE shows.id=$1;`
|
||||
)
|
||||
|
||||
@ -91,29 +83,85 @@ type Show struct {
|
||||
Episodes []*Episode
|
||||
TrackedSeason int
|
||||
TrackedEpisode int
|
||||
BannerURL string `json:"banner_url"`
|
||||
FanartURL string `json:"fanart_url"`
|
||||
PosterURL string `json:"poster_url"`
|
||||
}
|
||||
|
||||
// ShowDB represents the Show in the DB
|
||||
type ShowDB struct {
|
||||
ID string `db:"id"`
|
||||
ImdbID string `db:"imdb_id"`
|
||||
TvdbID int `db:"tvdb_id"`
|
||||
Title string `db:"title"`
|
||||
Rating float32 `db:"rating"`
|
||||
Plot string `db:"plot"`
|
||||
Year int `db:"year"`
|
||||
FirstAired time.Time `db:"first_aired"`
|
||||
Created time.Time `db:"created_at"`
|
||||
Updated time.Time `db:"updated_at"`
|
||||
// URL string `json:"-"`
|
||||
}
|
||||
|
||||
// NewShowDB returns a Show ready to be put in DB from a
|
||||
// Show
|
||||
func NewShowDB(s *Show) ShowDB {
|
||||
return ShowDB{
|
||||
ID: s.ID,
|
||||
ImdbID: s.ImdbID,
|
||||
Title: s.Title,
|
||||
Rating: s.Rating,
|
||||
Plot: s.Plot,
|
||||
TvdbID: s.TvdbID,
|
||||
Year: s.Year,
|
||||
FirstAired: *s.FirstAired,
|
||||
Created: s.Created,
|
||||
Updated: s.Updated,
|
||||
}
|
||||
}
|
||||
|
||||
// FillFromDB returns a Show from a ShowDB extracted from the DB
|
||||
func (s *Show) FillFromDB(sDB *ShowDB) {
|
||||
s.ID = sDB.ID
|
||||
s.ImdbID = sDB.ImdbID
|
||||
s.Title = sDB.Title
|
||||
s.Rating = sDB.Rating
|
||||
s.Plot = sDB.Plot
|
||||
s.TvdbID = sDB.TvdbID
|
||||
s.Year = sDB.Year
|
||||
s.FirstAired = &sDB.FirstAired
|
||||
s.Created = sDB.Created
|
||||
s.Updated = sDB.Updated
|
||||
}
|
||||
|
||||
// New returns a new Show with a polochon ShowConfig
|
||||
func New(conf polochon.ShowConfig) *Show {
|
||||
return &Show{Show: polochon.Show{ShowConfig: conf}}
|
||||
func New(imdbID string) *Show {
|
||||
return &Show{
|
||||
Show: polochon.Show{
|
||||
ImdbID: imdbID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns show details in database from id or imdbid or an error
|
||||
func (s *Show) Get(db *sqlx.DB) error {
|
||||
func (s *Show) Get(env *web.Env) error {
|
||||
var sDB ShowDB
|
||||
var err error
|
||||
if s.ID != "" {
|
||||
err = db.QueryRowx(getShowQueryByID, s.ID).StructScan(s)
|
||||
err = env.Database.QueryRowx(getShowQueryByID, s.ID).StructScan(&sDB)
|
||||
} else if s.ImdbID != "" {
|
||||
err = db.QueryRowx(getShowQueryByImdbID, s.ImdbID).StructScan(s)
|
||||
err = env.Database.QueryRowx(getShowQueryByImdbID, s.ImdbID).StructScan(&sDB)
|
||||
} else {
|
||||
err = fmt.Errorf("Can't get show details, you have to specify an ID or ImdbID")
|
||||
}
|
||||
if err != nil {
|
||||
if err.Error() == "sql: no rows in result set" {
|
||||
return ErrNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the poster url
|
||||
s.PosterURL = s.GetPosterURL(env)
|
||||
|
||||
s.FillFromDB(&sDB)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -139,36 +187,97 @@ func (s *Show) GetAsUser(db *sqlx.DB, user *users.User) error {
|
||||
// GetDetails retrieves details for the show, first try to
|
||||
// get info from db, if not exists, use polochon.Detailer
|
||||
// and save informations in the database for future use
|
||||
func (s *Show) GetDetails(db *sqlx.DB, log *logrus.Entry) error {
|
||||
var err error
|
||||
err = s.Get(db)
|
||||
if err == nil {
|
||||
// found ok
|
||||
return nil
|
||||
func (s *Show) GetDetails(env *web.Env, force bool) error {
|
||||
log := env.Log.WithFields(logrus.Fields{
|
||||
"imdb_id": s.ImdbID,
|
||||
"function": "shows.GetDetails",
|
||||
})
|
||||
log.Debugf("getting details")
|
||||
|
||||
if len(s.Detailers) == 0 {
|
||||
s.Detailers = env.Config.ShowDetailers
|
||||
}
|
||||
if err != ErrNotFound {
|
||||
|
||||
var err error
|
||||
err = s.Get(env)
|
||||
switch err {
|
||||
case nil:
|
||||
log.Debug("show found in database")
|
||||
if !force {
|
||||
log.Debug("returning show from db")
|
||||
return nil
|
||||
}
|
||||
case sql.ErrNoRows:
|
||||
log.Debug("show not found in database")
|
||||
default:
|
||||
// Unexpected error
|
||||
return err
|
||||
}
|
||||
|
||||
// so we got ErrNotFound so GetDetails from a detailer
|
||||
err = s.Show.GetDetails(log)
|
||||
// GetDetail
|
||||
err = s.Show.GetDetails(env.Log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debug("got details from detailers")
|
||||
s.Episodes = []*Episode{}
|
||||
for _, pe := range s.Show.Episodes {
|
||||
s.Episodes = append(s.Episodes, &Episode{ShowEpisode: *pe})
|
||||
}
|
||||
|
||||
err = s.Add(db)
|
||||
err = s.Upsert(env.Database)
|
||||
if err != nil {
|
||||
log.Debug("error while doing show upsert func", err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debug("show added in database")
|
||||
|
||||
// Download show images
|
||||
s.downloadImages(env)
|
||||
|
||||
log.Debug("images downloaded")
|
||||
|
||||
// Set the poster url
|
||||
s.PosterURL = s.GetPosterURL(env)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPosterURL returns the image URL or the default image if the poster is not yet downloaded
|
||||
func (s *Show) GetPosterURL(env *web.Env) string {
|
||||
// Check if the movie image exists
|
||||
if _, err := os.Stat(s.imgURL(env, "poster")); os.IsNotExist(err) {
|
||||
// TODO image in the config ?
|
||||
return "img/noimage.png"
|
||||
}
|
||||
return s.imgURL(env, "poster")
|
||||
}
|
||||
|
||||
// downloadImages will download the show images
|
||||
func (s *Show) downloadImages(env *web.Env) {
|
||||
// Download the banner
|
||||
err := web.Download(s.Show.Banner, s.imgURL(env, "banner"))
|
||||
if err != nil {
|
||||
env.Log.Errorf("failed to dowload banner: %s", err)
|
||||
}
|
||||
err = web.Download(s.Show.Fanart, s.imgURL(env, "fanart"))
|
||||
if err != nil {
|
||||
env.Log.Errorf("failed to dowload fanart: %s", err)
|
||||
}
|
||||
err = web.Download(s.Show.Poster, s.imgURL(env, "poster"))
|
||||
if err != nil {
|
||||
env.Log.Errorf("failed to dowload poster: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// imgFile returns the image location on disk
|
||||
func (s *Show) imgURL(env *web.Env, imgType string) string {
|
||||
fileURL := fmt.Sprintf("img/shows/%s-%s.jpg", s.ImdbID, imgType)
|
||||
return filepath.Join(env.Config.PublicDir, fileURL)
|
||||
}
|
||||
|
||||
// GetDetailsAsUser like GetDetails but with User context
|
||||
func (s *Show) GetDetailsAsUser(db *sqlx.DB, user *users.User, log *logrus.Entry) error {
|
||||
var err error
|
||||
@ -191,7 +300,7 @@ func (s *Show) GetDetailsAsUser(db *sqlx.DB, user *users.User, log *logrus.Entry
|
||||
s.Episodes = append(s.Episodes, &Episode{ShowEpisode: *pe})
|
||||
}
|
||||
|
||||
err = s.Add(db)
|
||||
err = s.Upsert(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -207,10 +316,11 @@ func (s *Show) IsTracked() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Add a show in the database
|
||||
func (s *Show) Add(db *sqlx.DB) error {
|
||||
// Upsert a show in the database
|
||||
func (s *Show) Upsert(db *sqlx.DB) error {
|
||||
sDB := NewShowDB(s)
|
||||
var id string
|
||||
r, err := db.NamedQuery(addShowQuery, s)
|
||||
r, err := db.NamedQuery(upsertShowQuery, sDB)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -220,8 +330,8 @@ func (s *Show) Add(db *sqlx.DB) error {
|
||||
s.ID = id
|
||||
|
||||
for _, e := range s.Episodes {
|
||||
e.ShowID = s.ID
|
||||
err = e.Add(db)
|
||||
e.ShowImdbID = s.ImdbID
|
||||
err = e.Upsert(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -231,7 +341,7 @@ func (s *Show) Add(db *sqlx.DB) error {
|
||||
|
||||
// Delete show from database
|
||||
func (s *Show) Delete(db *sqlx.DB) error {
|
||||
r, err := db.Exec(deleteShowQuery, s.ID)
|
||||
r, err := db.Exec(deleteShowQueryByID, s.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -243,35 +353,37 @@ func (s *Show) Delete(db *sqlx.DB) error {
|
||||
}
|
||||
|
||||
// GetEpisodes from database
|
||||
func (s *Show) GetEpisodes(db *sqlx.DB) error {
|
||||
// When retrive episode's info from database populate the s.Episodes member
|
||||
// and not s.Show.Episodes
|
||||
s.Episodes = []*Episode{}
|
||||
err := db.Select(&s.Episodes, getEpisodesQuery, s.ID)
|
||||
func (s *Show) GetEpisodes(env *web.Env) error {
|
||||
// We retrive episode's info from database populate the s.Episodes member
|
||||
var episodesDB = []*EpisodeDB{}
|
||||
err := env.Database.Select(&episodesDB, getEpisodesQuery, s.ImdbID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(episodesDB) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, episodeDB := range episodesDB {
|
||||
episode := NewEpisode()
|
||||
episode.FillFromDB(episodeDB)
|
||||
s.Episodes = append(s.Episodes, episode)
|
||||
err = episode.GetTorrents(env, false)
|
||||
if err != nil {
|
||||
env.Log.Debugf("error while getting episode torrent: %q", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Episode represents an episode
|
||||
type Episode struct {
|
||||
sqly.BaseModel
|
||||
polochon.ShowEpisode
|
||||
ShowID string
|
||||
}
|
||||
|
||||
// Add episode to the database
|
||||
func (e *Episode) Add(db *sqlx.DB) error {
|
||||
var id string
|
||||
r, err := db.NamedQuery(addEpisodeQuery, e)
|
||||
if err != nil {
|
||||
return err
|
||||
// GetTorrents from the database or fetch them if needed
|
||||
func (s *Show) GetTorrents(env *web.Env, force bool) error {
|
||||
for _, e := range s.Episodes {
|
||||
err := e.GetTorrents(env, force)
|
||||
if err != nil {
|
||||
env.Log.Errorf("error while getting episode torrent: %s", err)
|
||||
}
|
||||
}
|
||||
for r.Next() {
|
||||
r.Scan(&id)
|
||||
}
|
||||
e.ID = id
|
||||
return nil
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ func TestTrackedShow(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
err := show.Add(db)
|
||||
err := show.Upsert(db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
160
src/internal/torrents/episode_torrents.go
Normal file
160
src/internal/torrents/episode_torrents.go
Normal file
@ -0,0 +1,160 @@
|
||||
package torrents
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/sqly"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
polochon "github.com/odwrtw/polochon/lib"
|
||||
)
|
||||
|
||||
const (
|
||||
upsertEpisodeTorrentQuery = `
|
||||
INSERT INTO episode_torrents (imdb_id, url, source, quality, upload_user,
|
||||
season, episode, seeders, leechers)
|
||||
VALUES (:imdb_id, :url, :source, :quality, :upload_user, :season, :episode,
|
||||
:seeders, :leechers)
|
||||
ON CONFLICT (imdb_id, season, episode, quality, source)
|
||||
DO UPDATE SET imdb_id=:imdb_id, url=:url, source=:source, quality=:quality,
|
||||
upload_user=:upload_user, season=:season, episode=:episode,
|
||||
seeders=:seeders, leechers=:leechers
|
||||
RETURNING id;`
|
||||
|
||||
getEpisodeTorrentQuery = `
|
||||
SELECT *
|
||||
FROM episode_torrents WHERE imdb_id=$1 AND season=$2 AND episode=$3;`
|
||||
|
||||
getEpisodeTorrentQueryByID = `
|
||||
SELECT *
|
||||
FROM episode_torrents WHERE id=$1;`
|
||||
|
||||
deleteEpisodeTorrentQuery = `DELETE FROM movie_torrents WHERE id=$1;`
|
||||
)
|
||||
|
||||
// EpisodeTorrent represents an episode torrent
|
||||
type EpisodeTorrent struct {
|
||||
sqly.BaseModel
|
||||
polochon.Torrent
|
||||
ShowImdbID string `json:"show_imdb_id"`
|
||||
Season int `json:"season"`
|
||||
Episode int `json:"episode"`
|
||||
}
|
||||
|
||||
// EpisodeTorrentDB represents the EpisodeTorrent in the DB
|
||||
type EpisodeTorrentDB struct {
|
||||
ID string `db:"id"`
|
||||
ImdbID string `db:"imdb_id"`
|
||||
URL string `db:"url"`
|
||||
Source string `db:"source"`
|
||||
Quality string `db:"quality"`
|
||||
UploadUser string `db:"upload_user"`
|
||||
Season int `db:"season"`
|
||||
Episode int `db:"episode"`
|
||||
Seeders int `db:"seeders"`
|
||||
Leechers int `db:"leechers"`
|
||||
Created time.Time `db:"created_at"`
|
||||
Updated time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
// NewEpisodeFromPolochon returns a new EpisodeTorrent from a polochon.ShowEpisode
|
||||
func NewEpisodeFromPolochon(se polochon.ShowEpisode, poTo polochon.Torrent) *EpisodeTorrent {
|
||||
return &EpisodeTorrent{
|
||||
ShowImdbID: se.ShowImdbID,
|
||||
Season: se.Season,
|
||||
Episode: se.Episode,
|
||||
Torrent: poTo,
|
||||
}
|
||||
}
|
||||
|
||||
// NewEpisode returns a new EpisodeTorrent
|
||||
func NewEpisode() *EpisodeTorrent {
|
||||
return &EpisodeTorrent{}
|
||||
}
|
||||
|
||||
// GetEpisodeTorrents returns show details in database from id or imdbid or an error
|
||||
func GetEpisodeTorrents(db *sqlx.DB, imdbID string, season, episode int) ([]*EpisodeTorrent, error) {
|
||||
var torrentsDB = []*EpisodeTorrentDB{}
|
||||
err := db.Select(&torrentsDB, getEpisodeTorrentQuery, imdbID, season, episode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(torrentsDB) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
|
||||
var torrents []*EpisodeTorrent
|
||||
for _, torrentDB := range torrentsDB {
|
||||
episode := NewEpisode()
|
||||
episode.FillFromDB(torrentDB)
|
||||
torrents = append(torrents, episode)
|
||||
}
|
||||
|
||||
return torrents, nil
|
||||
}
|
||||
|
||||
// Delete episode from database
|
||||
func (e *EpisodeTorrent) Delete(db *sqlx.DB) error {
|
||||
r, err := db.Exec(deleteEpisodeTorrentQuery, e.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
count, _ := r.RowsAffected()
|
||||
if count != 1 {
|
||||
return fmt.Errorf("Unexpected number of row deleted: %d", count)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FillFromDB will fill a MovieTorrent from a MovieTorrentDB extracted from the DB
|
||||
func (e *EpisodeTorrent) FillFromDB(eDB *EpisodeTorrentDB) {
|
||||
q, _ := polochon.StringToQuality(eDB.Quality)
|
||||
e.ShowImdbID = eDB.ImdbID
|
||||
e.Created = eDB.Created
|
||||
e.Updated = eDB.Updated
|
||||
e.ID = eDB.ID
|
||||
e.URL = eDB.URL
|
||||
e.Source = eDB.Source
|
||||
e.Quality = *q
|
||||
e.UploadUser = eDB.UploadUser
|
||||
e.Seeders = eDB.Seeders
|
||||
e.Leechers = eDB.Leechers
|
||||
}
|
||||
|
||||
// Upsert an episode torrent in the database
|
||||
func (e *EpisodeTorrent) Upsert(db *sqlx.DB) error {
|
||||
eDB := NewEpisodeTorrentDB(e)
|
||||
var id string
|
||||
r, err := db.NamedQuery(upsertEpisodeTorrentQuery, eDB)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for r.Next() {
|
||||
r.Scan(&id)
|
||||
}
|
||||
e.ID = id
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewEpisodeTorrentDB returns an EpisodeTorrent ready to be put in DB from a
|
||||
// EspisodeTorrent
|
||||
func NewEpisodeTorrentDB(e *EpisodeTorrent) EpisodeTorrentDB {
|
||||
return EpisodeTorrentDB{
|
||||
ID: e.ID,
|
||||
ImdbID: e.ShowImdbID,
|
||||
Season: e.Season,
|
||||
Episode: e.Episode,
|
||||
URL: e.URL,
|
||||
Source: e.Source,
|
||||
Quality: string(e.Quality),
|
||||
UploadUser: e.UploadUser,
|
||||
Seeders: e.Seeders,
|
||||
Leechers: e.Leechers,
|
||||
Created: e.Created,
|
||||
Updated: e.Updated,
|
||||
}
|
||||
}
|
@ -54,15 +54,6 @@ type MovieTorrentDB struct {
|
||||
Updated time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
// EpisodeTorrent represents an episode torrent
|
||||
type EpisodeTorrent struct {
|
||||
sqly.BaseModel
|
||||
polochon.Torrent
|
||||
ShowImdbID string `json:"show_imdb_id"`
|
||||
Season int `json:"season"`
|
||||
Episode int `json:"episode"`
|
||||
}
|
||||
|
||||
// NewMovieFromImDB returns a new MovieTorrent with an ImDB id
|
||||
func NewMovieFromImDB(imdbID string) *MovieTorrent {
|
||||
return &MovieTorrent{
|
@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/movies"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/shows"
|
||||
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/auth"
|
||||
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/config"
|
||||
@ -79,6 +80,12 @@ func main() {
|
||||
env.Handle("/movies/{id:tt[0-9]+}/get_details", movies.GetDetailsHandler).WithRole(users.UserRole)
|
||||
env.Handle("/movies/explore", extmedias.Explore)
|
||||
env.Handle("/movies/refresh", extmedias.Refresh)
|
||||
env.Handle("/movies/search", movies.SearchMovie)
|
||||
|
||||
// env.Handle("/shows/polochon", shows.FromPolochon).WithRole(users.UserRole)
|
||||
env.Handle("/shows/{id:tt[0-9]+}", shows.GetDetailsHandler)
|
||||
env.Handle("/shows/refresh", extmedias.RefreshShows)
|
||||
env.Handle("/shows/explore", extmedias.ExploreShows)
|
||||
|
||||
n := negroni.Classic()
|
||||
n.Use(authMiddleware)
|
||||
|
Loading…
x
Reference in New Issue
Block a user