예제 #1
0
        public async Task CreateLocalMoviesAsync(ICollection <CreateLocalMovieRequest> requests)
        {
            if (_type != ScraperType.Local)
            {
                throw new InvalidOperationException($"scrape session of type {_type} cannot create local movies");
            }

            var toAdd = requests.Where(x => !LocalImdbCodes.Contains(x.ImdbCode))
                        .Select(x => new LocalMovie
            {
                Source      = _source,
                ImdbCode    = x.ImdbCode.Trim().ToLower(),
                Title       = x.Title,
                Year        = x.Year,
                DateCreated = x.DateCreated,
                DateScraped = _scrapeDate,
                ThumbPath   = x.ThumbPath
            })
                        .ToList();

            if (!toAdd.Any())
            {
                return;
            }

            LocalImdbCodes.AddRange(toAdd.Select(x => x.ImdbCode));
            _context.AddRange(toAdd);

            var downloadedMovies = toAdd
                                   .Join(MovieImdbCodes, lm => lm.ImdbCode, x => x, (lm, x) => new DownloadedMovie
            {
                MovieImdbCode      = x,
                LocalMovieImdbCode = x
            });

            _context.AddRange(downloadedMovies);

            await _context.SaveChangesAsync(_cancellationToken);
        }
예제 #2
0
        public static async Task <ICollection <Genre> > AssertGenresAsync(
            this MolliesMoviesContext context, ICollection <string> toAssert, CancellationToken cancellationToken = default)
        {
            var cleaned = toAssert.Select(x => x.Trim()).ToList();
            var result  = await context.Set <Genre>()
                          .Where(x => cleaned.Contains(x.Name))
                          .ToListAsync(cancellationToken);

            var newGenres = cleaned.Except(result.Select(x => x.Name)).ToList();

            if (newGenres.Any())
            {
                var toAdd = newGenres.Select(x => new Genre {
                    Name = x
                }).ToList();

                result.AddRange(toAdd);
                await context.AddRangeAsync(toAdd, cancellationToken);

                await context.SaveChangesAsync(cancellationToken);
            }

            return(result);
        }
예제 #3
0
        public async Task ScrapeAsync(int id, CancellationToken cancellationToken = default)
        {
            Scrape scrape;

            try
            {
                scrape = await _context.Scrapes().FirstOrDefaultAsync(x => x.Id == id, cancellationToken);

                if (scrape is null)
                {
                    throw new Exception($"cannot find scrape record {id}");
                }
            }
            catch (Exception e)
            {
                _logger.LogError(e, "failed when getting scrape record {id}", id);
                // TODO requeue on db fail
                return;
            }

            scrape.ScrapeSources = new List <ScrapeSource>();
            IScrapeSession session = null;

            foreach (var scraper in _scrapers)
            {
                var source = new ScrapeSource
                {
                    Source    = scraper.Source,
                    Type      = scraper.Type,
                    StartDate = _clock.UtcNow
                };
                scrape.ScrapeSources.Add(source);

                try
                {
                    session = await _movieService.GetScrapeSessionAsync(scraper.Source, scraper.Type, session, cancellationToken);

                    var result = await scraper.ScrapeAsync(session, cancellationToken);

                    source.Success      = true;
                    source.EndDate      = _clock.UtcNow;
                    source.MovieCount   = result.MovieCount;
                    source.TorrentCount = result.TorrentCount;

                    switch (scraper.Type)
                    {
                    case ScraperType.Local:
                        scrape.LocalMovieCount += result.MovieCount;
                        break;

                    case ScraperType.Torrent:
                        scrape.MovieCount   += result.MovieCount;
                        scrape.TorrentCount += result.TorrentCount;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
                catch (Exception e)
                {
                    _logger.LogError(e, "failed to scrape {source}", scraper.Source);
                    source.Success = false;
                    source.EndDate = _clock.UtcNow;
                    source.Error   = e.ToString();
                }
            }

            try
            {
                scrape.ImageCount = await ScrapeImagesAsync(session, cancellationToken);
            }
            catch (Exception e)
            {
                _logger.LogError(e, "failed to scrape images");
            }

            scrape.Success = scrape.ScrapeSources.All(x => x.Success);
            scrape.EndDate = _clock.UtcNow;
            await _context.SaveChangesAsync(cancellationToken);
        }
예제 #4
0
        public async Task DownloadMovieTorrentAsync(int movieId, int torrentId, CancellationToken cancellationToken = default)
        {
            var options = _options.Value;
            var movie   = await _movieService.GetAsync(movieId, cancellationToken);

            var torrent = movie.MovieSources
                          .SelectMany(x => x.Torrents)
                          .FirstOrDefault(x => x.Id == torrentId);

            if (torrent is null)
            {
                throw BadRequestException.Create($"torrent with id {torrentId} does not exist on movie with id {movieId}");
            }

            if (!(movie.LocalMovie is null))
            {
                throw BadRequestException.Create($"movie with id {movieId} is already downloaded");
            }

            if (movie.TransmissionStatus.HasValue)
            {
                throw BadRequestException.Create($"movie with id {movieId} is currently downloading");
            }

            var torrentName = $"{movie.Title} ({movie.Year})";

            var client   = new Client(options.RpcUri.ToString());
            var torrents = await client.TorrentGetAsync(TorrentFields.ALL_FIELDS);

            if (torrents.Torrents.Any(x => x.Name == torrentName))
            {
                throw BadRequestException.Create($"movie with id {movieId} is currently downloading");
            }

            // get magnet uri
            var trs       = string.Join('&', options.Trackers.Select(x => $"tr={x}"));
            var magnetUri = $"magnet:?xt=urn:btih:{torrent.Hash}&dn={Uri.EscapeDataString(torrentName)}&{trs}";

            var result = await client.TorrentAddAsync(new NewTorrent
            {
                Filename = magnetUri
            });

            _logger.LogInformation("added torrent {name}", result.Name);

            var context = new TransmissionContext
            {
                ExternalId = result.ID,
                Name       = result.Name,
                MagnetUri  = magnetUri,
                MovieId    = movie.Id,
                TorrentId  = torrent.Id,
                Statuses   = new List <TransmissionContextStatus> {
                    GetStatus(TransmissionStatusCode.Started)
                }
            };

            _context.Add(context);
            await _context.SaveChangesAsync(cancellationToken);

            _logger.LogInformation("saved context for torrent {name}", result.Name);
        }