Пример #1
0
        /// <summary>
        /// Get movies for a cast by its ImdbCode
        /// </summary>
        /// <param name="imdbCode"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        public async Task <IEnumerable <MovieLightJson> > GetMovieFromCast(string imdbCode, CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Utils.Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Pessimistic);

            try
            {
                return(await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    var watch = Stopwatch.StartNew();
                    var wrapper = new MovieLightResponse();
                    var restClient = new RestClient(Utils.Constants.PopcornApi);
                    var request = new RestRequest("/movies/cast/{segment}", Method.GET);
                    request.AddUrlSegment("segment", imdbCode);
                    try
                    {
                        var response = await restClient.ExecuteTaskAsync(request, cancellation)
                                       .ConfigureAwait(false);
                        if (response.ErrorException != null)
                        {
                            throw response.ErrorException;
                        }

                        wrapper = JsonSerializer.Deserialize <MovieLightResponse>(response.RawBytes);
                        foreach (var movie in wrapper.Movies)
                        {
                            movie.TranslationLanguage = TmdbClient.DefaultLanguage;
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "GetMovieFromCast cancelled.");
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"GetMovieFromCast: {exception.Message}");
                        throw;
                    }
                    finally
                    {
                        watch.Stop();
                        var elapsedMs = watch.ElapsedMilliseconds;
                        Logger.Debug(
                            $"GetMovieFromCast ({imdbCode}) in {elapsedMs} milliseconds.");
                    }

                    var result = wrapper?.Movies ?? new List <MovieLightJson>();
                    ProcessTranslations(result);
                    return result;
                }, ct).ConfigureAwait(false));
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                return(new List <MovieLightJson>());
            }
        }
Пример #2
0
        public async Task <IActionResult> GetFromCast(string castId)
        {
            var hash = Convert.ToBase64String(
                Encoding.UTF8.GetBytes($"cast:{castId}"));

            try
            {
                var cachedMovie = await _cachingService.GetCache(hash);

                if (cachedMovie != null)
                {
                    try
                    {
                        return(Content(cachedMovie, "application/json"));
                    }
                    catch (Exception ex)
                    {
                        _loggingService.Telemetry.TrackException(ex);
                    }
                }
            }
            catch (Exception ex)
            {
                _loggingService.Telemetry.TrackException(ex);
            }

            using (var context = new PopcornContextFactory().CreateDbContext(new string[0]))
            {
                var imdbParameter = new SqlParameter("@imdbCode", castId);
                var query         = @"
                    SELECT 
                        Movie.Title, Movie.Year, Movie.Rating, Movie.PosterImage, Movie.ImdbCode, Movie.GenreNames
                    FROM 
                        MovieSet AS Movie
                    INNER JOIN
                        CastSet AS Cast
                    ON 
                        Cast.MovieId = Movie.Id
                    WHERE
                        Cast.ImdbCode = @imdbCode";
                var movieQuery    =
                    await context.Database.ExecuteSqlQueryAsync(query, new CancellationToken(), imdbParameter);

                var reader = movieQuery.DbDataReader;
                var movies = new List <MovieLightJson>();
                while (await reader.ReadAsync())
                {
                    var movie = new MovieLightJson
                    {
                        Title       = !await reader.IsDBNullAsync(0) ? reader.GetString(0) : string.Empty,
                        Year        = !await reader.IsDBNullAsync(1) ? reader.GetInt32(1) : 0,
                        Rating      = !await reader.IsDBNullAsync(2) ? reader.GetDouble(2) : 0d,
                        PosterImage = !await reader.IsDBNullAsync(3) ? reader.GetString(3) : string.Empty,
                        ImdbCode    = !await reader.IsDBNullAsync(4) ? reader.GetString(4) : string.Empty,
                        Genres      = !await reader.IsDBNullAsync(5) ? reader.GetString(5) : string.Empty
                    };
                    movies.Add(movie);
                }

                var response = new MovieLightResponse
                {
                    TotalMovies = movies.Count,
                    Movies      = movies
                };

                var json = JsonSerializer.ToJsonString(response, StandardResolver.SnakeCase);
                await _cachingService.SetCache(hash, json, TimeSpan.FromDays(1));

                return(Content(json, "application/json"));
            }
        }
