diff --git a/backend/external_medias/handlers.go b/backend/external_medias/handlers.go index 0a72c6c..cfd4a42 100644 --- a/backend/external_medias/handlers.go +++ b/backend/external_medias/handlers.go @@ -141,7 +141,7 @@ func GetShows(env *web.Env, user *models.User, source string, category string, f for _, id := range media.IDs { pShow, _ := pShows.Has(id) wShow, _ := wShows.IsShowInWishlist(id) - show := shows.NewWithClient(&polochon.Show{ImdbID: id}, client, pShow, wShow) + show := shows.NewWithClient(id, client, pShow, wShow) // First check in the DB before := []polochon.Detailer{env.Backend.Detailer} diff --git a/backend/movies/handlers.go b/backend/movies/handlers.go index 7fe76a2..f7b8526 100644 --- a/backend/movies/handlers.go +++ b/backend/movies/handlers.go @@ -283,6 +283,7 @@ func GetWishlistHandler(env *web.Env, w http.ResponseWriter, r *http.Request) er func RefreshMovieSubtitlesHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error { vars := mux.Vars(r) id := vars["id"] + lang := polochon.Language(vars["lang"]) // Get the user user := auth.GetCurrentUser(r, env.Log) @@ -294,29 +295,35 @@ func RefreshMovieSubtitlesHandler(env *web.Env, w http.ResponseWriter, r *http.R } movie := &papi.Movie{Movie: &polochon.Movie{ImdbID: id}} - refreshSubs, err := client.UpdateSubtitles(movie) + sub, err := client.UpdateSubtitle(movie, lang) if err != nil { return env.RenderError(w, err) } - subs := []subtitles.Subtitle{} - for _, lang := range refreshSubs { - subtitleURL, _ := client.SubtitleURL(movie, lang) - subs = append(subs, subtitles.Subtitle{ - Language: lang, - URL: subtitleURL, - VVTFile: fmt.Sprintf("/movies/%s/subtitles/%s", id, lang), - }) + // TODO: handle this with a better error + if sub == nil { + return env.RenderJSON(w, nil) } - return env.RenderJSON(w, subs) + url, err := client.DownloadURLWithToken(sub) + if err != nil { + return env.RenderError(w, err) + } + + s := &subtitles.Subtitle{ + Subtitle: sub.Subtitle, + URL: url, + VVTFile: fmt.Sprintf("/movies/%s/subtitles/%s", id, sub.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 := vars["lang"] + lang := polochon.Language(vars["lang"]) // Get the user user := auth.GetCurrentUser(r, env.Log) @@ -327,7 +334,14 @@ func DownloadVVTSubtitle(env *web.Env, w http.ResponseWriter, r *http.Request) e return env.RenderError(w, err) } - url, err := client.SubtitleURL(&papi.Movie{Movie: &polochon.Movie{ImdbID: id}}, lang) + s := &papi.Subtitle{ + Subtitle: &polochon.Subtitle{ + Video: &papi.Movie{Movie: &polochon.Movie{ImdbID: id}}, + Lang: lang, + }, + } + + url, err := client.DownloadURLWithToken(s) if err != nil { return env.RenderError(w, err) } diff --git a/backend/movies/movies.go b/backend/movies/movies.go index 9a53ea6..8d57759 100644 --- a/backend/movies/movies.go +++ b/backend/movies/movies.go @@ -48,7 +48,7 @@ func (m *Movie) MarshalJSON() ([]byte, error) { if m.pMovie != nil { // Get the DownloadURL - movieToMarshal.PolochonURL, _ = m.client.DownloadURL(m.pMovie) + movieToMarshal.PolochonURL, _ = m.client.DownloadURLWithToken(m.pMovie) // Get the metadata movieToMarshal.DateAdded = m.pMovie.DateAdded @@ -58,13 +58,14 @@ func (m *Movie) MarshalJSON() ([]byte, error) { movieToMarshal.Container = m.pMovie.Container // Append the Subtitles - for _, l := range m.pMovie.Subtitles { - subtitleURL, _ := m.client.SubtitleURL(m.pMovie, l) - movieToMarshal.Subtitles = append(movieToMarshal.Subtitles, subtitles.Subtitle{ - Language: l, - URL: subtitleURL, - VVTFile: fmt.Sprintf("/movies/%s/subtitles/%s", m.ImdbID, l), - }) + for _, s := range m.pMovie.Subtitles { + subtitleURL, _ := m.client.DownloadURLWithToken(s) + movieToMarshal.Subtitles = append(movieToMarshal.Subtitles, + subtitles.Subtitle{ + Subtitle: s.Subtitle, + URL: subtitleURL, + VVTFile: fmt.Sprintf("/movies/%s/subtitles/%s", m.ImdbID, s.Lang), + }) } } @@ -73,13 +74,18 @@ func (m *Movie) MarshalJSON() ([]byte, error) { // New returns a new Movie with all the needed infos func New(imdbID string, client *papi.Client, pMovie *papi.Movie, isWishlisted bool) *Movie { + var m *polochon.Movie + if pMovie != nil && pMovie.Movie != nil { + m = pMovie.Movie + } else { + m = &polochon.Movie{ImdbID: imdbID} + } + return &Movie{ client: client, pMovie: pMovie, Wishlisted: isWishlisted, - Movie: &polochon.Movie{ - ImdbID: imdbID, - }, + Movie: m, } } diff --git a/backend/routes.go b/backend/routes.go index 2f9303d..ddc819d 100644 --- a/backend/routes.go +++ b/backend/routes.go @@ -43,7 +43,7 @@ func setupRoutes(env *web.Env) { env.Handle("/movies/{id:tt[0-9]+}", movies.PolochonDeleteHandler).WithRole(models.UserRole).Methods("DELETE") env.Handle("/movies/{id:tt[0-9]+}/refresh", movies.RefreshMovieHandler).WithRole(models.UserRole).Methods("POST") env.Handle("/movies/{id:tt[0-9]+}/subtitles/{lang}", movies.DownloadVVTSubtitle).WithRole(models.UserRole).Methods("GET") - env.Handle("/movies/{id:tt[0-9]+}/subtitles/refresh", movies.RefreshMovieSubtitlesHandler).WithRole(models.UserRole).Methods("POST") + env.Handle("/movies/{id:tt[0-9]+}/subtitles/{lang}", movies.RefreshMovieSubtitlesHandler).WithRole(models.UserRole).Methods("POST") env.Handle("/movies/refresh", extmedias.RefreshMoviesHandler).WithRole(models.AdminRole).Methods("POST") // Shows routes @@ -54,7 +54,7 @@ func setupRoutes(env *web.Env) { env.Handle("/shows/{id:tt[0-9]+}", shows.GetDetailsHandler).WithRole(models.UserRole).Methods("GET") env.Handle("/shows/{id:tt[0-9]+}/refresh", shows.RefreshShowHandler).WithRole(models.UserRole).Methods("POST") env.Handle("/shows/{id:tt[0-9]+}/seasons/{season:[0-9]+}/episodes/{episode:[0-9]+}", shows.RefreshEpisodeHandler).WithRole(models.UserRole).Methods("POST") - env.Handle("/shows/{id:tt[0-9]+}/seasons/{season:[0-9]+}/episodes/{episode:[0-9]+}/subtitles/refresh", shows.RefreshEpisodeSubtitlesHandler).WithRole(models.UserRole).Methods("POST") + env.Handle("/shows/{id:tt[0-9]+}/seasons/{season:[0-9]+}/episodes/{episode:[0-9]+}/subtitles/{lang}", shows.RefreshEpisodeSubtitlesHandler).WithRole(models.UserRole).Methods("POST") env.Handle("/shows/{id:tt[0-9]+}/seasons/{season:[0-9]+}/episodes/{episode:[0-9]+}/subtitles/{lang}", shows.DownloadVVTSubtitle).WithRole(models.UserRole).Methods("GET") env.Handle("/shows/refresh", extmedias.RefreshShowsHandler).WithRole(models.AdminRole).Methods("POST") diff --git a/backend/shows/episodes.go b/backend/shows/episodes.go index 2a7b9cd..43b2ca6 100644 --- a/backend/shows/episodes.go +++ b/backend/shows/episodes.go @@ -3,7 +3,6 @@ package shows import ( "encoding/json" "fmt" - "time" "git.quimbo.fr/odwrtw/canape/backend/models" "git.quimbo.fr/odwrtw/canape/backend/subtitles" @@ -26,18 +25,13 @@ func (e *Episode) MarshalJSON() ([]byte, error) { var downloadURL string var subs []subtitles.Subtitle - var dateAdded time.Time - var quality string - var audioCodec string - var videoCodec string - var container string // If the episode is present, fill the downloadURL if e.show.pShow != nil { pEpisode := e.show.pShow.GetEpisode(e.Season, e.Episode) if pEpisode != nil { // Get the DownloadURL - downloadURL, _ = e.show.client.DownloadURL( + downloadURL, _ = e.show.client.DownloadURLWithToken( &papi.Episode{ ShowEpisode: &polochon.ShowEpisode{ ShowImdbID: e.ShowImdbID, @@ -46,19 +40,20 @@ func (e *Episode) MarshalJSON() ([]byte, error) { }, }, ) - dateAdded = pEpisode.DateAdded - quality = string(pEpisode.Quality) - audioCodec = pEpisode.AudioCodec - videoCodec = pEpisode.VideoCodec - container = pEpisode.Container + + e.ShowEpisode.VideoMetadata = pEpisode.ShowEpisode.VideoMetadata + e.ShowEpisode.File = pEpisode.ShowEpisode.File // Append the Subtitles - for _, l := range pEpisode.Subtitles { - subtitleURL, _ := e.show.client.SubtitleURL(pEpisode, l) + for _, s := range pEpisode.Subtitles { + subtitleURL, _ := e.show.client.DownloadURLWithToken(s) subs = append(subs, subtitles.Subtitle{ - Language: l, - URL: subtitleURL, - VVTFile: fmt.Sprintf("/shows/%s/seasons/%d/episodes/%d/subtitles/%s", e.ShowImdbID, e.Season, e.Episode, l), + Subtitle: &polochon.Subtitle{ + File: polochon.File{Size: s.Size}, + Lang: s.Lang, + }, + URL: subtitleURL, + VVTFile: fmt.Sprintf("/shows/%s/seasons/%d/episodes/%d/subtitles/%s", e.ShowImdbID, e.Season, e.Episode, s.Lang), }) } } @@ -69,21 +64,11 @@ func (e *Episode) MarshalJSON() ([]byte, error) { *alias PolochonURL string `json:"polochon_url"` Subtitles []subtitles.Subtitle `json:"subtitles"` - DateAdded time.Time `json:"date_added"` - Quality string `json:"quality"` - AudioCodec string `json:"audio_codec"` - VideoCodec string `json:"video_codec"` - Container string `json:"container"` Thumb string `json:"thumb"` }{ alias: (*alias)(e), PolochonURL: downloadURL, Subtitles: subs, - DateAdded: dateAdded, - Quality: quality, - AudioCodec: audioCodec, - VideoCodec: videoCodec, - Container: container, Thumb: e.Thumb, } diff --git a/backend/shows/handlers.go b/backend/shows/handlers.go index 1d3eca5..3ee5405 100644 --- a/backend/shows/handlers.go +++ b/backend/shows/handlers.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "log" "strconv" "net/http" @@ -35,15 +34,15 @@ func GetDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) err pShow, err := client.GetShow(id) if err != nil && err != papi.ErrResourceNotFound { - log.Println("Got error getting show ", err) + env.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) + env.Log.Println("Got error getting wishlisted show ", err) } - s := NewWithClient(&polochon.Show{ImdbID: id}, client, pShow, wShow) + s := NewWithClient(id, client, pShow, wShow) // First try from the db first := []polochon.Detailer{env.Backend.Detailer} // Then try from the polochon detailers @@ -81,15 +80,15 @@ func RefreshShowHandler(env *web.Env, w http.ResponseWriter, r *http.Request) er pShow, err := client.GetShow(id) if err != nil && err != papi.ErrResourceNotFound { - log.Println("Got error getting show ", err) + env.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) + env.Log.Println("Got error getting wishlisted show ", err) } - s := NewWithClient(&polochon.Show{ImdbID: id}, client, pShow, wShow) + s := NewWithClient(id, client, pShow, wShow) // Refresh the polochon detailers detailers := env.Config.Show.Detailers err = s.Refresh(env, detailers) @@ -163,7 +162,7 @@ func SearchShow(env *web.Env, w http.ResponseWriter, r *http.Request) error { for _, s := range shows { pShow, _ := pShows.Has(s.ImdbID) wShow, _ := wShows.IsShowInWishlist(s.ImdbID) - show := NewWithClient(s, client, pShow, wShow) + show := NewWithClient(s.ImdbID, client, pShow, wShow) // First try from the db first := []polochon.Detailer{env.Backend.Detailer} @@ -242,8 +241,7 @@ func GetWishlistHandler(env *web.Env, w http.ResponseWriter, r *http.Request) er showList := []*Show{} for _, wishedShow := range wShows.List() { pShow, _ := pShows.Has(wishedShow.ImdbID) - poloShow := &polochon.Show{ImdbID: wishedShow.ImdbID} - show := NewWithClient(poloShow, client, pShow, wishedShow) + show := NewWithClient(wishedShow.ImdbID, client, pShow, wishedShow) // First check in the DB before := []polochon.Detailer{env.Backend.Detailer} @@ -309,7 +307,7 @@ func RefreshEpisodeHandler(env *web.Env, w http.ResponseWriter, r *http.Request) } s := &Show{ - Show: &polochon.Show{ImdbID: id}, + Show: pShow.Show, client: client, pShow: pShow, } @@ -343,6 +341,7 @@ func RefreshEpisodeHandler(env *web.Env, w http.ResponseWriter, r *http.Request) 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 @@ -366,29 +365,35 @@ func RefreshEpisodeSubtitlesHandler(env *web.Env, w http.ResponseWriter, r *http }, } - refreshedSubs, err := client.UpdateSubtitles(e) + sub, err := client.UpdateSubtitle(e, lang) 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), - }) + // TODO: handle this with a better error + if sub == nil { + return env.RenderJSON(w, nil) } - return env.RenderJSON(w, subs) + 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 := vars["lang"] + lang := polochon.Language(vars["lang"]) season, _ := strconv.Atoi(vars["season"]) episode, _ := strconv.Atoi(vars["episode"]) @@ -401,13 +406,20 @@ func DownloadVVTSubtitle(env *web.Env, w http.ResponseWriter, r *http.Request) e return env.RenderError(w, err) } - url, err := client.SubtitleURL(&papi.Episode{ - ShowEpisode: &polochon.ShowEpisode{ - ShowImdbID: id, - Season: season, - Episode: episode, + s := &papi.Subtitle{ + Subtitle: &polochon.Subtitle{ + Video: &papi.Episode{ + ShowEpisode: &polochon.ShowEpisode{ + ShowImdbID: id, + Season: season, + Episode: episode, + }, + }, + Lang: lang, }, - }, lang) + } + + url, err := client.DownloadURLWithToken(s) if err != nil { return env.RenderError(w, err) } diff --git a/backend/shows/shows.go b/backend/shows/shows.go index aa14690..1a370c0 100644 --- a/backend/shows/shows.go +++ b/backend/shows/shows.go @@ -62,7 +62,14 @@ func New(imdbID string) *Show { } // NewWithClient returns a new Show with a polochon ShowConfig -func NewWithClient(show *polochon.Show, client *papi.Client, pShow *papi.Show, wShow *models.WishedShow) *Show { +func NewWithClient(imdbID string, client *papi.Client, pShow *papi.Show, wShow *models.WishedShow) *Show { + var show *polochon.Show + if pShow == nil || pShow.Show == nil { + show = &polochon.Show{ImdbID: imdbID} + } else { + show = pShow.Show + } + s := &Show{ Show: show, client: client, @@ -252,7 +259,7 @@ func getPolochonShows(env *web.Env, user *models.User) ([]*Show, error) { // Create Shows objects from the shows retrieved for _, pShow := range pshows.List() { wShow, _ := wShows.IsShowInWishlist(pShow.ImdbID) - show := NewWithClient(&polochon.Show{ImdbID: pShow.ImdbID}, client, pShow, wShow) + show := NewWithClient(pShow.ImdbID, client, pShow, wShow) shows = append(shows, show) } return shows, nil diff --git a/backend/subtitles/subtitles.go b/backend/subtitles/subtitles.go index e5a4127..c8a5771 100644 --- a/backend/subtitles/subtitles.go +++ b/backend/subtitles/subtitles.go @@ -1,8 +1,10 @@ package subtitles +import polochon "github.com/odwrtw/polochon/lib" + // Subtitle represents a Subtitle type Subtitle struct { - Language string `json:"language"` - URL string `json:"url"` - VVTFile string `json:"vvt_file"` + *polochon.Subtitle + URL string `json:"url"` + VVTFile string `json:"vvt_file"` } diff --git a/frontend/js/actions/subtitles.js b/frontend/js/actions/subtitles.js index 6460791..6e95a78 100644 --- a/frontend/js/actions/subtitles.js +++ b/frontend/js/actions/subtitles.js @@ -1,24 +1,25 @@ import { configureAxios, request } from "../requests"; -export const searchMovieSubtitles = (imdbId) => { +export const searchMovieSubtitle = (imdbId, lang) => { return request( "MOVIE_SUBTITLES_UPDATE", - configureAxios().post(`/movies/${imdbId}/subtitles/refresh`), + configureAxios().post(`/movies/${imdbId}/subtitles/${lang}`), null, - { imdbId: imdbId } + { imdbId, lang } ); }; -export const searchEpisodeSubtitles = (imdbId, season, episode) => { +export const searchEpisodeSubtitle = (imdbId, season, episode, lang) => { const url = `/shows/${imdbId}/seasons/${season}/episodes/${episode}`; return request( "EPISODE_SUBTITLES_UPDATE", - configureAxios().post(`${url}/subtitles/refresh`), + configureAxios().post(`${url}/subtitles/${lang}`), null, { - imdbId: imdbId, - season: season, - episode: episode, + imdbId, + season, + episode, + lang, } ); }; diff --git a/frontend/js/components/buttons/download.js b/frontend/js/components/buttons/download.js index f3025c5..664efe9 100644 --- a/frontend/js/components/buttons/download.js +++ b/frontend/js/components/buttons/download.js @@ -18,7 +18,7 @@ export const DownloadAndStream = ({ url, name, subtitles }) => { DownloadAndStream.propTypes = { url: PropTypes.string, name: PropTypes.string, - subtitles: PropTypes.array, + subtitles: PropTypes.object, }; const DownloadButton = ({ url }) => ( @@ -67,30 +67,29 @@ const StreamButton = ({ name, url, subtitles }) => { StreamButton.propTypes = { name: PropTypes.string.isRequired, url: PropTypes.string.isRequired, - subtitles: PropTypes.array, + subtitles: PropTypes.object, }; const Player = ({ url, subtitles }) => { - const subs = subtitles || []; - return (