func getMovieById(movieId string, language string) *Movie { var movie *Movie cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tmdb.movie.%s.%s", movieId, language) if err := cacheStore.Get(key, &movie); err != nil { rateLimiter.Call(func() { urlValues := napping.Params{ "api_key": apiKey, "append_to_response": "credits,images,alternative_titles,translations,external_ids,trailers", "language": language, }.AsUrlValues() napping.Get( tmdbEndpoint+"movie/"+movieId, &urlValues, &movie, nil, ) if movie != nil { cacheStore.Set(key, movie, cacheTime) } }) } if movie == nil { return nil } switch t := movie.RawPopularity.(type) { case string: popularity, _ := strconv.ParseFloat(t, 64) movie.Popularity = popularity case float64: movie.Popularity = t } return movie }
func GetSeason(showId int, seasonNumber int, language string) *Season { var season *Season cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tmdb.season.%d.%d.%s", showId, seasonNumber, language) if err := cacheStore.Get(key, &season); err != nil { rateLimiter.Call(func() { urlValues := napping.Params{ "api_key": apiKey, "append_to_response": "credits,images,videos,external_ids", "language": language, }.AsUrlValues() resp, err := napping.Get( fmt.Sprintf("%stv/%d/season/%d", tmdbEndpoint, showId, seasonNumber), &urlValues, &season, nil, ) if err != nil { panic(err) } if resp.Status() != 200 { panic(errors.New(fmt.Sprintf("Bad status: %d", resp.Status()))) } }) season.EpisodeCount = len(season.Episodes) if season != nil { cacheStore.Set(key, season, cacheTime) } } if season == nil { return nil } return season }
func GetShow(showId int, language string) *Show { var show *Show cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tmdb.show.%d.%s", showId, language) if err := cacheStore.Get(key, &show); err != nil { rateLimiter.Call(func() { urlValues := napping.Params{ "api_key": apiKey, "append_to_response": "credits,images,alternative_titles,translations,external_ids", "language": language, }.AsUrlValues() napping.Get( tmdbEndpoint+"tv/"+strconv.Itoa(showId), &urlValues, &show, nil, ) }) if show != nil { cacheStore.Set(key, show, cacheTime) } } if show == nil { return nil } switch t := show.RawPopularity.(type) { case string: if popularity, err := strconv.ParseFloat(t, 64); err == nil { show.Popularity = popularity } case float64: show.Popularity = t } return show }
func Find(externalId string, externalSource string) *FindResult { var result *FindResult cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tmdb.find.%s.%s", externalSource, externalId) if err := cacheStore.Get(key, &result); err != nil { rateLimiter.Call(func() { urlValues := napping.Params{ "api_key": apiKey, "external_source": externalSource, }.AsUrlValues() resp, err := napping.Get( tmdbEndpoint+"find/"+externalId, &urlValues, &result, nil, ) if err != nil { panic(err) } if resp.Status() != 200 { panic(errors.New(fmt.Sprintf("Bad status: %d", resp.Status()))) } cacheStore.Set(key, result, 365*24*time.Hour) }) } return result }
func Find(externalId string, externalSource string) *FindResult { var result *FindResult cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tmdb.find.%s.%s", externalSource, externalId) if err := cacheStore.Get(key, &result); err != nil { rateLimiter.Call(func() { urlValues := napping.Params{ "api_key": apiKey, "external_source": externalSource, }.AsUrlValues() resp, err := napping.Get( tmdbEndpoint+"find/"+externalId, &urlValues, &result, nil, ) if err != nil { log.Error(err.Error()) xbmc.Notify("Quasar", "Failed Find call, check your logs.", config.AddonIcon()) } else if resp.Status() != 200 { message := fmt.Sprintf("Find call bad status: %d", resp.Status()) log.Error(message) xbmc.Notify("Quasar", message, config.AddonIcon()) } cacheStore.Set(key, result, 365*24*time.Hour) }) } return result }
func GetShow(showId int, language string) *Show { var show *Show cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tmdb.show.%d.%s", showId, language) if err := cacheStore.Get(key, &show); err != nil { rateLimiter.Call(func() { urlValues := napping.Params{ "api_key": apiKey, "append_to_response": "credits,images,alternative_titles,translations,external_ids", "language": language, }.AsUrlValues() resp, err := napping.Get( tmdbEndpoint+"tv/"+strconv.Itoa(showId), &urlValues, &show, nil, ) if err != nil { switch e := err.(type) { case *json.UnmarshalTypeError: log.Errorf("UnmarshalTypeError: Value[%s] Type[%v] Offset[%d] for %d", e.Value, e.Type, e.Offset, showId) case *json.InvalidUnmarshalError: log.Errorf("InvalidUnmarshalError: Type[%v]", e.Type) default: log.Error(err.Error()) } LogError(err) xbmc.Notify("Quasar", "GetShow failed, check your logs.", config.AddonIcon()) } else if resp.Status() != 200 { message := fmt.Sprintf("GetShow bad status: %d", resp.Status()) log.Error(message) xbmc.Notify("Quasar", message, config.AddonIcon()) } }) if show != nil { cacheStore.Set(key, show, cacheTime) } } if show == nil { return nil } switch t := show.RawPopularity.(type) { case string: if popularity, err := strconv.ParseFloat(t, 64); err == nil { show.Popularity = popularity } case float64: show.Popularity = t } return show }
func GetSeason(showId int, seasonNumber int, language string) *Season { var season *Season cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tmdb.season.%d.%d.%s", showId, seasonNumber, language) if err := cacheStore.Get(key, &season); err != nil { rateLimiter.Call(func() { urlValues := napping.Params{ "api_key": apiKey, "append_to_response": "credits,images,videos,external_ids", "language": language, }.AsUrlValues() resp, err := napping.Get( fmt.Sprintf("%stv/%d/season/%d", tmdbEndpoint, showId, seasonNumber), &urlValues, &season, nil, ) if err != nil { log.Error(err.Error()) xbmc.Notify("Quasar", err.Error(), config.AddonIcon()) } else if resp.Status() != 200 { message := fmt.Sprintf("GetSeason bad status: %d", resp.Status()) log.Error(message) xbmc.Notify("Quasar", message, config.AddonIcon()) } }) season.EpisodeCount = len(season.Episodes) // Fix for shows that have translations but return empty strings // for episode names and overviews. // We detect if episodes have their name filled, and if not re-query // with no language set. // See https://github.com/scakemyer/plugin.video.quasar/issues/249 if season.EpisodeCount > 0 { for index := 0; index < season.EpisodeCount; index++ { if season.Episodes[index].Name == "" { season.Episodes[index] = GetEpisode(showId, seasonNumber, index+1, "") } } } if season != nil { cacheStore.Set(key, season, cacheTime) } } if season == nil { return nil } return season }
func NewShowCached(tvdbId string, language string) (*Show, error) { var show *Show cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tvdb.show.%s.%s", tvdbId, language) if err := cacheStore.Get(key, &show); err != nil { newShow, err := NewShow(tvdbId, language) if err != nil { return nil, err } if newShow != nil { cacheStore.Set(key, newShow, cacheTime) } show = newShow } return show, nil }
func GetMovieById(movieId string, language string) *Movie { var movie *Movie cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tmdb.movie.%s.%s", movieId, language) if err := cacheStore.Get(key, &movie); err != nil { rateLimiter.Call(func() { urlValues := napping.Params{ "api_key": apiKey, "append_to_response": "credits,images,alternative_titles,translations,external_ids,trailers,release_dates", "language": language, }.AsUrlValues() resp, err := napping.Get( tmdbEndpoint+"movie/"+movieId, &urlValues, &movie, nil, ) if err != nil { log.Error(err.Error()) xbmc.Notify("Quasar", "GetMovie failed, check your logs.", config.AddonIcon()) } else if resp.Status() != 200 { message := fmt.Sprintf("GetMovie bad status: %d", resp.Status()) log.Error(message) xbmc.Notify("Quasar", message, config.AddonIcon()) } if movie != nil { cacheStore.Set(key, movie, cacheTime) } }) } if movie == nil { return nil } switch t := movie.RawPopularity.(type) { case string: popularity, _ := strconv.ParseFloat(t, 64) movie.Popularity = popularity case float64: movie.Popularity = t } return movie }
func InShowsCollection(tmdbId int) bool { if config.Get().TraktToken == "" { return false } var shows []*trakt.Shows cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.trakt.collection.shows") if err := cacheStore.Get(key, &shows); err != nil { shows, _ := trakt.CollectionShows() cacheStore.Set(key, shows, 30*time.Second) } for _, show := range shows { if tmdbId == show.Show.IDs.TMDB { return true } } return false }
func InMoviesCollection(tmdbId int) bool { if config.Get().TraktToken == "" { return false } var movies []*trakt.Movies cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.trakt.collection.movies") if err := cacheStore.Get(key, &movies); err != nil { movies, _ := trakt.CollectionMovies() cacheStore.Set(key, movies, 30*time.Second) } for _, movie := range movies { if tmdbId == movie.Movie.IDs.TMDB { return true } } return false }
func GetEpisode(showId int, seasonNumber int, episodeNumber int, language string) *Episode { var episode *Episode cacheStore := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) key := fmt.Sprintf("com.tmdb.episode.%d.%d.%s", showId, seasonNumber, episodeNumber, language) if err := cacheStore.Get(key, &episode); err != nil { rateLimiter.Call(func() { urlValues := napping.Params{ "api_key": apiKey, "append_to_response": "credits,images,videos,external_ids", "language": language, }.AsUrlValues() resp, err := napping.Get( fmt.Sprintf("%stv/%d/season/%d/episode/%d", tmdbEndpoint, showId, seasonNumber, episodeNumber), &urlValues, &episode, nil, ) if err != nil { log.Error(err.Error()) xbmc.Notify("Quasar", "GetEpisode failed, check your logs.", config.AddonIcon()) } else if resp.Status() != 200 { message := fmt.Sprintf("GetEpisode bad status: %d", resp.Status()) log.Error(message) xbmc.Notify("Quasar", message, config.AddonIcon()) } }) if episode != nil { cacheStore.Set(key, episode, cacheTime) } } if episode == nil { return nil } return episode }
func Routes(btService *bittorrent.BTService) *gin.Engine { r := gin.Default() gin.SetMode(gin.ReleaseMode) //r.Use(ga.GATracker()) store := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) r.GET("/", Index) r.GET("/search", Search) r.GET("/pasted", PasteURL) torrents := r.Group("/torrents") { torrents.GET("/", ListTorrents(btService)) torrents.GET("/pause/:torrentId", PauseTorrent(btService)) torrents.GET("/delete/:torrentId", RemoveTorrent(btService)) } movies := r.Group("/movies") { movies.GET("/", cache.Cache(store, IndexCacheTime), MoviesIndex) movies.GET("/search", SearchMovies) movies.GET("/popular", cache.Cache(store, DefaultCacheTime), PopularMovies) movies.GET("/popular/:genre", cache.Cache(store, DefaultCacheTime), PopularMovies) movies.GET("/top", cache.Cache(store, DefaultCacheTime), TopRatedMovies) movies.GET("/imdb250", cache.Cache(store, DefaultCacheTime), IMDBTop250) movies.GET("/mostvoted", cache.Cache(store, DefaultCacheTime), MoviesMostVoted) movies.GET("/genres", cache.Cache(store, IndexCacheTime), MovieGenres) } movie := r.Group("/movie") { movie.GET("/:imdbId/links", MovieLinks) movie.GET("/:imdbId/play", MoviePlay) } shows := r.Group("/shows") { shows.GET("/", cache.Cache(store, IndexCacheTime), TVIndex) shows.GET("/search", SearchShows) shows.GET("/popular", cache.Cache(store, DefaultCacheTime), PopularShows) shows.GET("/popular/:genre", cache.Cache(store, DefaultCacheTime), PopularShows) shows.GET("/top", cache.Cache(store, DefaultCacheTime), TopRatedShows) shows.GET("/mostvoted", cache.Cache(store, DefaultCacheTime), TVMostVoted) shows.GET("/genres", cache.Cache(store, IndexCacheTime), TVGenres) } show := r.Group("/show") { show.GET("/:showId/seasons", cache.Cache(store, DefaultCacheTime), ShowSeasons) show.GET("/:showId/season/:season/episodes", cache.Cache(store, EpisodesCacheTime), ShowEpisodes) show.GET("/:showId/season/:season/episode/:episode/play", ShowEpisodePlay) show.GET("/:showId/season/:season/episode/:episode/links", ShowEpisodeLinks) } library := r.Group("/library") { library.GET("/movie/add/:imdbId", AddMovie) library.GET("/movie/remove/:imdbId", RemoveMovie) library.GET("/movie/addremove/:imdbId", AddRemoveMovie) library.GET("/show/add/:showId", AddShow) library.GET("/show/remove/:showId", RemoveShow) library.GET("/show/addremove/:showId", AddRemoveShow) library.GET("/update", UpdateLibrary) library.GET("/getpath", GetLibraryPath) library.GET("/getcount", GetCount) library.GET("/lookup", Lookup) library.GET("/play/movie/:imdbId", PlayMovie) library.GET("/play/show/:showId/season/:season/episode/:episode", PlayShow) } provider := r.Group("/provider") { provider.GET("/:provider/movie/:imdbId", ProviderGetMovie) provider.GET("/:provider/show/:showId/season/:season/episode/:episode", ProviderGetEpisode) } repo := r.Group("/repository") { repo.GET("/:user/:repository/*filepath", repository.GetAddonFiles) repo.HEAD("/:user/:repository/*filepath", repository.GetAddonFiles) } r.GET("/youtube/:id", PlayYoutubeVideo) r.GET("/subtitles", SubtitlesIndex) r.GET("/subtitle/:id", SubtitleGet) r.GET("/play", Play(btService)) r.POST("/callbacks/:cid", providers.CallbackHandler) cmd := r.Group("/cmd") { cmd.GET("/clear_cache", ClearCache) } return r }
func Routes(btService *bittorrent.BTService) *gin.Engine { r := gin.Default() gin.SetMode(gin.ReleaseMode) store := cache.NewFileStore(path.Join(config.Get().ProfilePath, "cache")) r.GET("/", Index) r.GET("/search", Search) r.GET("/pasted", PasteURL) torrents := r.Group("/torrents") { torrents.GET("/", ListTorrents(btService)) torrents.GET("/pause", PauseSession(btService)) torrents.GET("/resume", ResumeSession(btService)) torrents.GET("/pause/:torrentId", PauseTorrent(btService)) torrents.GET("/resume/:torrentId", ResumeTorrent(btService)) torrents.GET("/delete/:torrentId", RemoveTorrent(btService)) } movies := r.Group("/movies") { movies.GET("/", cache.Cache(store, IndexCacheTime), MoviesIndex) movies.GET("/search", SearchMovies) movies.GET("/popular", cache.Cache(store, DefaultCacheTime), PopularMovies) movies.GET("/popular/:genre", cache.Cache(store, DefaultCacheTime), PopularMovies) movies.GET("/recent", cache.Cache(store, DefaultCacheTime), RecentMovies) movies.GET("/recent/:genre", cache.Cache(store, DefaultCacheTime), RecentMovies) movies.GET("/top", cache.Cache(store, DefaultCacheTime), TopRatedMovies) movies.GET("/imdb250", cache.Cache(store, DefaultCacheTime), IMDBTop250) movies.GET("/mostvoted", cache.Cache(store, DefaultCacheTime), MoviesMostVoted) movies.GET("/genres", cache.Cache(store, IndexCacheTime), MovieGenres) trakt := movies.Group("/trakt") { trakt.GET("/", cache.Cache(store, IndexCacheTime), MoviesTrakt) trakt.GET("/watchlist", WatchlistMovies) trakt.GET("/collection", CollectionMovies) trakt.GET("/popular", cache.Cache(store, DefaultCacheTime), TraktPopularMovies) trakt.GET("/trending", cache.Cache(store, DefaultCacheTime), TraktTrendingMovies) trakt.GET("/played", cache.Cache(store, DefaultCacheTime), TraktMostPlayedMovies) trakt.GET("/watched", cache.Cache(store, DefaultCacheTime), TraktMostWatchedMovies) trakt.GET("/collected", cache.Cache(store, DefaultCacheTime), TraktMostCollectedMovies) trakt.GET("/anticipated", cache.Cache(store, DefaultCacheTime), TraktMostAnticipatedMovies) trakt.GET("/boxoffice", cache.Cache(store, DefaultCacheTime), TraktBoxOffice) } } movie := r.Group("/movie") { movie.GET("/:tmdbId/links", MovieLinks) movie.GET("/:tmdbId/play", MoviePlay) movie.GET("/:tmdbId/watchlist/add", AddMovieToWatchlist) movie.GET("/:tmdbId/watchlist/remove", RemoveMovieFromWatchlist) movie.GET("/:tmdbId/collection/add", AddMovieToCollection) movie.GET("/:tmdbId/collection/remove", RemoveMovieFromCollection) } shows := r.Group("/shows") { shows.GET("/", cache.Cache(store, IndexCacheTime), TVIndex) shows.GET("/search", SearchShows) shows.GET("/popular", cache.Cache(store, DefaultCacheTime), PopularShows) shows.GET("/popular/:genre", cache.Cache(store, DefaultCacheTime), PopularShows) shows.GET("/recent/shows", cache.Cache(store, DefaultCacheTime), RecentShows) shows.GET("/recent/shows/:genre", cache.Cache(store, DefaultCacheTime), RecentShows) shows.GET("/recent/episodes", cache.Cache(store, DefaultCacheTime), RecentEpisodes) shows.GET("/recent/episodes/:genre", cache.Cache(store, DefaultCacheTime), RecentEpisodes) shows.GET("/top", cache.Cache(store, DefaultCacheTime), TopRatedShows) shows.GET("/mostvoted", cache.Cache(store, DefaultCacheTime), TVMostVoted) shows.GET("/genres", cache.Cache(store, IndexCacheTime), TVGenres) trakt := shows.Group("/trakt") { trakt.GET("/", cache.Cache(store, IndexCacheTime), TVTrakt) trakt.GET("/watchlist", WatchlistShows) trakt.GET("/collection", CollectionShows) trakt.GET("/popular", cache.Cache(store, DefaultCacheTime), TraktPopularShows) trakt.GET("/trending", cache.Cache(store, DefaultCacheTime), TraktTrendingShows) trakt.GET("/played", cache.Cache(store, DefaultCacheTime), TraktMostPlayedShows) trakt.GET("/watched", cache.Cache(store, DefaultCacheTime), TraktMostWatchedShows) trakt.GET("/collected", cache.Cache(store, DefaultCacheTime), TraktMostCollectedShows) trakt.GET("/anticipated", cache.Cache(store, DefaultCacheTime), TraktMostAnticipatedShows) } } show := r.Group("/show") { show.GET("/:showId/seasons", cache.Cache(store, DefaultCacheTime), ShowSeasons) show.GET("/:showId/season/:season/links", ShowSeasonLinks) show.GET("/:showId/season/:season/episodes", cache.Cache(store, EpisodesCacheTime), ShowEpisodes) show.GET("/:showId/season/:season/episode/:episode/play", ShowEpisodePlay) show.GET("/:showId/season/:season/episode/:episode/links", ShowEpisodeLinks) show.GET("/:showId/watchlist/add", AddShowToWatchlist) show.GET("/:showId/watchlist/remove", RemoveShowFromWatchlist) show.GET("/:showId/collection/add", AddShowToCollection) show.GET("/:showId/collection/remove", RemoveShowFromCollection) } // TODO // episode := r.Group("/episode") // { // episode.GET("/:episodeId/watchlist/add", AddEpisodeToWatchlist) // } library := r.Group("/library") { library.GET("/movie/add/:tmdbId", AddMovie) library.GET("/movie/remove/:tmdbId", RemoveMovie) library.GET("/show/add/:showId", AddShow) library.GET("/show/remove/:showId", RemoveShow) library.GET("/update", UpdateLibrary) library.GET("/getpath", GetLibraryPath) library.GET("/getcount", GetCount) library.GET("/lookup", Lookup) library.GET("/play/movie/:tmdbId", PlayMovie) library.GET("/play/show/:showId/season/:season/episode/:episode", PlayShow) } provider := r.Group("/provider") { provider.GET("/", ProviderList) provider.GET("/:provider/check", ProviderCheck) provider.GET("/:provider/enable", ProviderEnable) provider.GET("/:provider/disable", ProviderDisable) provider.GET("/:provider/failure", ProviderFailure) provider.GET("/:provider/settings", ProviderSettings) provider.GET("/:provider/movie/:tmdbId", ProviderGetMovie) provider.GET("/:provider/show/:showId/season/:season/episode/:episode", ProviderGetEpisode) } repo := r.Group("/repository") { repo.GET("/:user/:repository/*filepath", repository.GetAddonFiles) repo.HEAD("/:user/:repository/*filepath", repository.GetAddonFilesHead) } trakt := r.Group("/trakt") { trakt.GET("/authorize", AuthorizeTrakt) } r.GET("/setviewmode/:content_type", SetViewMode) r.GET("/youtube/:id", PlayYoutubeVideo) r.GET("/subtitles", SubtitlesIndex) r.GET("/subtitle/:id", SubtitleGet) r.GET("/play", Play(btService)) r.POST("/callbacks/:cid", providers.CallbackHandler) cmd := r.Group("/cmd") { cmd.GET("/clear_cache", ClearCache) } return r }