336 lines
8.7 KiB
Go
336 lines
8.7 KiB
Go
package shows
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
|
|
"github.com/gorilla/mux"
|
|
customError "github.com/odwrtw/errors"
|
|
"github.com/odwrtw/papi"
|
|
polochon "github.com/odwrtw/polochon/lib"
|
|
"github.com/odwrtw/polochon/modules/pam"
|
|
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/auth"
|
|
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/config"
|
|
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/users"
|
|
"gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/web"
|
|
)
|
|
|
|
// ErrPolochonUnavailable is an error returned if the polochon server is not available
|
|
var ErrPolochonUnavailable = fmt.Errorf("Invalid polochon address")
|
|
|
|
// GetDetailsHandler retrieves details of a show
|
|
func GetDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
return DetailsHandler(env, w, r, false)
|
|
}
|
|
|
|
// RefreahDetailsHandler refresh details of a show
|
|
func RefreshDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
return DetailsHandler(env, w, r, true)
|
|
}
|
|
|
|
// DetailsHandler handles details of an episode
|
|
func DetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request, force bool) error {
|
|
vars := mux.Vars(r)
|
|
id := vars["id"]
|
|
|
|
v := auth.GetCurrentUser(r, env.Log)
|
|
user, ok := v.(*users.User)
|
|
if !ok {
|
|
return env.RenderError(w, errors.New("invalid user type"))
|
|
}
|
|
|
|
s := New(id)
|
|
if err := s.GetDetails(env, user, force); err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
if err := s.GetEpisodes(env, force); err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
// Get the show from the polochon of the user
|
|
pShow, err := getPolochonShow(user, s.ImdbID)
|
|
if err != nil {
|
|
env.Log.Warnf("error while getting polochon show %s : %s", s.ImdbID, err)
|
|
}
|
|
// For each of the user's polochon episodes, add a direct link to it
|
|
for _, pEpisode := range pShow.Episodes {
|
|
for _, e := range s.Episodes {
|
|
if e.Season != pEpisode.Season || e.Episode != pEpisode.Episode {
|
|
continue
|
|
}
|
|
e.PolochonURL = pEpisode.PolochonURL
|
|
}
|
|
}
|
|
|
|
return env.RenderJSON(w, s)
|
|
}
|
|
|
|
// SearchShow will search a show
|
|
func SearchShow(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
var data struct {
|
|
Key string `json:"key"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
|
return env.RenderError(w, errors.New("failed to get the search key"))
|
|
}
|
|
|
|
if data.Key == "" {
|
|
return env.RenderError(w, errors.New("no given key"))
|
|
}
|
|
|
|
v := auth.GetCurrentUser(r, env.Log)
|
|
user, ok := v.(*users.User)
|
|
if !ok {
|
|
return env.RenderError(w, errors.New("invalid user type"))
|
|
}
|
|
|
|
var shows []*polochon.Show
|
|
searchers := env.Config.ShowSearchers
|
|
for _, searcher := range searchers {
|
|
result, err := searcher.SearchShow(data.Key, env.Log)
|
|
if err != nil {
|
|
env.Log.Errorf("error while searching show : %s", err)
|
|
continue
|
|
}
|
|
shows = append(shows, result...)
|
|
}
|
|
|
|
env.Log.Debugf("got %d shows doing search %q", len(shows), data.Key)
|
|
showList := []*Show{}
|
|
for _, s := range shows {
|
|
show := New(s.ImdbID)
|
|
err := show.GetDetails(env, user, false)
|
|
if err != nil {
|
|
env.Log.Errorf("error while getting show details : %s", err)
|
|
continue
|
|
}
|
|
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()))
|
|
}
|
|
}
|
|
|
|
v := auth.GetCurrentUser(r, env.Log)
|
|
user, ok := v.(*users.User)
|
|
if !ok {
|
|
return env.RenderError(w, errors.New("invalid user type"))
|
|
}
|
|
|
|
s := New(id)
|
|
if err := s.AddToWishlist(env, user, 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"]
|
|
|
|
v := auth.GetCurrentUser(r, env.Log)
|
|
user, ok := v.(*users.User)
|
|
if !ok {
|
|
return env.RenderError(w, errors.New("invalid user type"))
|
|
}
|
|
|
|
s := New(id)
|
|
if err := s.DeleteFromWishlist(env, user); 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 {
|
|
v := auth.GetCurrentUser(r, env.Log)
|
|
user, ok := v.(*users.User)
|
|
if !ok {
|
|
return env.RenderError(w, errors.New("invalid user type"))
|
|
}
|
|
|
|
shows, err := GetWishlist(env, user)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
return env.RenderJSON(w, shows)
|
|
}
|
|
|
|
// getPolochonShows returns all the Shows from the polochon of a user
|
|
func getPolochonShows(user *users.User) ([]*Show, error) {
|
|
shows := []*Show{}
|
|
|
|
var polochonConfig config.UserPolochon
|
|
err := user.GetConfig("polochon", &polochonConfig)
|
|
if err != nil {
|
|
return shows, err
|
|
}
|
|
|
|
client, err := papi.New(polochonConfig.URL)
|
|
if err != nil {
|
|
return shows, err
|
|
}
|
|
|
|
if polochonConfig.Token != "" {
|
|
client.SetToken(polochonConfig.Token)
|
|
}
|
|
|
|
pshows, err := client.GetShows()
|
|
if err != nil {
|
|
// Catch network error for accessing specified polochon address
|
|
if uerr, ok := err.(*url.Error); ok {
|
|
if nerr, ok := uerr.Err.(*net.OpError); ok {
|
|
if nerr.Op == "dial" {
|
|
return shows, ErrPolochonUnavailable
|
|
}
|
|
|
|
}
|
|
}
|
|
return shows, err
|
|
}
|
|
for _, pshow := range pshows {
|
|
show := New(pshow.ImdbID)
|
|
for _, season := range pshow.Seasons {
|
|
for _, episode := range season.Episodes {
|
|
e := NewEpisode()
|
|
e.Season = episode.Season
|
|
e.Episode = episode.Episode
|
|
e.ShowImdbID = episode.ShowImdbID
|
|
e.PolochonURL, _ = client.DownloadURL(
|
|
&papi.Episode{
|
|
ShowImdbID: show.ImdbID,
|
|
Episode: e.Episode,
|
|
Season: e.Season,
|
|
},
|
|
)
|
|
|
|
show.Episodes = append(show.Episodes, e)
|
|
}
|
|
}
|
|
shows = append(shows, show)
|
|
}
|
|
return shows, nil
|
|
}
|
|
|
|
// getPolochonShow returns a Show with its epidodes from the polochon of a user
|
|
func getPolochonShow(user *users.User, imdbID string) (Show, error) {
|
|
shows, err := getPolochonShows(user)
|
|
if err != nil {
|
|
return Show{}, err
|
|
}
|
|
for _, s := range shows {
|
|
if s.ImdbID == imdbID {
|
|
return *s, nil
|
|
}
|
|
}
|
|
return Show{}, nil
|
|
}
|
|
|
|
// FromPolochon will returns shows from Polochon
|
|
func FromPolochon(env *web.Env, w http.ResponseWriter, r *http.Request) error {
|
|
v := auth.GetCurrentUser(r, env.Log)
|
|
user, ok := v.(*users.User)
|
|
if !ok {
|
|
return env.RenderError(w, errors.New("invalid user type"))
|
|
}
|
|
|
|
shows, err := getPolochonShows(user)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
var polochonConfig config.UserPolochon
|
|
err = user.GetConfig("polochon", &polochonConfig)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
detailer, err := pam.New(&pam.Params{
|
|
Endpoint: polochonConfig.URL,
|
|
Token: polochonConfig.Token,
|
|
})
|
|
|
|
for _, s := range shows {
|
|
s.Detailers = []polochon.Detailer{detailer}
|
|
err := s.GetDetails(env, user, false)
|
|
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 {
|
|
return EpisodeDetailsHandler(env, w, r, true)
|
|
}
|
|
|
|
// EpisodeDetailsHandler handles details of a show
|
|
func EpisodeDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request, force bool) 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"])
|
|
|
|
v := auth.GetCurrentUser(r, env.Log)
|
|
user, ok := v.(*users.User)
|
|
if !ok {
|
|
return env.RenderError(w, errors.New("invalid user type"))
|
|
}
|
|
|
|
s := New(id)
|
|
e, err := s.GetEpisodeDetails(env, season, episode, force)
|
|
if err != nil {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
err = e.GetTorrents(env, force)
|
|
if err != nil && customError.IsFatal(err) {
|
|
return env.RenderError(w, err)
|
|
}
|
|
|
|
// Get the show from the polochon of the user
|
|
pShow, err := getPolochonShow(user, id)
|
|
if err != nil {
|
|
env.Log.Warnf("error while getting polochon episode %s S%02dE%02d : %s", id, season, episode, err)
|
|
}
|
|
// Find if the user has a the episode in its polochon to add the
|
|
// DownloadURL
|
|
for _, pEpisode := range pShow.Episodes {
|
|
if e.Season == pEpisode.Season && e.Episode == pEpisode.Episode {
|
|
e.PolochonURL = pEpisode.PolochonURL
|
|
break
|
|
}
|
|
}
|
|
|
|
return env.RenderJSON(w, e)
|
|
}
|