Пример #3
0
        public async Task <IActionResult> Get([RequiredFromQuery] int page, [FromQuery] int limit,
                                              [FromQuery] int minimum_rating, [FromQuery] string query_term,
                                              [FromQuery] string genre, [FromQuery] string sort_by)
        {
            var nbMoviesPerPage = 20;

            if (limit >= 20 && limit <= 50)
            {
                nbMoviesPerPage = limit;
            }

            var currentPage = 1;

            if (page >= 1)
            {
                currentPage = page;
            }

            var queryTerm = string.Empty;

            if (!string.IsNullOrWhiteSpace(query_term))
            {
                queryTerm = query_term;
            }

            var genreFilter = string.Empty;

            if (!string.IsNullOrWhiteSpace(genre))
            {
                genreFilter = genre;
            }

            var hash = Convert.ToBase64String(
                Encoding.UTF8.GetBytes(
                    $@"type=movies&page={page}&limit={limit}&minimum_rating={minimum_rating}&query_term={
                            query_term
                        }&genre={genre}&sort_by={sort_by}"));

            try
            {
                var cachedMovies = await _cachingService.GetCache(hash);

                if (cachedMovies != null)
                {
                    try
                    {
                        return(Content(cachedMovies, "application/json"));
                    }
                    catch (Exception ex)
                    {
                        _loggingService.Telemetry.TrackException(ex);
                    }
                }
            }
            catch (Exception ex)
            {
                _loggingService.Telemetry.TrackException(ex);
            }

            using (var context = new PopcornContextFactory().CreateDbContext(new string[0]))
            {
                var skipParameter   = new SqlParameter("@skip", (currentPage - 1) * nbMoviesPerPage);
                var takeParameter   = new SqlParameter("@take", nbMoviesPerPage);
                var ratingParameter = new SqlParameter("@rating", minimum_rating);
                var queryParameter  = new SqlParameter("@Keywords", string.Format(@"""{0}""", queryTerm));
                var genreParameter  = new SqlParameter("@genre", genreFilter);
                var query           = @"
                    SELECT DISTINCT
                        Movie.Title, Movie.Year, Movie.Rating, Movie.PosterImage, Movie.ImdbCode, Movie.GenreNames, Torrent.Peers, Torrent.Seeds, COUNT(*) OVER () as TotalCount, Movie.DateUploadedUnix, Movie.Id, Movie.DownloadCount, Movie.LikeCount
                    FROM 
                        MovieSet AS Movie
                    CROSS APPLY
					(
						SELECT TOP 1 Torrent.MovieId, Torrent.Peers, Torrent.Seeds FROM TorrentMovieSet AS Torrent
						WHERE Torrent.MovieId = Movie.Id  AND Torrent.Url <> '' AND Torrent.Url IS NOT NULL
					) Torrent

                    INNER JOIN
                        CastSet AS Cast
                    ON Cast.MovieId = Movie.Id
                    WHERE 1 = 1";

                if (minimum_rating > 0 && minimum_rating < 10)
                {
                    query += @" AND
                        Rating >= @rating";
                }

                if (!string.IsNullOrWhiteSpace(query_term))
                {
                    query += @" AND
                        (CONTAINS(Movie.Title, @Keywords) OR CONTAINS(Cast.Name, @Keywords) OR CONTAINS(Movie.ImdbCode, @Keywords) OR CONTAINS(Cast.ImdbCode, @Keywords))";
                }

                if (!string.IsNullOrWhiteSpace(genre))
                {
                    query += @" AND
                        CONTAINS(Movie.GenreNames, @genre)";
                }

                query += " GROUP BY Movie.Id, Movie.Title, Movie.Year, Movie.Rating, Movie.PosterImage, Movie.ImdbCode, Movie.GenreNames, Torrent.Peers, Torrent.Seeds, Movie.DateUploadedUnix, Movie.Id, Movie.DownloadCount, Movie.LikeCount";

                if (!string.IsNullOrWhiteSpace(sort_by))
                {
                    switch (sort_by)
                    {
                    case "title":
                        query += " ORDER BY Movie.Title ASC";
                        break;

                    case "year":
                        query += " ORDER BY Movie.Year DESC";
                        break;

                    case "rating":
                        query += " ORDER BY Movie.Rating DESC";
                        break;

                    case "peers":
                        query += " ORDER BY Torrent.Peers DESC";
                        break;

                    case "seeds":
                        query += " ORDER BY Torrent.Seeds DESC";
                        break;

                    case "download_count":
                        query += " ORDER BY Movie.DownloadCount DESC";
                        break;

                    case "like_count":
                        query += " ORDER BY Movie.LikeCount DESC";
                        break;

                    case "date_added":
                        query += " ORDER BY Movie.DateUploadedUnix DESC";
                        break;

                    default:
                        query += " ORDER BY Movie.DateUploadedUnix DESC";
                        break;
                    }
                }
                else
                {
                    query += " ORDER BY Movie.DateUploadedUnix DESC";
                }

                query += @" OFFSET @skip ROWS 
                    FETCH NEXT @take ROWS ONLY";

                var moviesQuery = await context.Database.ExecuteSqlQueryAsync(query, new CancellationToken(),
                                                                              skipParameter, takeParameter,
                                                                              ratingParameter, queryParameter,
                                                                              genreParameter);

                var reader = moviesQuery.DbDataReader;
                var count  = 0;
                var movies = new List <MovieLightJson>();
                while (await reader.ReadAsync())
                {
                    var movie = new MovieLightJson
                    {
                        Title       = !await reader.IsDBNullAsync(0) ? reader.GetString(0) : string.Empty,
                        Year        = !await reader.IsDBNullAsync(1) ? reader.GetInt32(1) : 0,
                        Rating      = !await reader.IsDBNullAsync(2) ? reader.GetDouble(2) : 0d,
                        PosterImage = !await reader.IsDBNullAsync(3) ? reader.GetString(3) : string.Empty,
                        ImdbCode    = !await reader.IsDBNullAsync(4) ? reader.GetString(4) : string.Empty,
                        Genres      = !await reader.IsDBNullAsync(5) ? reader.GetString(5) : string.Empty
                    };
                    movies.Add(movie);
                    count = !await reader.IsDBNullAsync(8) ? reader.GetInt32(8) : 0;
                }

                var response = new MovieLightResponse
                {
                    TotalMovies = count,
                    Movies      = movies
                };

                var json = JsonSerializer.ToJsonString(response, StandardResolver.SnakeCase);
                await _cachingService.SetCache(hash, json, TimeSpan.FromDays(1));

                return(Content(json, "application/json"));
            }
        }
Пример #4
0
        public async Task <IActionResult> GetSimilar([FromBody] IEnumerable <string> imdbIds, [RequiredFromQuery] int page, [FromQuery] int limit,
                                                     [FromQuery] int minimum_rating, [FromQuery] string query_term,
                                                     [FromQuery] string genre, [FromQuery] string sort_by)
        {
            var nbMoviesPerPage = 20;

            if (limit >= 20 && limit <= 50)
            {
                nbMoviesPerPage = limit;
            }

            var currentPage = 1;

            if (page >= 1)
            {
                currentPage = page;
            }

            var queryTerm = string.Empty;

            if (!string.IsNullOrWhiteSpace(query_term))
            {
                queryTerm = query_term;
            }

            var genreFilter = string.Empty;

            if (!string.IsNullOrWhiteSpace(genre))
            {
                genreFilter = genre;
            }

            if (!imdbIds.Any())
            {
                return(Json(new MovieLightResponse
                {
                    Movies = new List <MovieLightJson>(),
                    TotalMovies = 0
                }));
            }

            var hash = Convert.ToBase64String(
                Encoding.UTF8.GetBytes(
                    $@"type=movies&similar&imdbIds={string.Join(',', imdbIds)}&page={page}&limit={limit}&minimum_rating={minimum_rating}&query_term={
                            query_term
                        }&genre={genre}&sort_by={sort_by}"));

            try
            {
                var cachedMovies = await _cachingService.GetCache(hash);

                if (cachedMovies != null)
                {
                    try
                    {
                        return(Content(cachedMovies, "application/json"));
                    }
                    catch (Exception ex)
                    {
                        _loggingService.Telemetry.TrackException(ex);
                    }
                }
            }
            catch (Exception ex)
            {
                _loggingService.Telemetry.TrackException(ex);
            }

            using (var context = new PopcornContextFactory().CreateDbContext(new string[0]))
            {
                var skipParameter   = new SqlParameter("@skip", (currentPage - 1) * nbMoviesPerPage);
                var takeParameter   = new SqlParameter("@take", nbMoviesPerPage);
                var ratingParameter = new SqlParameter("@rating", minimum_rating);
                var queryParameter  = new SqlParameter("@Keywords", string.Format(@"""{0}""", queryTerm));
                var genreParameter  = new SqlParameter("@genre", genreFilter);
                var query           = @"
                    SELECT DISTINCT
                        Movie.Title, Movie.Year, Movie.Rating, Movie.PosterImage, Movie.ImdbCode, Movie.GenreNames, COUNT(*) OVER () as TotalCount
                    FROM 
                        MovieSet AS Movie
                    WHERE
                        Movie.ImdbCode IN (SELECT 
                            Similar.TmdbId                      
                        FROM 
                            Similar AS Similar
                        INNER JOIN
					    (
						    SELECT Movie.ID
						    FROM 
							    MovieSet AS Movie
						    WHERE 
							    Movie.ImdbCode IN ({@imdbIds})
						) Movie
					ON Similar.MovieId = Movie.Id)
                    AND 1 = 1";

                if (minimum_rating > 0 && minimum_rating < 10)
                {
                    query += @" AND
                        Rating >= @rating";
                }

                if (!string.IsNullOrWhiteSpace(query_term))
                {
                    query += @" AND
                        (CONTAINS(Movie.Title, @Keywords) OR CONTAINS(Movie.ImdbCode, @Keywords))";
                }

                if (!string.IsNullOrWhiteSpace(genre))
                {
                    query += @" AND
                        CONTAINS(Movie.GenreNames, @genre)";
                }

                query += " ORDER BY Movie.Rating DESC";
                query += @" OFFSET @skip ROWS 
                    FETCH NEXT @take ROWS ONLY";

                using (var cmd = new SqlCommand(query,
                                                new SqlConnection(context.Database.GetDbConnection().ConnectionString)))
                {
                    cmd.AddArrayParameters(imdbIds, "@imdbIds");
                    cmd.Parameters.Add(skipParameter);
                    cmd.Parameters.Add(takeParameter);
                    cmd.Parameters.Add(ratingParameter);
                    cmd.Parameters.Add(queryParameter);
                    cmd.Parameters.Add(genreParameter);
                    await cmd.Connection.OpenAsync();

                    var reader = await cmd.ExecuteReaderAsync(new CancellationToken());

                    var count  = 0;
                    var movies = new List <MovieLightJson>();
                    while (await reader.ReadAsync())
                    {
                        var movie = new MovieLightJson
                        {
                            Title       = !await reader.IsDBNullAsync(0) ? reader.GetString(0) : string.Empty,
                            Year        = !await reader.IsDBNullAsync(1) ? reader.GetInt32(1) : 0,
                            Rating      = !await reader.IsDBNullAsync(2) ? reader.GetDouble(2) : 0d,
                            PosterImage = !await reader.IsDBNullAsync(3) ? reader.GetString(3) : string.Empty,
                            ImdbCode    = !await reader.IsDBNullAsync(4) ? reader.GetString(4) : string.Empty,
                            Genres      = !await reader.IsDBNullAsync(5) ? reader.GetString(5) : string.Empty
                        };
                        movies.Add(movie);
                        count = !await reader.IsDBNullAsync(6) ? reader.GetInt32(6) : 0;
                    }

                    var response = new MovieLightResponse
                    {
                        TotalMovies = count,
                        Movies      = movies
                    };

                    var json = JsonSerializer.ToJsonString(response, StandardResolver.SnakeCase);
                    await _cachingService.SetCache(hash, json, TimeSpan.FromDays(1));

                    return(Content(json, "application/json"));
                }
            }
        }
Пример #5
0
        public async Task <IActionResult> GetMoviesByIds([FromBody] IEnumerable <string> imdbIds)
        {
            if (!imdbIds.Any())
            {
                return(Json(new MovieLightResponse
                {
                    Movies = new List <MovieLightJson>(),
                    TotalMovies = 0
                }));
            }

            var hash = Convert.ToBase64String(
                Encoding.UTF8.GetBytes(
                    $@"type=movies&imdbIds={string.Join(',', imdbIds)}"));

            try
            {
                var cachedMovies = await _cachingService.GetCache(hash);

                if (cachedMovies != null)
                {
                    try
                    {
                        return(Content(cachedMovies, "application/json"));
                    }
                    catch (Exception ex)
                    {
                        _loggingService.Telemetry.TrackException(ex);
                    }
                }
            }
            catch (Exception ex)
            {
                _loggingService.Telemetry.TrackException(ex);
            }

            using (var context = new PopcornContextFactory().CreateDbContext(new string[0]))
            {
                var query = @"
                    SELECT DISTINCT
                        Movie.Title, Movie.Year, Movie.Rating, Movie.PosterImage, Movie.ImdbCode, Movie.GenreNames, COUNT(*) OVER () as TotalCount
                    FROM 
                        MovieSet AS Movie
                    WHERE
                        Movie.ImdbCode IN ({@imdbIds})
                    ORDER BY Movie.Rating DESC";

                using (var cmd = new SqlCommand(query,
                                                new SqlConnection(context.Database.GetDbConnection().ConnectionString)))
                {
                    cmd.AddArrayParameters(imdbIds, "@imdbIds");
                    await cmd.Connection.OpenAsync();

                    var reader = await cmd.ExecuteReaderAsync(new CancellationToken());

                    var count  = 0;
                    var movies = new List <MovieLightJson>();
                    while (await reader.ReadAsync())
                    {
                        var movie = new MovieLightJson
                        {
                            Title       = !await reader.IsDBNullAsync(0) ? reader.GetString(0) : string.Empty,
                            Year        = !await reader.IsDBNullAsync(1) ? reader.GetInt32(1) : 0,
                            Rating      = !await reader.IsDBNullAsync(2) ? reader.GetDouble(2) : 0d,
                            PosterImage = !await reader.IsDBNullAsync(3) ? reader.GetString(3) : string.Empty,
                            ImdbCode    = !await reader.IsDBNullAsync(4) ? reader.GetString(4) : string.Empty,
                            Genres      = !await reader.IsDBNullAsync(5) ? reader.GetString(5) : string.Empty
                        };
                        movies.Add(movie);
                        count = !await reader.IsDBNullAsync(6) ? reader.GetInt32(6) : 0;
                    }

                    var response = new MovieLightResponse
                    {
                        TotalMovies = count,
                        Movies      = movies
                    };

                    var json = JsonSerializer.ToJsonString(response, StandardResolver.SnakeCase);
                    await _cachingService.SetCache(hash, json, TimeSpan.FromDays(1));

                    return(Content(json, "application/json"));
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Search movies by criteria
        /// </summary>
        /// <param name="criteria">Criteria used for search</param>
        /// <param name="page">Page to return</param>
        /// <param name="limit">The maximum number of movies to return</param>
        /// <param name="genre">The genre to filter</param>
        /// <param name="ratingFilter">Used to filter by rating</param>
        /// <param name="ct">Cancellation token</param>
        /// <returns>Searched movies and the number of movies found</returns>
        public async Task <(IEnumerable <MovieLightJson> movies, int nbMovies)> SearchMoviesAsync(string criteria,
                                                                                                  int page,
                                                                                                  int limit,
                                                                                                  GenreJson genre,
                                                                                                  double ratingFilter,
                                                                                                  CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Optimistic);

            try
            {
                return(await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    var watch = Stopwatch.StartNew();
                    var wrapper = new MovieLightResponse();
                    if (limit < 1 || limit > 50)
                    {
                        limit = Constants.MaxMoviesPerPage;
                    }

                    if (page < 1)
                    {
                        page = 1;
                    }

                    var restClient = new RestClient(Constants.PopcornApi);
                    var request = new RestRequest("/{segment}", Method.GET);
                    request.AddUrlSegment("segment", "movies");
                    request.AddParameter("limit", limit);
                    request.AddParameter("page", page);
                    request.AddParameter("genre", genre != null ? genre.EnglishName : string.Empty);
                    request.AddParameter("minimum_rating", Convert.ToInt32(ratingFilter));
                    request.AddParameter("query_term", criteria);
                    request.AddParameter("sort_by", "year");

                    try
                    {
                        var response = await restClient.ExecuteTaskAsync(request, cancellation);
                        if (response.ErrorException != null)
                        {
                            throw response.ErrorException;
                        }

                        wrapper = JsonSerializer.Deserialize <MovieLightResponse>(response.RawBytes);
                        foreach (var movie in wrapper.Movies)
                        {
                            movie.TranslationLanguage = (await _tmdbService.GetClient).DefaultLanguage;
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "SearchMoviesAsync cancelled.");
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"SearchMoviesAsync: {exception.Message}");
                        throw;
                    }
                    finally
                    {
                        watch.Stop();
                        var elapsedMs = watch.ElapsedMilliseconds;
                        Logger.Trace(
                            $"SearchMoviesAsync ({criteria}, {page}, {limit}) in {elapsedMs} milliseconds.");
                    }

                    var result = wrapper?.Movies ?? new List <MovieLightJson>();
                    await ProcessTranslations(result);
                    var nbResult = wrapper?.TotalMovies ?? 0;
                    return (result, nbResult);
                }, ct));
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                throw;
            }
        }
Пример #7
0
        /// <summary>
        /// Get movies by ids
        /// </summary>
        /// <param name="imdbIds">The imdbIds of the movies, split by comma</param>
        /// <param name="ct">Cancellation token</param>
        /// <returns>Similar movies</returns>
        public async Task <(IEnumerable <MovieLightJson> movies, int nbMovies)> GetMoviesByIds(
            IEnumerable <string> imdbIds,
            CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Optimistic);

            try
            {
                return(await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    var watch = Stopwatch.StartNew();
                    var wrapper = new MovieLightResponse();
                    var restClient = new RestClient(Constants.PopcornApi);
                    var request = new RestRequest("/{segment}/{subsegment}", Method.POST);
                    request.AddUrlSegment("segment", "movies");
                    request.AddUrlSegment("subsegment", "ids");
                    request.AddJsonBody(imdbIds);

                    try
                    {
                        var response = await restClient.ExecuteTaskAsync(request, cancellation);
                        if (response.ErrorException != null)
                        {
                            throw response.ErrorException;
                        }

                        wrapper = JsonSerializer.Deserialize <MovieLightResponse>(response.RawBytes);
                        foreach (var movie in wrapper.Movies)
                        {
                            movie.TranslationLanguage = (await _tmdbService.GetClient).DefaultLanguage;
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "GetMoviesByIds cancelled.");
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"GetMoviesByIds: {exception.Message}");
                        throw;
                    }
                    finally
                    {
                        watch.Stop();
                        var elapsedMs = watch.ElapsedMilliseconds;
                        Logger.Trace(
                            $"GetMoviesByIds ({string.Join(",", imdbIds)}) in {elapsedMs} milliseconds.");
                    }

                    var result = wrapper?.Movies ?? new List <MovieLightJson>();
                    await ProcessTranslations(result);
                    var nbResult = wrapper?.TotalMovies ?? 0;
                    return (result, nbResult);
                }, ct));
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                return(new List <MovieLightJson>(), 0);
            }
        }
