We now use the right log object with prefix and return an error on GetDetails only if the error is Fatal
415 lines
11 KiB
Go
415 lines
11 KiB
Go
package shows
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
|
|
"net/http"
|
|
|
|
"git.quimbo.fr/odwrtw/canape/backend/auth"
|
|
"git.quimbo.fr/odwrtw/canape/backend/models"
|
|
"git.quimbo.fr/odwrtw/canape/backend/subtitles"
|
|
"git.quimbo.fr/odwrtw/canape/backend/web"
|
|
"github.com/gorilla/mux"
|
|
"github.com/odwrtw/papi"
|
|
polochon "github.com/odwrtw/polochon/lib"
|
|
)
|
|
|
|
// ErrPolochonUnavailable is an error returned if the polochon server is not available
|
|
var ErrPolochonUnavailable = fmt.Errorf("Invalid polochon address")
|
|
|
|
// GetDetailsHandler handles details of a show
|
|
func GetDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
vars := mux.Vars(r)
|
|
id := vars["id"]
|
|
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
client, err := user.NewPapiClient(env.Database)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
pShow, err := client.GetShow(id)
|
|
if err != nil && err != papi.ErrResourceNotFound {
|
|
log.Println("Got error getting show ", err)
|
|
}
|
|
|
|
wShow, err := models.IsShowWishlisted(env.Database, user.ID, id)
|
|
if err != nil && err != papi.ErrResourceNotFound {
|
|
log.Println("Got error getting wishlisted show ", err)
|
|
}
|
|
|
|
s := NewWithClient(&polochon.Show{ImdbID: id}, client, pShow, wShow, env.Config.PublicDir, env.Config.ImgURLPrefix)
|
|
// First try from the db
|
|
first := []polochon.Detailer{env.Backend.Detailer}
|
|
// Then try from the polochon detailers
|
|
detailers := env.Config.Show.Detailers
|
|
err = s.GetAndFetch(env, first, detailers)
|
|
if err != nil {
|
|
env.Log.Error(err)
|
|
return err
|
|
}
|
|
|
|
env.Log.Debug("getting episodes torrents")
|
|
for _, e := range s.Show.Episodes {
|
|
// Get torrents from the db
|
|
backend := []polochon.Torrenter{env.Backend.Torrenter}
|
|
err := GetTorrents(env, e, backend)
|
|
if err != nil {
|
|
env.Log.Error(err)
|
|
}
|
|
}
|
|
|
|
return env.RenderJSON(w, s)
|
|
}
|
|
|
|
// RefreshShowHandler refreshes details of a show + torrents
|
|
func RefreshShowHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
vars := mux.Vars(r)
|
|
id := vars["id"]
|
|
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
client, err := user.NewPapiClient(env.Database)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
pShow, err := client.GetShow(id)
|
|
if err != nil && err != papi.ErrResourceNotFound {
|
|
log.Println("Got error getting show ", err)
|
|
}
|
|
|
|
wShow, err := models.IsShowWishlisted(env.Database, user.ID, id)
|
|
if err != nil && err != papi.ErrResourceNotFound {
|
|
log.Println("Got error getting wishlisted show ", err)
|
|
}
|
|
|
|
s := NewWithClient(&polochon.Show{ImdbID: id}, client, pShow, wShow, env.Config.PublicDir, env.Config.ImgURLPrefix)
|
|
// Refresh the polochon detailers
|
|
detailers := env.Config.Show.Detailers
|
|
err = s.Refresh(env, detailers)
|
|
if err != nil {
|
|
env.Log.Error(err)
|
|
return err
|
|
}
|
|
|
|
env.Log.Debug("getting episodes torrents")
|
|
for _, e := range s.Episodes {
|
|
// Get torrents from the db
|
|
err := RefreshTorrents(env, e, env.Config.Show.Torrenters)
|
|
if err != nil {
|
|
env.Log.Error(err)
|
|
}
|
|
}
|
|
|
|
// Get everything from DB again
|
|
detailer := []polochon.Detailer{env.Backend.Detailer}
|
|
err = s.GetDetails(env, detailer)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
return env.RenderJSON(w, s)
|
|
}
|
|
|
|
// SearchShow will search a show
|
|
func SearchShow(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
vars := mux.Vars(r)
|
|
search := vars["search"]
|
|
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
var shows []*polochon.Show
|
|
searchers := env.Config.Show.Searchers
|
|
// Iterate on all the searchers to search for the show
|
|
for _, searcher := range searchers {
|
|
log := env.Log.WithField("searcher", searcher.Name())
|
|
result, err := searcher.SearchShow(search, log)
|
|
if err != nil {
|
|
log.Errorf("error while searching show : %s", err)
|
|
continue
|
|
}
|
|
log.Debug("found show")
|
|
// Add the results to the list of results
|
|
shows = append(shows, result...)
|
|
}
|
|
|
|
env.Log.Debugf("got %d shows doing search %q", len(shows), search)
|
|
|
|
client, err := user.NewPapiClient(env.Database)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
// Get the polochon's shows
|
|
pShows, err := client.GetShows()
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
// Get the user's wishlisted shows
|
|
wShows, err := models.GetShowWishlist(env.Database, user.ID)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
showList := []*Show{}
|
|
// Now iterate over all the shows to get details
|
|
for _, s := range shows {
|
|
pShow, _ := pShows.Has(s.ImdbID)
|
|
wShow, _ := wShows.IsShowInWishlist(s.ImdbID)
|
|
show := NewWithClient(s, client, pShow, wShow, env.Config.PublicDir, env.Config.ImgURLPrefix)
|
|
|
|
// First try from the db
|
|
first := []polochon.Detailer{env.Backend.Detailer}
|
|
// Then try from the polochon detailers
|
|
detailers := env.Config.Show.Detailers
|
|
err := show.GetAndFetch(env, first, detailers)
|
|
if err != nil {
|
|
env.Log.Error(err)
|
|
}
|
|
showList = append(showList, show)
|
|
}
|
|
|
|
return env.RenderJSON(w, showList)
|
|
}
|
|
|
|
// AddToWishlist adds a show to the user's wishlist
|
|
func AddToWishlist(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
vars := mux.Vars(r)
|
|
id := vars["id"]
|
|
|
|
var data struct {
|
|
Season int `json:"season"`
|
|
Episode int `json:"episode"`
|
|
}
|
|
if r.ContentLength > 0 {
|
|
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
|
return env.RenderError(w, errors.New("failed to get POST data season and episode "+err.Error()))
|
|
}
|
|
}
|
|
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
if err := models.AddShowToWishlist(env.Database, user.ID, id, data.Season, data.Episode); err != nil {
|
|
env.Log.Warnf("Error while adding to db : %s", err)
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
return env.RenderOK(w, "Show added to wishlist")
|
|
}
|
|
|
|
// DeleteFromWishlist deletes a show from the user's wishlist
|
|
func DeleteFromWishlist(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
vars := mux.Vars(r)
|
|
id := vars["id"]
|
|
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
if err := models.DeleteShowFromWishlist(env.Database, user.ID, id); err != nil {
|
|
env.Log.Warnf("Error while deleting to db : %s", err)
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
return env.RenderOK(w, "Show deleted from wishlist")
|
|
}
|
|
|
|
// GetWishlistHandler returns the tracked shows of a user
|
|
func GetWishlistHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
client, err := user.NewPapiClient(env.Database)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
// Get the polochon's shows
|
|
pShows, err := client.GetShows()
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
wShows, err := models.GetShowWishlist(env.Database, user.ID)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
showList := []*Show{}
|
|
for _, wishedShow := range wShows.List() {
|
|
pShow, _ := pShows.Has(wishedShow.ImdbID)
|
|
poloShow := &polochon.Show{ImdbID: wishedShow.ImdbID}
|
|
show := NewWithClient(poloShow, client, pShow, wishedShow, env.Config.PublicDir, env.Config.ImgURLPrefix)
|
|
|
|
// First check in the DB
|
|
before := []polochon.Detailer{env.Backend.Detailer}
|
|
// Then with the default detailers
|
|
after := env.Config.Show.Detailers
|
|
err := show.GetAndFetch(env, before, after)
|
|
if err != nil {
|
|
env.Log.Errorf("error while getting show details : %s", err)
|
|
continue
|
|
}
|
|
showList = append(showList, show)
|
|
}
|
|
|
|
return env.RenderJSON(w, showList)
|
|
}
|
|
|
|
// PolochonShowsHandler will returns shows from Polochon
|
|
func PolochonShowsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
// Get the polochon's shows
|
|
shows, err := getPolochonShows(env, user)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
// Get details in DB for each shows
|
|
// Fetch the details if not found
|
|
for _, s := range shows {
|
|
// First try from the db
|
|
first := []polochon.Detailer{env.Backend.Detailer}
|
|
// Then try from the polochon detailer
|
|
detailers := env.Config.Show.Detailers
|
|
err := s.GetAndFetch(env, first, detailers)
|
|
if err != nil {
|
|
env.Log.Error(err)
|
|
}
|
|
}
|
|
|
|
return env.RenderJSON(w, shows)
|
|
}
|
|
|
|
// RefreshEpisodeHandler refresh details of an episode
|
|
func RefreshEpisodeHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
vars := mux.Vars(r)
|
|
id := vars["id"]
|
|
|
|
// No need to check errors here as the router is making sure that season
|
|
// and episode are numbers
|
|
season, _ := strconv.Atoi(vars["season"])
|
|
episode, _ := strconv.Atoi(vars["episode"])
|
|
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
client, err := user.NewPapiClient(env.Database)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
pShow, err := client.GetShow(id)
|
|
if err != nil && err != papi.ErrResourceNotFound {
|
|
env.Log.Warnf("Error getting show %q", err)
|
|
}
|
|
|
|
s := &Show{
|
|
Show: &polochon.Show{ImdbID: id},
|
|
client: client,
|
|
pShow: pShow,
|
|
publicDir: env.Config.PublicDir,
|
|
imgURLPrefix: env.Config.ImgURLPrefix,
|
|
}
|
|
|
|
e := NewEpisode(s, season, episode)
|
|
// Refresh the episode
|
|
err = e.Refresh(env, env.Config.Show.Detailers)
|
|
if err != nil {
|
|
env.Log.Error(err)
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
// Refresh the torrents
|
|
err = e.RefreshTorrents(env, env.Config.Show.Torrenters)
|
|
if err != nil {
|
|
env.Log.Error(err)
|
|
}
|
|
|
|
// Get everything from DB again
|
|
detailer := []polochon.Detailer{env.Backend.Detailer}
|
|
err = e.GetEpisodeDetails(env, detailer)
|
|
if err != nil {
|
|
env.Log.Error(err)
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
return env.RenderJSON(w, e)
|
|
}
|
|
|
|
// RefreshEpisodeSubtitlesHandler refreshes details for an episode
|
|
func RefreshEpisodeSubtitlesHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
vars := mux.Vars(r)
|
|
id := vars["id"]
|
|
|
|
// No need to check errors here as the router is making sure that season
|
|
// and episode are numbers
|
|
season, _ := strconv.Atoi(vars["season"])
|
|
episode, _ := strconv.Atoi(vars["episode"])
|
|
|
|
// Get the user
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
// Create a new papi client
|
|
client, err := user.NewPapiClient(env.Database)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
e := &papi.Episode{
|
|
ShowImdbID: id,
|
|
Season: season,
|
|
Episode: episode,
|
|
}
|
|
|
|
refreshedSubs, err := client.UpdateSubtitles(e)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
subs := []subtitles.Subtitle{}
|
|
for _, lang := range refreshedSubs {
|
|
subtitleURL, _ := client.SubtitleURL(e, lang)
|
|
subs = append(subs, subtitles.Subtitle{
|
|
Language: lang,
|
|
URL: subtitleURL,
|
|
VVTFile: fmt.Sprintf("/shows/%s/seasons/%d/episodes/%d/subtitles/%s", e.ShowImdbID, e.Season, e.Episode, lang),
|
|
})
|
|
}
|
|
|
|
return env.RenderJSON(w, subs)
|
|
}
|
|
|
|
// DownloadVVTSubtitle returns a vvt subtitle for the movie
|
|
func DownloadVVTSubtitle(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
vars := mux.Vars(r)
|
|
id := vars["id"]
|
|
lang := vars["lang"]
|
|
season, _ := strconv.Atoi(vars["season"])
|
|
episode, _ := strconv.Atoi(vars["episode"])
|
|
|
|
// Get the user
|
|
user := auth.GetCurrentUser(r, env.Log)
|
|
|
|
// Create a new papi client
|
|
client, err := user.NewPapiClient(env.Database)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
url, err := client.SubtitleURL(&papi.Episode{
|
|
ShowImdbID: id,
|
|
Season: season,
|
|
Episode: episode,
|
|
}, lang)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
return subtitles.ConvertSubtitle(url, w)
|
|
}
|