433 lines
11 KiB
Go
433 lines
11 KiB
Go
package shows
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"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"
|
|
polochon "github.com/odwrtw/polochon/lib"
|
|
"github.com/odwrtw/polochon/lib/papi"
|
|
)
|
|
|
|
// 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 {
|
|
env.Log.Println("Got error getting show ", err)
|
|
}
|
|
|
|
wShow, err := models.IsShowWishlisted(env.Database, user.ID, id)
|
|
if err != nil && err != papi.ErrResourceNotFound {
|
|
env.Log.Println("Got error getting wishlisted show ", err)
|
|
}
|
|
|
|
s := NewWithClient(id, client, pShow, wShow)
|
|
// 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 {
|
|
env.Log.Println("Got error getting show ", err)
|
|
}
|
|
|
|
wShow, err := models.IsShowWishlisted(env.Database, user.ID, id)
|
|
if err != nil && err != papi.ErrResourceNotFound {
|
|
env.Log.Println("Got error getting wishlisted show ", err)
|
|
}
|
|
|
|
s := NewWithClient(id, client, pShow, wShow)
|
|
// 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.ImdbID, client, pShow, wShow)
|
|
|
|
// 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)
|
|
show := NewWithClient(wishedShow.ImdbID, client, pShow, wishedShow)
|
|
|
|
// 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)
|
|
}
|
|
|
|
if pShow == nil {
|
|
pShow = &papi.Show{Show: &polochon.Show{ImdbID: id}}
|
|
}
|
|
|
|
s := &Show{
|
|
Show: pShow.Show,
|
|
client: client,
|
|
pShow: pShow,
|
|
}
|
|
|
|
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"]
|
|
lang := polochon.Language(vars["lang"])
|
|
|
|
// 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{
|
|
ShowEpisode: &polochon.ShowEpisode{
|
|
ShowImdbID: id,
|
|
Season: season,
|
|
Episode: episode,
|
|
},
|
|
}
|
|
|
|
sub, err := client.UpdateSubtitle(e, lang)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
// TODO: handle this with a better error
|
|
if sub == nil {
|
|
return env.RenderJSON(w, nil)
|
|
}
|
|
|
|
url, err := client.DownloadURL(sub)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
s := &subtitles.Subtitle{
|
|
Subtitle: sub.Subtitle,
|
|
URL: url,
|
|
VVTFile: fmt.Sprintf("/shows/%s/seasons/%d/episodes/%d/subtitles/%s", e.ShowImdbID, e.Season, e.Episode, lang),
|
|
}
|
|
|
|
return env.RenderJSON(w, s)
|
|
}
|
|
|
|
// 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 := polochon.Language(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)
|
|
}
|
|
|
|
s := &papi.Subtitle{
|
|
Subtitle: &polochon.Subtitle{
|
|
Video: &papi.Episode{
|
|
ShowEpisode: &polochon.ShowEpisode{
|
|
ShowImdbID: id,
|
|
Season: season,
|
|
Episode: episode,
|
|
},
|
|
},
|
|
Lang: lang,
|
|
},
|
|
}
|
|
|
|
url, err := client.DownloadURLWithToken(s)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
return subtitles.ConvertSubtitle(url, w)
|
|
}
|