Пример #8
0
        /// <summary>
        /// Get similar movies
        /// </summary>
        /// <param name="page">Page to return</param>
        /// <param name="limit">The maximum number of movies to return</param>
        /// <param name="imdbIds">The imdbIds of the movies, split by comma</param>
        /// <param name="ct">Cancellation token</param>
        /// <returns>Similar movies</returns>
        public async Task <(IEnumerable <MovieLightJson> movies, int nbMovies)> GetSimilarAsync(int page,
                                                                                                int limit,
                                                                                                IEnumerable <string> imdbIds,
                                                                                                CancellationToken ct)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Utils.Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Pessimistic);

            try
            {
                return(await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    var watch = Stopwatch.StartNew();
                    var wrapper = new MovieLightResponse();
                    if (limit < 1 || limit > 50)
                    {
                        limit = Utils.Constants.MaxMoviesPerPage;
                    }

                    if (page < 1)
                    {
                        page = 1;
                    }

                    var restClient = new RestClient(Utils.Constants.PopcornApi);
                    var request = new RestRequest("/{segment}/{subsegment}", Method.POST);
                    request.AddUrlSegment("segment", "movies");
                    request.AddUrlSegment("subsegment", "similar");
                    request.AddQueryParameter("limit", limit.ToString());
                    request.AddQueryParameter("page", page.ToString());
                    request.AddJsonBody(imdbIds);

                    try
                    {
                        var response = await restClient.ExecuteTaskAsync(request, cancellation);
                        if (response.ErrorException != null)
                        {
                            throw response.ErrorException;
                        }

                        wrapper = JsonSerializer.Deserialize <MovieLightResponse>(response.RawBytes);
                        foreach (var movie in wrapper.Movies)
                        {
                            movie.TranslationLanguage = TmdbClient.DefaultLanguage;
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "GetSimilarAsync cancelled.");
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"GetSimilarAsync: {exception.Message}");
                        throw;
                    }
                    finally
                    {
                        watch.Stop();
                        var elapsedMs = watch.ElapsedMilliseconds;
                        Logger.Debug(
                            $"GetSimilarAsync ({page}, {limit}, {string.Join(",", imdbIds)}) in {elapsedMs} milliseconds.");
                    }

                    var result = wrapper?.Movies ?? new List <MovieLightJson>();
                    ProcessTranslations(result);
                    var nbResult = wrapper?.TotalMovies ?? 0;
                    return (result, nbResult);
                }, ct).ConfigureAwait(false));
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                return(new List <MovieLightJson>(), 0);
            }
        }
