/// <summary> /// Initializes a new instance of the MoviePlayerViewModel class. /// </summary> /// <param name="movie">Movie to play</param> public MoviePlayerViewModel(MovieFull movie) { RegisterMessages(); RegisterCommands(); Movie = movie; TabName = !string.IsNullOrEmpty(Movie.Title) ? Movie.Title : Properties.Resources.PlayingTitleTab; }
/// <summary> /// Get the movie's subtitles /// </summary> /// <param name="movie">The movie</param> public async Task LoadSubtitlesAsync(MovieFull movie) { Logger.Debug( $"Load subtitles for movie: {movie.Title}"); Movie = movie; await _movieService.LoadSubtitlesAsync(movie, _cancellationDownloadingSubtitlesToken.Token); }
/// <summary> /// Translate movie informations (title, description, ...) /// </summary> /// <param name="movieToTranslate">Movie to translate</param> /// <param name="ct">Used to cancel translation</param> /// <returns>Task</returns> public async Task TranslateMovieFullAsync(MovieFull movieToTranslate, CancellationToken ct) { var watch = Stopwatch.StartNew(); try { await Task.Run(() => { var movie = TmdbClient.GetMovie(movieToTranslate.ImdbCode, MovieMethods.Credits); movieToTranslate.Title = movie?.Title; movieToTranslate.Genres = movie?.Genres?.Select(a => a.Name).ToList(); movieToTranslate.DescriptionFull = movie?.Overview; }, ct); } catch (Exception exception) when(exception is TaskCanceledException) { Logger.Debug( "TranslateMovieFull cancelled."); } catch (Exception exception) { Logger.Error( $"TranslateMovieFull: {exception.Message}"); throw; } finally { watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"TranslateMovieFull ({movieToTranslate.ImdbCode}) in {elapsedMs} milliseconds."); } }
/// <summary> /// Download the movie's poster image /// </summary> /// <param name="movie">The movie to process</param> public async Task DownloadPosterImageAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); if (movie.Images == null) { return; } var posterPath = new List <string> { movie.Images.LargeCoverImage }; await posterPath.ForEachAsync( poster => DownloadFileHelper.DownloadFileTaskAsync(poster, Constants.PosterMovieDirectory + movie.ImdbCode + Constants.ImageFileExtension), (poster, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { movie.PosterImagePath = t.Item2; } }); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadPosterImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); }
/// <summary> /// Download actors' image for a movie /// </summary> /// <param name="movie">The movie to process</param> public async Task DownloadActorImageAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); if (movie.Actors == null) { return; } await movie.Actors.ForEachAsync( actor => DownloadFileHelper.DownloadFileTaskAsync(actor.SmallImage, Constants.ActorMovieDirectory + actor.Name + Constants.ImageFileExtension), (actor, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { actor.SmallImagePath = t.Item2; } }); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadActorImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); }
public void Equals_DifferentMovies_ReturnsFalse() { var fixture = new Fixture(); var id1 = fixture.Create <int>(); var dateUploadedUnix1 = fixture.Create <int>(); var id2 = fixture.Create <int>(); var dateUploadedUnix2 = fixture.Create <int>(); var movie1 = new MovieFull { Id = id1, DateUploadedUnix = dateUploadedUnix1 }; var movie2 = new MovieFull { Id = id2, DateUploadedUnix = dateUploadedUnix2 }; Assert.AreEqual( _comparer.Equals(movie1, movie2), false); Assert.AreEqual( _comparer.Equals(movie1, null), false); Assert.AreEqual( _comparer.Equals(movie2, null), false); }
/// <summary> /// Download a subtitle /// </summary> /// <param name="movie">The movie of which to retrieve its subtitles</param> /// <param name="progress">Report the progress of the download</param> /// <param name="ct">Cancellation token</param> public async Task DownloadSubtitleAsync(MovieFull movie, IProgress <long> progress, CancellationTokenSource ct) { if (movie.SelectedSubtitle == null) { return; } var watch = Stopwatch.StartNew(); var filePath = Constants.Subtitles + movie.ImdbCode + "\\" + movie.SelectedSubtitle.Language.EnglishName + ".zip"; try { var result = await DownloadFileHelper.DownloadFileTaskAsync( Constants.YifySubtitles + movie.SelectedSubtitle.Url, filePath, progress : progress, ct : ct); if (result.Item3 == null && !string.IsNullOrEmpty(result.Item2)) { using (var archive = ZipFile.OpenRead(result.Item2)) { foreach (var entry in archive.Entries) { if (entry.FullName.StartsWith("_") || !entry.FullName.EndsWith(".srt", StringComparison.OrdinalIgnoreCase)) { continue; } var subtitlePath = Path.Combine(Constants.Subtitles + movie.ImdbCode, entry.FullName); if (!File.Exists(subtitlePath)) { entry.ExtractToFile(subtitlePath); } movie.SelectedSubtitle.FilePath = subtitlePath; } } } } catch (Exception exception) when(exception is TaskCanceledException) { Logger.Debug( "DownloadSubtitleAsync cancelled."); } catch (Exception exception) { Logger.Error( $"DownloadSubtitleAsync: {exception.Message}"); throw; } finally { watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadSubtitleAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); } }
/// <summary> /// Get the link to the youtube trailer of a movie /// </summary> /// <param name="movie">The movie</param> /// <param name="ct">Used to cancel loading trailer</param> /// <returns>Video trailer</returns> public async Task <ResultContainer <Video> > GetMovieTrailerAsync(MovieFull movie, CancellationToken ct) { var watch = Stopwatch.StartNew(); var trailers = new ResultContainer <Video>(); try { await Task.Run(() => { trailers = TmdbClient.GetMovie(movie.ImdbCode, MovieMethods.Videos)?.Videos; }, ct); } catch (Exception exception) when(exception is TaskCanceledException) { Logger.Debug( "GetMovieTrailerAsync cancelled."); } catch (Exception exception) { Logger.Error( $"GetMovieTrailerAsync: {exception.Message}"); throw; } finally { watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"GetMovieTrailerAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); } return(trailers); }
/// <summary> /// Initializes a new instance of the MoviePlayerViewModel class. /// </summary> /// <param name="movie">Movie to play</param> public MoviePlayerViewModel(MovieFull movie) { RegisterMessages(); RegisterCommands(); Movie = movie; TabName = !string.IsNullOrEmpty(Movie.Title) ? Movie.Title : Properties.Resources.PlayingTitleTab; }
/// <summary> /// Get the link to the youtube trailer of a movie /// </summary> /// <param name="movie">The movie</param> /// <returns>Video trailer</returns> public async Task <ResultContainer <Video> > GetMovieTrailerAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); var trailers = new ResultContainer <Video>(); try { await Task.Run(() => { trailers = TmdbClient.GetMovie(movie.ImdbCode, MovieMethods.Videos)?.Videos; }); } catch (Exception ex) when(ex is SocketException || ex is WebException) { Messenger.Default.Send(new ManageExceptionMessage(ex)); } watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"GetMovieTrailerAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); return(trailers); }
public void GetHashCode_DifferentMovies_ReturnsDifferentHashCode() { var fixture = new Fixture(); var id1 = fixture.Create <int>(); var dateUploadedUnix1 = fixture.Create <int>(); var id2 = fixture.Create <int>(); var dateUploadedUnix2 = fixture.Create <int>(); var movie1 = new MovieFull { Id = id1, DateUploadedUnix = dateUploadedUnix1 }; var movie2 = new MovieFull { Id = id2, DateUploadedUnix = dateUploadedUnix2 }; Assert.AreNotEqual( _comparer.GetHashCode(movie1), _comparer.GetHashCode(movie2)); }
/// <summary> /// Initializes a new instance of the SubtitlesViewModel class. /// </summary> /// <param name="movie">The movie</param> private SubtitlesViewModel(MovieFull movie) { Logger.Debug("Initializing a new instance of SubtitlesViewModel"); CancellationDownloadingSubtitlesToken = new CancellationTokenSource(); MovieService = SimpleIoc.Default.GetInstance<MovieService>(); Movie = movie; }
/// <summary> /// Initializes a new instance of the DownloadMovieViewModel class. /// </summary> /// <param name="movie">The movie to download</param> public DownloadMovieViewModel(MovieFull movie) { RegisterMessages(); RegisterCommands(); CancellationDownloadingMovieToken = new CancellationTokenSource(); MovieService = SimpleIoc.Default.GetInstance <MovieService>(); Movie = movie; MovieSettings = new MovieSettingsViewModel(movie); }
/// <summary> /// Download the movie's background image /// </summary> /// <param name="movie">The movie to process</param> /// <param name="ct">Used to cancel downloading background image</param> public async Task DownloadBackgroundImageAsync(MovieFull movie, CancellationTokenSource ct) { var watch = Stopwatch.StartNew(); try { await Task.Run(async() => { TmdbClient.GetConfig(); var tmdbMovie = TmdbClient.GetMovie(movie.ImdbCode, MovieMethods.Images); var remotePath = new List <string> { TmdbClient.GetImageUrl(Constants.BackgroundImageSizeTmDb, tmdbMovie.BackdropPath).AbsoluteUri }; await remotePath.ForEachAsync( background => DownloadFileHelper.DownloadFileTaskAsync(background, Constants.BackgroundMovieDirectory + movie.ImdbCode + Constants.ImageFileExtension, ct: ct), (background, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { movie.BackgroundImagePath = t.Item2; } }); }, ct.Token); } catch (Exception exception) when(exception is TaskCanceledException) { Logger.Debug( "DownloadBackgroundImageAsync cancelled."); } catch (Exception exception) { Logger.Error( $"DownloadBackgroundImageAsync: {exception.Message}"); throw; } finally { watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadBackgroundImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); } }
public static async Task Initialize(TestContext context) { var moviesCsv = Helpers.GetFromCsv <MovieCsv>(moviesTestDataPath); var castCsv = Helpers.GetFromCsv <CastCsv>(castTestDataPath); var cast = castCsv.GroupBy(k => k.MovieId).ToDictionary(k => k.Key, v => v.ToList()); _moviesWithCast = moviesCsv.Select(m => MovieFull.GetMovieFull(m, cast.ContainsKey(m.TmdbId) ? cast[m.TmdbId] : new List <CastCsv>())).ToList(); //Don't add Cast into the movie document - testing performance vs graph _movies = moviesCsv.Select(m => MovieFull.GetMovieFull(m, new List <CastCsv>())).ToList(); Assert.AreEqual(4802, moviesCsv.Count()); _cosmosClient = await CosmosClientSql.GetByConnectionString(connectionString, databaseId, containerId); }
/// <summary> /// Download the movie's poster image /// </summary> /// <param name="movie">The movie to process</param> /// <param name="ct">Used to cancel downloading poster image</param> public async Task DownloadPosterImageAsync(MovieFull movie, CancellationTokenSource ct) { if (movie.Images == null) { return; } var watch = Stopwatch.StartNew(); var posterPath = new List <string> { movie.Images.LargeCoverImage }; try { await posterPath.ForEachAsync( poster => DownloadFileHelper.DownloadFileTaskAsync(poster, Constants.PosterMovieDirectory + movie.ImdbCode + Constants.ImageFileExtension, ct: ct), (poster, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { movie.PosterImagePath = t.Item2; } }); } catch (Exception exception) when(exception is TaskCanceledException) { Logger.Debug( "DownloadPosterImageAsync cancelled."); } catch (Exception exception) { Logger.Error( $"DownloadPosterImageAsync: {exception.Message}"); throw; } finally { watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadPosterImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); } }
public static void AssertMovieFullIsSame(MovieFull expected, MovieFull actual) { Assert.AreEqual(expected.TmdbId, actual.TmdbId, "Id not matching"); Assert.AreEqual(expected.Title, actual.Title, "Title not matching"); Assert.AreEqual(expected.Tagline, actual.Tagline, "Tagline not matching"); Assert.AreEqual(expected.Runtime, actual.Runtime, "Runtime not matching"); Assert.AreEqual(expected.Revenue, actual.Revenue, "Revenue not matching"); Assert.AreEqual(expected.ReleaseDate, actual.ReleaseDate, "ReleaseDate not matching"); Assert.AreEqual(expected.Overview, actual.Overview, "Overview not matching"); Assert.AreEqual(expected.Language, actual.Language, "Language not matching"); Assert.AreEqual(expected.Keywords.Count(), actual.Keywords.Count(), "Keywords not matching"); Assert.AreEqual(expected.Genres.Count(), actual.Genres.Count(), "Genres not matching"); Assert.AreEqual(expected.Format, actual.Format, "Format not matching"); Assert.AreEqual(expected.Budget, actual.Budget, "Budget not matching"); Assert.AreEqual(expected.Cast.Count, actual.Cast.Count, "Cast not matching"); AssertRatingIsSame(expected.Rating, actual.Rating); }
/// <summary> /// Get the movie's subtitles according to a language /// </summary> /// <param name="movie">The movie of which to retrieve its subtitles</param> /// <param name="ct">Cancellation token</param> public async Task LoadSubtitlesAsync(MovieFull movie, CancellationToken ct) { var restClient = new RestClient(Constants.YifySubtitlesApi); var request = new RestRequest("/{segment}", Method.GET); request.AddUrlSegment("segment", movie.ImdbCode); var response = await restClient.ExecuteGetTaskAsync(request, ct); if (response.ErrorException != null) { Messenger.Default.Send(new ManageExceptionMessage(new Exception(response.ErrorException.Message))); } var wrapper = await Task.Run(() => JsonConvert.DeserializeObject <SubtitlesWrapperDeserialized>(response.Content), ct); var subtitles = new ObservableCollection <Subtitle>(); Dictionary <string, List <SubtitleDeserialized> > movieSubtitles; if (wrapper.Subtitles.TryGetValue(movie.ImdbCode, out movieSubtitles)) { foreach (var subtitle in movieSubtitles) { var sub = subtitle.Value.Aggregate((sub1, sub2) => sub1.Rating > sub2.Rating ? sub1 : sub2); subtitles.Add(new Subtitle { Id = sub.Id, Language = new CustomLanguage { Culture = string.Empty, EnglishName = subtitle.Key, LocalizedName = string.Empty }, Hi = sub.Hi, Rating = sub.Rating, Url = sub.Url }); } } subtitles.Sort(); movie.AvailableSubtitles = subtitles; }
/// <summary> /// Download a subtitle /// </summary> /// <param name="movie">The movie of which to retrieve its subtitles</param> /// <param name="progress">Report the progress of the download</param> /// <param name="ct">Cancellation token</param> public async Task DownloadSubtitleAsync(MovieFull movie, IProgress <long> progress, CancellationTokenSource ct) { if (movie.SelectedSubtitle == null) { return; } var filePath = Constants.Subtitles + movie.ImdbCode + "\\" + movie.SelectedSubtitle.Language.EnglishName + ".zip"; try { var result = await DownloadFileHelper.DownloadFileTaskAsync( Constants.YifySubtitles + movie.SelectedSubtitle.Url, filePath, 10000, progress, ct); if (result.Item3 == null && !string.IsNullOrEmpty(result.Item2)) { using (var archive = ZipFile.OpenRead(result.Item2)) { foreach (var entry in archive.Entries) { if (!entry.FullName.StartsWith("_") && entry.FullName.EndsWith(".srt", StringComparison.OrdinalIgnoreCase)) { var subtitlePath = Path.Combine(Constants.Subtitles + movie.ImdbCode, entry.FullName); if (!File.Exists(subtitlePath)) { entry.ExtractToFile(subtitlePath); } movie.SelectedSubtitle.FilePath = subtitlePath; } } } } } catch (Exception ex) { Logger.Error( $"DownloadSubtitleAsync (failed): {movie.Title}. Additional informations : {ex.Message}"); } }
/// <summary> /// Download actors' image for a movie /// </summary> /// <param name="movie">The movie to process</param> /// <param name="ct">Used to cancel downloading actor image</param> public async Task DownloadCastImageAsync(MovieFull movie, CancellationTokenSource ct) { if (movie.Cast == null) { return; } var watch = Stopwatch.StartNew(); try { await movie.Cast.ForEachAsync( cast => DownloadFileHelper.DownloadFileTaskAsync(cast.SmallImage, Constants.CastMovieDirectory + cast.Name + Constants.ImageFileExtension, ct: ct), (cast, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { cast.SmallImagePath = t.Item2; } }); } catch (Exception exception) when(exception is TaskCanceledException) { Logger.Debug( "DownloadCastImageAsync cancelled."); } catch (Exception exception) { Logger.Error( $"DownloadCastImageAsync: {exception.Message}"); throw; } finally { watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadCastImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); } }
/// <summary> /// Translate movie informations (title, description, ...) /// </summary> /// <param name="movieToTranslate">Movie to translate</param> /// <returns>Task</returns> public async Task TranslateMovieFullAsync(MovieFull movieToTranslate) { var watch = Stopwatch.StartNew(); await Task.Run(() => { var movie = TmdbClient.GetMovie(movieToTranslate.ImdbCode, MovieMethods.Credits); movieToTranslate.Title = movie.Title; movieToTranslate.Genres = movie.Genres.Select(a => a.Name).ToList(); movieToTranslate.DescriptionFull = movie.Overview; }); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"TranslateMovieFull ({movieToTranslate.ImdbCode}) in {elapsedMs} milliseconds."); }
public void GetHashCode_SameMovie_ReturnsSameHashCode() { var fixture = new Fixture(); var movie1 = new MovieFull(); var movie2 = new MovieFull(); var id = fixture.Create <int>(); var dateUploadedUnix = fixture.Create <int>(); movie1.Id = id; movie2.Id = id; movie1.DateUploadedUnix = dateUploadedUnix; movie2.DateUploadedUnix = dateUploadedUnix; Assert.AreEqual( _comparer.GetHashCode(movie1), _comparer.GetHashCode(movie1)); Assert.AreEqual( _comparer.GetHashCode(movie1), _comparer.GetHashCode(movie2)); }
public void Equals_SameMovie_ReturnsTrue() { var fixture = new Fixture(); var movie1 = new MovieFull(); var movie2 = new MovieFull(); var id = fixture.Create <int>(); var dateUploadedUnix = fixture.Create <int>(); movie1.Id = id; movie2.Id = id; movie1.DateUploadedUnix = dateUploadedUnix; movie2.DateUploadedUnix = dateUploadedUnix; Assert.AreEqual( _comparer.Equals(movie1, movie1), true); Assert.AreEqual( _comparer.Equals(movie1, movie2), true); }
public async Task <IActionResult> Index(string id) { var json = await movieServices.GetByIDAsync(id); MovieFull movieFull = JsonConvert.DeserializeObject <MovieFull>(json); var commentsForMovie = _moviedb.Comments.Where(comment => comment.MovieImdbApi == id); List <AppUser> users = new List <AppUser>(); foreach (var comment in commentsForMovie) { var user = await _userManager.FindByIdAsync(comment.UserId); users.Add(user); } MovieInfoViewModel viewModel = new MovieInfoViewModel { Movie = movieFull, comments = commentsForMovie, userEmails = users }; return(View(viewModel)); }
/// <summary> /// Download the movie's background image /// </summary> /// <param name="movie">The movie to process</param> public async Task DownloadBackgroundImageAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); await Task.Run(async() => { try { TmdbClient.GetConfig(); var tmdbMovie = TmdbClient.GetMovie(movie.ImdbCode, MovieMethods.Images); var remotePath = new List <string> { TmdbClient.GetImageUrl(Constants.BackgroundImageSizeTmDb, tmdbMovie.BackdropPath).AbsoluteUri }; await remotePath.ForEachAsync( background => DownloadFileHelper.DownloadFileTaskAsync(background, Constants.BackgroundMovieDirectory + movie.ImdbCode + Constants.ImageFileExtension), (background, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { movie.BackgroundImagePath = t.Item2; } }); } catch (Exception ex) when(ex is SocketException || ex is WebException) { Messenger.Default.Send(new ManageExceptionMessage(ex)); } }); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadBackgroundImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); }
/// <summary> /// Initializes a new instance of the MovieSettingsViewModel class. /// </summary> /// <param name="movie">The movie</param> public MovieSettingsViewModel(MovieFull movie) { Movie = movie; }
/// <summary> /// Get the movie's subtitles /// </summary> /// <param name="movie">The movie</param> /// <returns></returns> private async Task LoadSubtitlesAsync(MovieFull movie) { await MovieService.LoadSubtitlesAsync(movie, CancellationDownloadingSubtitlesToken.Token); }
/// <summary> /// Initializes a new instance of the TrailerViewModel class. /// </summary> /// <param name="movie">Movie's trailer</param> private TrailerViewModel(MovieFull movie) { MovieService = SimpleIoc.Default.GetInstance<MovieService>(); Movie = movie; }
/// <summary> /// Initializes a new instance of the DownloadMovieViewModel class. /// </summary> /// <param name="movie">The movie to download</param> public DownloadMovieViewModel(MovieFull movie) { Logger.Debug("Initializing a new instance of DownloadMovieViewModel"); RegisterMessages(); RegisterCommands(); CancellationDownloadingMovieToken = new CancellationTokenSource(); MovieService = SimpleIoc.Default.GetInstance<MovieService>(); Movie = movie; MovieSettings = new MovieSettingsViewModel(movie); }
/// <summary> /// Download the movie's poster image /// </summary> /// <param name="movie">The movie to process</param> public async Task DownloadPosterImageAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); if (movie.Images == null) return; var posterPath = new List<string> { movie.Images.LargeCoverImage }; try { await posterPath.ForEachAsync( poster => DownloadFileHelper.DownloadFileTaskAsync(poster, Constants.PosterMovieDirectory + movie.ImdbCode + Constants.ImageFileExtension), (poster, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { movie.PosterImagePath = t.Item2; } }); } catch (Exception ex) when (ex is SocketException || ex is WebException) { Logger.Error( $"Error while downloading poster image of the movie {movie.Title}: {ex.Message}"); Messenger.Default.Send(new ManageExceptionMessage(ex)); } watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadPosterImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); }
/// <summary> /// Download a subtitle /// </summary> /// <param name="movie">The movie of which to retrieve its subtitles</param> /// <param name="progress">Report the progress of the download</param> /// <param name="ct">Cancellation token</param> public async Task DownloadSubtitleAsync(MovieFull movie, IProgress<long> progress, CancellationTokenSource ct) { if (movie.SelectedSubtitle == null) return; var filePath = Constants.Subtitles + movie.ImdbCode + "\\" + movie.SelectedSubtitle.Language.EnglishName + ".zip"; try { var result = await DownloadFileHelper.DownloadFileTaskAsync( Constants.YifySubtitles + movie.SelectedSubtitle.Url, filePath, 10000, progress, ct); if (result.Item3 == null && !string.IsNullOrEmpty(result.Item2)) { using (var archive = ZipFile.OpenRead(result.Item2)) { foreach (var entry in archive.Entries) { if (!entry.FullName.StartsWith("_") && entry.FullName.EndsWith(".srt", StringComparison.OrdinalIgnoreCase)) { var subtitlePath = Path.Combine(Constants.Subtitles + movie.ImdbCode, entry.FullName); if (!File.Exists(subtitlePath)) { entry.ExtractToFile(subtitlePath); } movie.SelectedSubtitle.FilePath = subtitlePath; } } } } } catch (Exception ex) { Logger.Error( $"DownloadSubtitleAsync (failed): {movie.Title}. Additional informations : {ex.Message}"); } }
/// <summary> /// Get the link to the youtube trailer of a movie /// </summary> /// <param name="movie">The movie</param> /// <returns>Video trailer</returns> public async Task<ResultContainer<Video>> GetMovieTrailerAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); var trailers = new ResultContainer<Video>(); try { await Task.Run(() => { trailers = TmdbClient.GetMovie(movie.ImdbCode, MovieMethods.Videos)?.Videos; }); } catch (Exception ex) when (ex is SocketException || ex is WebException) { Logger.Error( $"Error while getting the movie's trailer of {movie.Title}: {ex.Message}"); Messenger.Default.Send(new ManageExceptionMessage(ex)); } watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"GetMovieTrailerAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); return trailers; }
/// <summary> /// Download the movie's poster image /// </summary> /// <param name="movie">The movie to process</param> public async Task DownloadPosterImageAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); if (movie.Images == null) return; var posterPath = new List<string> { movie.Images.LargeCoverImage }; await posterPath.ForEachAsync( poster => DownloadFileHelper.DownloadFileTaskAsync(poster, Constants.PosterMovieDirectory + movie.ImdbCode + Constants.ImageFileExtension), (poster, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { movie.PosterImagePath = t.Item2; } }); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadPosterImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); }
/// <summary> /// Get TMDb movie informations /// </summary> /// <param name="movieToLoad">Movie to load</param> /// <param name="ct">Used to cancel loading</param> /// <returns>Movie's full details</returns> public async Task <MovieFull> GetMovieFullDetailsAsync(MovieShort movieToLoad, CancellationToken ct) { var watch = Stopwatch.StartNew(); var movie = new MovieFull(); var restClient = new RestClient(Constants.YtsApiEndpoint); var request = new RestRequest("/{segment}", Method.GET); request.AddUrlSegment("segment", "movie_details.json"); request.AddParameter("movie_id", movieToLoad.Id); request.AddParameter("with_images", true); request.AddParameter("with_cast", true); try { var response = await restClient.ExecuteGetTaskAsync <WrapperMovieFull>(request, ct); if (response.ErrorException != null) { throw response.ErrorException; } await Task.Run(() => { var tmdbInfos = TmdbClient.GetMovie(response.Data.Movie.ImdbCode, MovieMethods.Credits); movie = new MovieFull { Id = response.Data.Movie.Id, Actors = response.Data.Movie.Actors, BackgroundImagePath = string.Empty, DateUploaded = response.Data.Movie.DateUploaded, DateUploadedUnix = response.Data.Movie.DateUploadedUnix, DescriptionFull = tmdbInfos.Overview, DescriptionIntro = response.Data.Movie.DescriptionIntro, Directors = response.Data.Movie.Directors, DownloadCount = response.Data.Movie.DownloadCount, FullHdAvailable = response.Data.Movie.Torrents.Any(torrent => torrent.Quality == "1080p"), Genres = tmdbInfos.Genres.Select(a => a.Name).ToList(), Images = response.Data.Movie.Images, ImdbCode = response.Data.Movie.ImdbCode, Language = response.Data.Movie.Language, LikeCount = response.Data.Movie.LikeCount, MpaRating = response.Data.Movie.MpaRating, PosterImagePath = string.Empty, RatingValue = response.Data.Movie.Rating, RtAudienceRating = response.Data.Movie.RtAudienceRating, RtAudienceScore = response.Data.Movie.RtAudienceScore, RtCriticsRating = response.Data.Movie.RtCriticsRating, RtCrtiticsScore = response.Data.Movie.RtCrtiticsScore, Runtime = response.Data.Movie.Runtime, Title = tmdbInfos.Title, TitleLong = response.Data.Movie.TitleLong, Torrents = response.Data.Movie.Torrents, Url = response.Data.Movie.Url, WatchInFullHdQuality = false, Year = response.Data.Movie.Year, YtTrailerCode = response.Data.Movie.YtTrailerCode }; }, ct); } catch (Exception exception) when(exception is TaskCanceledException) { Logger.Debug( "GetMovieFullDetailsAsync cancelled."); } catch (Exception exception) { Logger.Error( $"GetMovieFullDetailsAsync: {exception.Message}"); throw; } finally { watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"GetMovieFullDetailsAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); } return(movie); }
/// <summary> /// Initializes a new instance of the MovieSettingsViewModel class. /// </summary> /// <param name="movie">The movie</param> public MovieSettingsViewModel(MovieFull movie) { Logger.Debug("Initializing a new instance of MovieSettingsViewModel"); Movie = movie; }
/// <summary> /// Download actors' image for a movie /// </summary> /// <param name="movie">The movie to process</param> public async Task DownloadActorImageAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); if (movie.Actors == null) return; await movie.Actors.ForEachAsync( actor => DownloadFileHelper.DownloadFileTaskAsync(actor.SmallImage, Constants.ActorMovieDirectory + actor.Name + Constants.ImageFileExtension), (actor, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { actor.SmallImagePath = t.Item2; } }); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadActorImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); }
/// <summary> /// Get the movie's subtitles /// </summary> /// <param name="movie">The movie</param> /// <returns></returns> private async Task LoadSubtitlesAsync(MovieFull movie) { Logger.Info( $"Load subtitles for movie: {movie.Title}"); await MovieService.LoadSubtitlesAsync(movie, CancellationDownloadingSubtitlesToken.Token); }
/// <summary> /// Initialize asynchronously an instance of the SubtitlesViewModel class /// </summary> /// <param name="movie">The movie</param> /// <returns>Instance of SubtitlesViewModel</returns> public static Task<SubtitlesViewModel> CreateAsync(MovieFull movie) { var ret = new SubtitlesViewModel(movie); return ret.InitializeAsync(); }
/// <summary> /// Get TMDb movie informations /// </summary> /// <param name="movieToLoad">Movie to load</param> /// <returns>Movie's full details</returns> public async Task<MovieFull> GetMovieFullDetailsAsync(MovieShort movieToLoad) { var watch = Stopwatch.StartNew(); var restClient = new RestClient(Constants.YtsApiEndpoint); var request = new RestRequest("/{segment}", Method.GET); request.AddUrlSegment("segment", "movie_details.json"); request.AddParameter("movie_id", movieToLoad.Id); request.AddParameter("with_images", true); request.AddParameter("with_cast", true); var response = await restClient.ExecuteGetTaskAsync(request); if (response.ErrorException != null) { Logger.Error( $"Error while loading the movie {movieToLoad.Title}: {response.ErrorException.Message}"); Messenger.Default.Send(new ManageExceptionMessage(new WebException(response.ErrorException.Message))); } var movie = new MovieFull(); await Task.Run(() => { var wrapper = JsonConvert.DeserializeObject<WrapperMovieFullDeserialized>(response.Content); if (wrapper == null) return; var tmdbInfos = TmdbClient.GetMovie(wrapper.Movie.ImdbCode, MovieMethods.Credits); var rating = Convert.ToDouble(wrapper.Movie.Rating, CultureInfo.InvariantCulture); rating /= 2.0; movie = new MovieFull { Id = wrapper.Movie.Id, Actors = wrapper.Movie.Actors, BackgroundImagePath = string.Empty, DateUploaded = wrapper.Movie.DateUploaded, DateUploadedUnix = wrapper.Movie.DateUploadedUnix, DescriptionFull = tmdbInfos.Overview, DescriptionIntro = wrapper.Movie.DescriptionIntro, Directors = wrapper.Movie.Directors, DownloadCount = wrapper.Movie.DownloadCount, FullHdAvailable = wrapper.Movie.Torrents.Any(torrent => torrent.Quality == "1080p"), Genres = tmdbInfos.Genres.Select(a => a.Name).ToList(), Images = wrapper.Movie.Images, ImdbCode = wrapper.Movie.ImdbCode, Language = wrapper.Movie.Language, LikeCount = wrapper.Movie.LikeCount, MpaRating = wrapper.Movie.MpaRating, PosterImagePath = string.Empty, RatingValue = rating, RtAudienceRating = wrapper.Movie.RtAudienceRating, RtAudienceScore = wrapper.Movie.RtAudienceScore, RtCriticsRating = wrapper.Movie.RtCriticsRating, RtCrtiticsScore = wrapper.Movie.RtCrtiticsScore, Runtime = wrapper.Movie.Runtime, Title = tmdbInfos.Title, TitleLong = wrapper.Movie.TitleLong, Torrents = wrapper.Movie.Torrents, Url = wrapper.Movie.Url, WatchInFullHdQuality = false, Year = wrapper.Movie.Year, YtTrailerCode = wrapper.Movie.YtTrailerCode }; }); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"GetMovieFullDetails ({movie.ImdbCode}) in {elapsedMs} milliseconds."); return movie; }
/// <summary> /// Constructor /// </summary> /// <param name="movie">The movie</param> public ChangeHasBeenSeenMovieMessage(MovieFull movie) { Movie = movie; }
/// <summary> /// Translate movie informations (title, description, ...) /// </summary> /// <param name="movieToTranslate">Movie to translate</param> /// <returns>Task</returns> public async Task TranslateMovieFullAsync(MovieFull movieToTranslate) { var watch = Stopwatch.StartNew(); await Task.Run(() => { var movie = TmdbClient.GetMovie(movieToTranslate.ImdbCode, MovieMethods.Credits); movieToTranslate.Title = movie.Title; movieToTranslate.Genres = movie.Genres.Select(a => a.Name).ToList(); movieToTranslate.DescriptionFull = movie.Overview; }); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"TranslateMovieFull ({movieToTranslate.ImdbCode}) in {elapsedMs} milliseconds."); }
/// <summary> /// Get the movie's subtitles according to a language /// </summary> /// <param name="movie">The movie of which to retrieve its subtitles</param> /// <param name="ct">Cancellation token</param> public async Task LoadSubtitlesAsync(MovieFull movie, CancellationToken ct) { var watch = Stopwatch.StartNew(); var restClient = new RestClient(Constants.YifySubtitlesApi); var request = new RestRequest("/{segment}", Method.GET); request.AddUrlSegment("segment", movie.ImdbCode); try { var response = await restClient.ExecuteGetTaskAsync <SubtitlesWrapper>(request, ct); if (response.ErrorException != null) { throw response.ErrorException; } var wrapper = response.Data; var subtitles = new ObservableCollection <Subtitle>(); Dictionary <string, List <Subtitle> > movieSubtitles; if (wrapper.Subtitles.TryGetValue(movie.ImdbCode, out movieSubtitles)) { foreach (var subtitle in movieSubtitles) { var sub = subtitle.Value.Aggregate((sub1, sub2) => sub1.Rating > sub2.Rating ? sub1 : sub2); subtitles.Add(new Subtitle { Id = sub.Id, Language = new CustomLanguage { Culture = string.Empty, EnglishName = subtitle.Key, LocalizedName = string.Empty }, Hi = sub.Hi, Rating = sub.Rating, Url = sub.Url }); } } subtitles.Sort(); movie.AvailableSubtitles = subtitles; } catch (Exception exception) when(exception is TaskCanceledException) { Logger.Debug( "LoadSubtitlesAsync cancelled."); } catch (Exception exception) { Logger.Error( $"LoadSubtitlesAsync: {exception.Message}"); throw; } finally { watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"LoadSubtitlesAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); } }
/// <summary> /// Get the movie's subtitles according to a language /// </summary> /// <param name="movie">The movie of which to retrieve its subtitles</param> /// <param name="ct">Cancellation token</param> public async Task LoadSubtitlesAsync(MovieFull movie, CancellationToken ct) { var restClient = new RestClient(Constants.YifySubtitlesApi); var request = new RestRequest("/{segment}", Method.GET); request.AddUrlSegment("segment", movie.ImdbCode); var response = await restClient.ExecuteGetTaskAsync(request, ct); if (response.ErrorException != null) { Logger.Error( $"Error while getting the movie's subtitles of {movie.Title}: {response.ErrorException.Message}"); Messenger.Default.Send(new ManageExceptionMessage(new Exception(response.ErrorException.Message))); } var wrapper = await Task.Run(() => JsonConvert.DeserializeObject<SubtitlesWrapperDeserialized>(response.Content), ct); var subtitles = new ObservableCollection<Subtitle>(); Dictionary<string, List<SubtitleDeserialized>> movieSubtitles; if (wrapper.Subtitles.TryGetValue(movie.ImdbCode, out movieSubtitles)) { foreach (var subtitle in movieSubtitles) { var sub = subtitle.Value.Aggregate((sub1, sub2) => sub1.Rating > sub2.Rating ? sub1 : sub2); subtitles.Add(new Subtitle { Id = sub.Id, Language = new CustomLanguage { Culture = string.Empty, EnglishName = subtitle.Key, LocalizedName = string.Empty }, Hi = sub.Hi, Rating = sub.Rating, Url = sub.Url }); } } subtitles.Sort(); movie.AvailableSubtitles = subtitles; }
/// <summary> /// Initializes a new instance of the TrailerViewModel class. /// </summary> /// <param name="movie">Movie's trailer</param> private TrailerViewModel(MovieFull movie) { Logger.Debug("Initializing a new instance of TrailerViewModel"); MovieService = SimpleIoc.Default.GetInstance<MovieService>(); Movie = movie; }
/// <summary> /// Download the movie's background image /// </summary> /// <param name="movie">The movie to process</param> public async Task DownloadBackgroundImageAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); await Task.Run(async () => { try { TmdbClient.GetConfig(); var tmdbMovie = TmdbClient.GetMovie(movie.ImdbCode, MovieMethods.Images); var remotePath = new List<string> { TmdbClient.GetImageUrl(Constants.BackgroundImageSizeTmDb, tmdbMovie.BackdropPath).AbsoluteUri }; await remotePath.ForEachAsync( background => DownloadFileHelper.DownloadFileTaskAsync(background, Constants.BackgroundMovieDirectory + movie.ImdbCode + Constants.ImageFileExtension), (background, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { movie.BackgroundImagePath = t.Item2; } }); } catch (Exception ex) when (ex is SocketException || ex is WebException) { Logger.Error( $"Error while downloading background image of the movie {movie.Title}: {ex.Message}"); Messenger.Default.Send(new ManageExceptionMessage(ex)); } }); watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadBackgroundImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); }
/// <summary> /// Get trailer of a movie /// </summary> /// <param name="movie">The movie</param> /// <param name="ct">Cancellation token</param> private async Task LoadTrailerAsync(MovieFull movie, CancellationTokenSource ct) { await Task.Run(async () => { Logger.Info( $"Loading movie's trailer: {movie.Title}"); // Inform subscribers we are loading movie trailer try { // Retrieve trailer from API var trailer = await MovieService.GetMovieTrailerAsync(movie); // No error has been encounter, we can create our VideoInfo VideoInfo video = null; try { // Retrieve Youtube Infos video = await GetVideoInfoForStreamingAsync( Constants.YoutubePath + trailer.Results.FirstOrDefault()?.Key, Constants.YoutubeStreamingQuality.High); if (video != null && video.RequiresDecryption) { Logger.Info( $"Decrypting Youtube trailer url: {video.Title}"); // Decrypt encoded Youtube video link await Task.Run(() => DownloadUrlResolver.DecryptDownloadUrl(video)); } } catch (Exception ex) { if (ex is WebException || ex is VideoNotAvailableException || ex is YoutubeParseException) { Logger.Info( $"Failed loading movie's trailer: {movie.Title}"); if (ex is VideoNotAvailableException) Messenger.Default.Send( new ManageExceptionMessage( new Exception( LocalizationProviderHelper.GetLocalizedValue<string>("TrailerNotAvailable")))); Messenger.Default.Send(new StopPlayingTrailerMessage()); return; } } if (video == null) { Logger.Info( $"Failed loading movie's trailer: {movie.Title}"); Messenger.Default.Send( new ManageExceptionMessage( new Exception(LocalizationProviderHelper.GetLocalizedValue<string>("TrailerNotAvailable")))); Messenger.Default.Send(new StopPlayingTrailerMessage()); return; } if (!ct.IsCancellationRequested) { Logger.Info( $"Movie's trailer loaded: {movie.Title}"); TrailerPlayer = new TrailerPlayerViewModel(new Models.Trailer.Trailer(new Uri(video.DownloadUrl))); } } catch (WebException e) { Messenger.Default.Send(new StopPlayingTrailerMessage()); Messenger.Default.Send(new ManageExceptionMessage(e)); } catch (Exception) { Messenger.Default.Send(new StopPlayingTrailerMessage()); } }, ct.Token); }
/// <summary> /// Download actors' image for a movie /// </summary> /// <param name="movie">The movie to process</param> public async Task DownloadActorImageAsync(MovieFull movie) { var watch = Stopwatch.StartNew(); if (movie.Actors == null) return; try { await movie.Actors.ForEachAsync( actor => DownloadFileHelper.DownloadFileTaskAsync(actor.SmallImage, Constants.ActorMovieDirectory + actor.Name + Constants.ImageFileExtension), (actor, t) => { if (t.Item3 == null && !string.IsNullOrEmpty(t.Item2)) { actor.SmallImagePath = t.Item2; } }); } catch (Exception ex) when (ex is SocketException || ex is WebException) { Logger.Error( $"Error while downloading an actor image of the movie {movie.Title}: {ex.Message}"); Messenger.Default.Send(new ManageExceptionMessage(ex)); } watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Logger.Debug( $"DownloadActorImageAsync ({movie.ImdbCode}) in {elapsedMs} milliseconds."); }
/// <summary> /// Initialize asynchronously an instance of the TrailerViewModel class /// </summary> /// <param name="movie">The movie</param> /// <param name="ct">Cancellation token</param> /// <returns>Instance of TrailerViewModel</returns> public static Task<TrailerViewModel> CreateAsync(MovieFull movie, CancellationTokenSource ct) { var ret = new TrailerViewModel(movie); return ret.InitializeAsync(ct); }
/// <summary> /// Download a movie /// </summary> /// <param name="movie">The movie to download</param> /// <param name="downloadProgress">Report download progress</param> /// <param name="downloadRate">Report download rate</param> /// <param name="ct">Cancellation token</param> private async Task DownloadMovieAsync(MovieFull movie, IProgress<double> downloadProgress, IProgress<double> downloadRate, CancellationToken ct) { await Task.Run(async () => { using (var session = new Session()) { Logger.Debug( $"Start downloading movie : {movie.Title}"); IsDownloadingMovie = true; session.ListenOn(6881, 6889); var torrentUrl = movie.WatchInFullHdQuality ? movie.Torrents?.FirstOrDefault(torrent => torrent.Quality == "1080p")?.Url : movie.Torrents?.FirstOrDefault(torrent => torrent.Quality == "720p")?.Url; var addParams = new AddTorrentParams { SavePath = Constants.MovieDownloads, Url = torrentUrl, DownloadLimit = SimpleIoc.Default.GetInstance<SettingsViewModel>().DownloadLimit*1024, UploadLimit = SimpleIoc.Default.GetInstance<SettingsViewModel>().UploadLimit*1024 }; var handle = session.AddTorrent(addParams); // We have to download sequentially, so that we're able to play the movie without waiting handle.SequentialDownload = true; var alreadyBuffered = false; while (IsDownloadingMovie) { var status = handle.QueryStatus(); var progress = status.Progress*100.0; downloadProgress?.Report(progress); var test = Math.Round(status.DownloadRate/1024.0, 0); downloadRate?.Report(test); handle.FlushCache(); if (handle.NeedSaveResumeData()) { handle.SaveResumeData(); } if (progress >= Constants.MinimumBufferingBeforeMoviePlaying && !alreadyBuffered) { // Get movie file foreach ( var filePath in Directory.GetFiles(status.SavePath + handle.TorrentFile.Name, "*" + Constants.VideoFileExtension) ) { alreadyBuffered = true; movie.FilePath = new Uri(filePath); Messenger.Default.Send(new PlayMovieMessage(movie)); } } try { await Task.Delay(1000, ct); } catch (TaskCanceledException) { break; } } } }, ct); }
/// <summary> /// Constructor /// </summary> /// <param name="movie">The movie</param> public PlayMovieMessage(MovieFull movie) { Movie = movie; }
/// <summary> /// DownloadMovieMessage /// </summary> /// <param name="movie">The movie to download</param> public DownloadMovieMessage(MovieFull movie) { Movie = movie; }
/// <summary> /// Initializes a new instance of the SubtitlesViewModel class. /// </summary> /// <param name="movie">The movie</param> private SubtitlesViewModel(MovieFull movie) { CancellationDownloadingSubtitlesToken = new CancellationTokenSource(); MovieService = SimpleIoc.Default.GetInstance<MovieService>(); Movie = movie; }