Пример #9
0
        /// <summary>
        /// Search movies by criteria
        /// </summary>
        /// <param name="criteria">Criteria used for search</param>
        /// <param name="page">Page to return</param>
        /// <param name="limit">The maximum number of movies to return</param>
        /// <param name="genre">The genre to filter</param>
        /// <param name="ratingFilter">Used to filter by rating</param>
        /// <param name="ct">Cancellation token</param>
        /// <returns>Searched movies and the number of movies found</returns>
        public async Task <(IEnumerable <MovieLightJson> movies, int nbMovies)> SearchMoviesAsync(string criteria,
                                                                                                  int page,
                                                                                                  int limit,
                                                                                                  GenreJson genre,
                                                                                                  double ratingFilter,
                                                                                                  CancellationToken ct)
        {
            var watch   = Stopwatch.StartNew();
            var wrapper = new MovieLightResponse();

            if (limit < 1 || limit > 50)
            {
                limit = Utils.Constants.MaxMoviesPerPage;
            }

            if (page < 1)
            {
                page = 1;
            }

            var restClient = new RestClient(Utils.Constants.PopcornApi);
            var request    = new RestRequest("/{segment}", Method.GET);

            request.AddUrlSegment("segment", "movies");
            request.AddParameter("limit", limit);
            request.AddParameter("page", page);
            if (genre != null)
            {
                request.AddParameter("genre", genre.EnglishName);
            }
            request.AddParameter("minimum_rating", Convert.ToInt32(ratingFilter));
            request.AddParameter("query_term", criteria);

            try
            {
                var response = await restClient.ExecuteTaskAsync <MovieLightResponse>(request, ct);

                if (response.ErrorException != null)
                {
                    throw response.ErrorException;
                }

                wrapper = response.Data;
            }
            catch (Exception exception) when(exception is TaskCanceledException)
            {
                Logger.Debug(
                    "SearchMoviesAsync cancelled.");
            }
            catch (Exception exception)
            {
                Logger.Error(
                    $"SearchMoviesAsync: {exception.Message}");
                throw;
            }
            finally
            {
                watch.Stop();
                var elapsedMs = watch.ElapsedMilliseconds;
                Logger.Debug(
                    $"SearchMoviesAsync ({criteria}, {page}, {limit}) in {elapsedMs} milliseconds.");
            }

            var result = wrapper?.Movies ?? new List <MovieLightJson>();

            Task.Run(async() =>
            {
                await ProcessTranslations(result).ConfigureAwait(false);
            }).ConfigureAwait(false);

            var nbResult = wrapper?.TotalMovies ?? 0;

            return(result, nbResult);
        }
Пример #10
0
        public async Task <IActionResult> Get([RequiredFromQuery] int page, [FromQuery] int limit,
                                              [FromQuery] int minimum_rating, [FromQuery] string query_term,
                                              [FromQuery] string genre, [FromQuery] string sort_by)
        {
            var nbMoviesPerPage = 20;

            if (limit >= 20 && limit <= 50)
            {
                nbMoviesPerPage = limit;
            }

            var currentPage = 1;

            if (page >= 1)
            {
                currentPage = page;
            }

            var queryTerm = string.Empty;

            if (!string.IsNullOrWhiteSpace(query_term))
            {
                queryTerm = query_term;
            }

            var genreFilter = string.Empty;

            if (!string.IsNullOrWhiteSpace(genre))
            {
                genreFilter = genre;
            }

            var hash = Convert.ToBase64String(
                Encoding.UTF8.GetBytes(
                    $@"type=movies&page={page}&limit={limit}&minimum_rating={minimum_rating}&query_term={
                            query_term
                        }&genre={genre}&sort_by={sort_by}"));

            try
            {
                var cachedMovies = await _cachingService.GetCache(hash);

                if (cachedMovies != null)
                {
                    try
                    {
                        return(Json(JsonConvert.DeserializeObject <MovieLightResponse>(cachedMovies)));
                    }
                    catch (Exception ex)
                    {
                        _loggingService.Telemetry.TrackException(ex);
                    }
                }
            }
            catch (Exception ex)
            {
                _loggingService.Telemetry.TrackException(ex);
            }

            using (var context = new PopcornContextFactory().CreateDbContext(new string[0]))
            {
                var skipParameter   = new SqlParameter("@skip", (currentPage - 1) * nbMoviesPerPage);
                var takeParameter   = new SqlParameter("@take", nbMoviesPerPage);
                var ratingParameter = new SqlParameter("@rating", minimum_rating);
                var queryParameter  = new SqlParameter("@Keywords", queryTerm);
                var genreParameter  = new SqlParameter("@genre", genreFilter);
                var query           = @"
                    SELECT 
                        Movie.Title, Movie.Year, Movie.Rating, Movie.PosterImage, Movie.ImdbCode, Movie.GenreNames, Torrent.Peers, Torrent.Seeds, COUNT(*) OVER () as TotalCount
                    FROM 
                        MovieSet AS Movie
                    INNER JOIN
                        TorrentMovieSet AS Torrent
                    ON 
                        Torrent.MovieId = Movie.Id
                    AND 
                        Torrent.Quality = '720p'
                    WHERE
                        1 = 1";

                if (minimum_rating > 0 && minimum_rating < 10)
                {
                    query += @" AND
                        Rating >= @rating";
                }

                if (!string.IsNullOrWhiteSpace(query_term))
                {
                    query += @" AND
                        FREETEXT(Title, @Keywords)";
                }

                if (!string.IsNullOrWhiteSpace(genre))
                {
                    query += @" AND
                        CONTAINS(GenreNames, @genre)";
                }

                if (!string.IsNullOrWhiteSpace(sort_by))
                {
                    switch (sort_by)
                    {
                    case "title":
                        query += " ORDER BY Movie.Title ASC";
                        break;

                    case "year":
                        query += " ORDER BY Movie.Year DESC";
                        break;

                    case "rating":
                        query += " ORDER BY Movie.Rating DESC";
                        break;

                    case "peers":
                        query += " ORDER BY Torrent.Peers DESC";
                        break;

                    case "seeds":
                        query += " ORDER BY Torrent.Seeds DESC";
                        break;

                    case "download_count":
                        query += " ORDER BY Movie.DownloadCount DESC";
                        break;

                    case "like_count":
                        query += " ORDER BY Movie.LikeCount DESC";
                        break;

                    case "date_added":
                        query += " ORDER BY Movie.DateUploadedUnix DESC";
                        break;

                    default:
                        query += " ORDER BY Movie.DateUploadedUnix DESC";
                        break;
                    }
                }
                else
                {
                    query += " ORDER BY Movie.DateUploadedUnix DESC";
                }

                query += @" OFFSET @skip ROWS 
                    FETCH NEXT @take ROWS ONLY";

                var moviesQuery = await context.Database.ExecuteSqlQueryAsync(query, new CancellationToken(),
                                                                              skipParameter, takeParameter,
                                                                              ratingParameter, queryParameter,
                                                                              genreParameter);

                var reader = moviesQuery.DbDataReader;
                var count  = 0;
                var movies = new List <MovieLightJson>();
                while (await reader.ReadAsync())
                {
                    var movie = new MovieLightJson
                    {
                        Title       = reader[0].GetType() != typeof(DBNull) ? (string)reader[0] : string.Empty,
                        Year        = reader[1].GetType() != typeof(DBNull) ? (int)reader[1] : 0,
                        Rating      = reader[2].GetType() != typeof(DBNull) ? (double)reader[2] : 0d,
                        PosterImage = reader[3].GetType() != typeof(DBNull) ? (string)reader[3] : string.Empty,
                        ImdbCode    = reader[4].GetType() != typeof(DBNull) ? (string)reader[4] : string.Empty,
                        Genres      = reader[5].GetType() != typeof(DBNull) ? (string)reader[5] : string.Empty
                    };
                    movies.Add(movie);
                    count = reader[8].GetType() != typeof(DBNull) ? (int)reader[8] : 0;
                }

                var response = new MovieLightResponse
                {
                    TotalMovies = count,
                    Movies      = movies
                };

                await _cachingService.SetCache(hash, JsonConvert.SerializeObject(response), TimeSpan.FromDays(1));

                return
                    (Json(response));
            }
        }
Пример #11
0
        public async Task <IActionResult> GetSimilar([FromBody] IEnumerable <string> imdbIds, [RequiredFromQuery] int page, [FromQuery] int limit)
        {
            if (!imdbIds.Any())
            {
                return(Json(new MovieLightResponse
                {
                    Movies = new List <MovieLightJson>(),
                    TotalMovies = 0
                }));
            }

            var nbMoviesPerPage = 20;

            if (limit >= 20 && limit <= 50)
            {
                nbMoviesPerPage = limit;
            }

            var currentPage = 1;

            if (page >= 1)
            {
                currentPage = page;
            }

            var hash = Convert.ToBase64String(
                Encoding.UTF8.GetBytes(
                    $@"type=movies&page={page}&limit={limit}&imdbId={string.Join(',', imdbIds)}"));

            try
            {
                var cachedMovies = await _cachingService.GetCache(hash);

                if (cachedMovies != null)
                {
                    try
                    {
                        return(Json(JsonConvert.DeserializeObject <MovieLightResponse>(cachedMovies)));
                    }
                    catch (Exception ex)
                    {
                        _loggingService.Telemetry.TrackException(ex);
                    }
                }
            }
            catch (Exception ex)
            {
                _loggingService.Telemetry.TrackException(ex);
            }

            using (var context = new PopcornContextFactory().CreateDbContext(new string[0]))
            {
                var skipParameter = new SqlParameter("@skip", (currentPage - 1) * nbMoviesPerPage);
                var takeParameter = new SqlParameter("@take", nbMoviesPerPage);
                var query         = @"
                    SELECT DISTINCT
                        Movie.Title, Movie.Year, Movie.Rating, Movie.PosterImage, Movie.ImdbCode, Movie.GenreNames, Torrent.Peers, Torrent.Seeds, COUNT(*) OVER () as TotalCount
                    FROM 
                        MovieSet AS Movie
                    INNER JOIN
                        TorrentMovieSet AS Torrent
                    ON 
                        Torrent.MovieId = Movie.Id
                    INNER JOIN
                        Similar
                    ON 
                        Similar.MovieId = Movie.Id
                    AND 
                        Torrent.Quality = '720p'
                    WHERE
                        Similar.TmdbId IN ({@imdbIds})
                    ORDER BY Movie.Rating DESC";

                query += @" OFFSET @skip ROWS 
                    FETCH NEXT @take ROWS ONLY";

                using (var cmd = new SqlCommand(query, new SqlConnection(context.Database.GetDbConnection().ConnectionString)))
                {
                    cmd.AddArrayParameters(imdbIds, "@imdbIds");
                    cmd.Parameters.Add(skipParameter);
                    cmd.Parameters.Add(takeParameter);
                    await cmd.Connection.OpenAsync();

                    var reader = await cmd.ExecuteReaderAsync(new CancellationToken());

                    var count  = 0;
                    var movies = new List <MovieLightJson>();
                    while (await reader.ReadAsync())
                    {
                        var movie = new MovieLightJson
                        {
                            Title       = reader[0].GetType() != typeof(DBNull) ? (string)reader[0] : string.Empty,
                            Year        = reader[1].GetType() != typeof(DBNull) ? (int)reader[1] : 0,
                            Rating      = reader[2].GetType() != typeof(DBNull) ? (double)reader[2] : 0d,
                            PosterImage = reader[3].GetType() != typeof(DBNull) ? (string)reader[3] : string.Empty,
                            ImdbCode    = reader[4].GetType() != typeof(DBNull) ? (string)reader[4] : string.Empty,
                            Genres      = reader[5].GetType() != typeof(DBNull) ? (string)reader[5] : string.Empty
                        };
                        movies.Add(movie);
                        count = reader[8].GetType() != typeof(DBNull) ? (int)reader[8] : 0;
                    }

                    var response = new MovieLightResponse
                    {
                        TotalMovies = count,
                        Movies      = movies
                    };
                    await _cachingService.SetCache(hash, JsonConvert.SerializeObject(response), TimeSpan.FromDays(1));

                    return
                        (Json(response));
                }
            }
        }
Пример #12
0
        /// <summary>
        /// Get similar movies
        /// </summary>
        /// <param name="page">Page to return</param>
        /// <param name="limit">The maximum number of movies to return</param>
        /// <param name="imdbIds">The imdbIds of the movies, split by comma</param>
        /// <param name="ct">Cancellation token</param>
        /// <returns>Similar movies</returns>
        public async Task <(IEnumerable <MovieLightJson> movies, int nbMovies)> GetSimilarAsync(int page,
                                                                                                int limit,
                                                                                                IEnumerable <string> imdbIds,
                                                                                                CancellationToken ct)
        {
            var watch   = Stopwatch.StartNew();
            var wrapper = new MovieLightResponse();

            if (limit < 1 || limit > 50)
            {
                limit = Utils.Constants.MaxMoviesPerPage;
            }

            if (page < 1)
            {
                page = 1;
            }

            var restClient = new RestClient(Utils.Constants.PopcornApi);
            var request    = new RestRequest("/{segment}/{subsegment}", Method.POST);

            request.AddUrlSegment("segment", "movies");
            request.AddUrlSegment("subsegment", "similar");
            request.AddQueryParameter("limit", limit.ToString());
            request.AddQueryParameter("page", page.ToString());
            request.AddJsonBody(imdbIds);

            try
            {
                var response = await restClient.ExecuteTaskAsync <MovieLightResponse>(request, ct);

                if (response.ErrorException != null)
                {
                    throw response.ErrorException;
                }

                wrapper = response.Data;
            }
            catch (Exception exception) when(exception is TaskCanceledException)
            {
                Logger.Debug(
                    "GetSimilarAsync cancelled.");
            }
            catch (Exception exception)
            {
                Logger.Error(
                    $"GetSimilarAsync: {exception.Message}");
                throw;
            }
            finally
            {
                watch.Stop();
                var elapsedMs = watch.ElapsedMilliseconds;
                Logger.Debug(
                    $"GetSimilarAsync ({page}, {limit}, {imdbIds}) in {elapsedMs} milliseconds.");
            }

            var result = wrapper?.Movies ?? new List <MovieLightJson>();

            Task.Run(async() =>
            {
                await ProcessTranslations(result).ConfigureAwait(false);
            }).ConfigureAwait(false);

            var nbResult = wrapper?.TotalMovies ?? 0;

            return(result, nbResult);
        }
Пример #13
0
        /// <summary>
        /// Get similar movies
        /// </summary>
        /// <param name="page">Page</param>
        /// <param name="limit">Limit</param>
        /// <param name="ratingFilter">Rating</param>
        /// <param name="sortBy">SortBy</param>
        /// <param name="imdbIds">The imdbIds of the movies, split by comma</param>
        /// <param name="ct">Cancellation token</param>
        /// <param name="genre">Genre</param>
        /// <returns>Similar movies</returns>
        public async Task <(IEnumerable <MovieLightJson> movies, int nbMovies)> GetSimilar(int page,
                                                                                           int limit,
                                                                                           double ratingFilter,
                                                                                           string sortBy,
                                                                                           IList <string> imdbIds,
                                                                                           CancellationToken ct,
                                                                                           GenreJson genre = null)
        {
            var timeoutPolicy =
                Policy.TimeoutAsync(Constants.DefaultRequestTimeoutInSecond, TimeoutStrategy.Optimistic);

            try
            {
                return(await timeoutPolicy.ExecuteAsync(async cancellation =>
                {
                    var watch = Stopwatch.StartNew();
                    var wrapper = new MovieLightResponse();
                    if (limit < 1 || limit > 50)
                    {
                        limit = Constants.MaxMoviesPerPage;
                    }

                    if (page < 1)
                    {
                        page = 1;
                    }

                    var request = new RestRequest("/{segment}/{subsegment}", Method.POST);
                    request.AddUrlSegment("segment", "movies");
                    request.AddUrlSegment("subsegment", "similar");
                    request.AddQueryParameter("limit", limit.ToString());
                    request.AddQueryParameter("page", page.ToString());
                    request.AddQueryParameter("genre", genre != null ? genre.EnglishName : string.Empty);
                    request.AddQueryParameter("minimum_rating", Convert.ToInt32(ratingFilter).ToString());
                    request.AddQueryParameter("sort_by", sortBy);
                    request.AddQueryParameter("query_term", string.Empty);
                    request.AddJsonBody(imdbIds);

                    try
                    {
                        var response = await _restClient.ExecuteTaskAsync(request, cancellation);
                        if (response.ErrorException != null)
                        {
                            throw response.ErrorException;
                        }

                        wrapper = JsonConvert.DeserializeObject <MovieLightResponse>(response.Content);
                        foreach (var movie in wrapper.Movies)
                        {
                            movie.TranslationLanguage = (await _tmdbService.GetClient).DefaultLanguage;
                        }
                    }
                    catch (Exception exception) when(exception is TaskCanceledException)
                    {
                        Logger.Debug(
                            "GetMoviesByIds cancelled.");
                    }
                    catch (Exception exception)
                    {
                        Logger.Error(
                            $"GetMoviesByIds: {exception.Message}");
                        throw;
                    }
                    finally
                    {
                        watch.Stop();
                        var elapsedMs = watch.ElapsedMilliseconds;
                        Logger.Trace(
                            $"GetMoviesByIds ({string.Join(",", imdbIds)}) in {elapsedMs} milliseconds.");
                    }

                    var result = wrapper?.Movies ?? new List <MovieLightJson>();
                    await ProcessTranslations(result);
                    var nbResult = wrapper?.TotalMovies ?? 0;
                    return (result, nbResult);
                }, ct));
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                return(new List <MovieLightJson>(), 0);
            }
        }