Esempio n. 1
0
        private IEnumerable <DownloadDecision> GetDecisions(List <ReleaseInfo> reports, SearchCriteriaBase searchCriteria = null)
        {
            if (reports.Any())
            {
                _logger.ProgressInfo("Processing {0} releases", reports.Count);
            }

            else
            {
                _logger.ProgressInfo("No results found");
            }

            var reportNumber = 1;

            foreach (var report in reports)
            {
                DownloadDecision decision = null;
                _logger.ProgressTrace("Processing release {0}/{1}", reportNumber, reports.Count);
                _logger.Debug("Processing release '{0}' from '{1}'", report.Title, report.Indexer);

                try
                {
                    var parsedEpisodeInfo = Parser.Parser.ParseTitle(report.Title);

                    if (parsedEpisodeInfo == null || parsedEpisodeInfo.IsPossibleSpecialEpisode)
                    {
                        var specialEpisodeInfo = _parsingService.ParseSpecialEpisodeTitle(parsedEpisodeInfo, report.Title, report.TvdbId, report.TvRageId, searchCriteria);

                        if (specialEpisodeInfo != null)
                        {
                            parsedEpisodeInfo = specialEpisodeInfo;
                        }
                    }

                    if (parsedEpisodeInfo != null && !parsedEpisodeInfo.SeriesTitle.IsNullOrWhiteSpace())
                    {
                        var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, report.TvdbId, report.TvRageId, searchCriteria);
                        remoteEpisode.Release = report;

                        if (remoteEpisode.Series == null)
                        {
                            var reason         = "Unknown Series";
                            var matchingTvdbId = _sceneMappingService.FindTvdbId(parsedEpisodeInfo.SeriesTitle, parsedEpisodeInfo.ReleaseTitle);

                            if (matchingTvdbId.HasValue)
                            {
                                reason = $"{parsedEpisodeInfo.SeriesTitle} matches an alias for series with TVDB ID: {matchingTvdbId}";
                            }

                            decision = new DownloadDecision(remoteEpisode, new Rejection(reason));
                        }
                        else if (remoteEpisode.Episodes.Empty())
                        {
                            decision = new DownloadDecision(remoteEpisode, new Rejection("Unable to identify correct episode(s) using release name and scene mappings"));
                        }
                        else
                        {
                            _aggregationService.Augment(remoteEpisode);
                            remoteEpisode.DownloadAllowed = remoteEpisode.Episodes.Any();
                            decision = GetDecisionForReport(remoteEpisode, searchCriteria);
                        }
                    }

                    if (searchCriteria != null)
                    {
                        if (parsedEpisodeInfo == null)
                        {
                            parsedEpisodeInfo = new ParsedEpisodeInfo
                            {
                                Language = LanguageParser.ParseLanguage(report.Title),
                                Quality  = QualityParser.ParseQuality(report.Title)
                            };
                        }

                        if (parsedEpisodeInfo.SeriesTitle.IsNullOrWhiteSpace())
                        {
                            var remoteEpisode = new RemoteEpisode
                            {
                                Release           = report,
                                ParsedEpisodeInfo = parsedEpisodeInfo
                            };

                            decision = new DownloadDecision(remoteEpisode, new Rejection("Unable to parse release"));
                        }
                    }
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Couldn't process release.");

                    var remoteEpisode = new RemoteEpisode {
                        Release = report
                    };
                    decision = new DownloadDecision(remoteEpisode, new Rejection("Unexpected error processing release"));
                }

                reportNumber++;

                if (decision != null)
                {
                    if (decision.Rejections.Any())
                    {
                        _logger.Debug("Release rejected for the following reasons: {0}", string.Join(", ", decision.Rejections));
                    }

                    else
                    {
                        _logger.Debug("Release accepted");
                    }

                    yield return(decision);
                }
            }
        }
Esempio n. 2
0
        public void Read(string path)
        {
            Logger.Debug($"Starting tag read for {path}");

            IsValid = false;
            TagLib.File file = null;
            try
            {
                file = TagLib.File.Create(path);
                var tag = file.Tag;

                Title        = tag.Title ?? tag.TitleSort;
                Performers   = tag.Performers ?? tag.PerformersSort;
                AlbumArtists = tag.AlbumArtists ?? tag.AlbumArtistsSort;
                Track        = tag.Track;
                TrackCount   = tag.TrackCount;
                Album        = tag.Album ?? tag.AlbumSort;
                Disc         = tag.Disc;
                DiscCount    = tag.DiscCount;
                Year         = tag.Year;
                Publisher    = tag.Publisher;
                Duration     = file.Properties.Duration;
                Genres       = tag.Genres;
                ImageSize    = tag.Pictures.FirstOrDefault()?.Data.Count ?? 0;
                MusicBrainzReleaseCountry  = tag.MusicBrainzReleaseCountry;
                MusicBrainzReleaseStatus   = tag.MusicBrainzReleaseStatus;
                MusicBrainzReleaseType     = tag.MusicBrainzReleaseType;
                MusicBrainzReleaseId       = tag.MusicBrainzReleaseId;
                MusicBrainzArtistId        = tag.MusicBrainzArtistId;
                MusicBrainzReleaseArtistId = tag.MusicBrainzReleaseArtistId;
                MusicBrainzReleaseGroupId  = tag.MusicBrainzReleaseGroupId;
                MusicBrainzTrackId         = tag.MusicBrainzTrackId;

                DateTime tempDate;

                // Do the ones that aren't handled by the generic taglib implementation
                if (file.TagTypesOnDisk.HasFlag(TagTypes.Id3v2))
                {
                    var id3tag = (TagLib.Id3v2.Tag)file.GetTag(TagTypes.Id3v2);
                    Media = id3tag.GetTextAsString("TMED");
                    Date  = ReadId3Date(id3tag, "TDRC");
                    OriginalReleaseDate       = ReadId3Date(id3tag, "TDOR");
                    MusicBrainzAlbumComment   = UserTextInformationFrame.Get(id3tag, "MusicBrainz Album Comment", false)?.Text.ExclusiveOrDefault();
                    MusicBrainzReleaseTrackId = UserTextInformationFrame.Get(id3tag, "MusicBrainz Release Track Id", false)?.Text.ExclusiveOrDefault();
                }
                else if (file.TagTypesOnDisk.HasFlag(TagTypes.Xiph))
                {
                    // while publisher is handled by taglib, it seems to be mapped to 'ORGANIZATION' and not 'LABEL' like Picard is
                    // https://picard.musicbrainz.org/docs/mappings/
                    var flactag = (TagLib.Ogg.XiphComment)file.GetTag(TagLib.TagTypes.Xiph);
                    Media = flactag.GetField("MEDIA").ExclusiveOrDefault();
                    Date  = DateTime.TryParse(flactag.GetField("DATE").ExclusiveOrDefault(), out tempDate) ? tempDate : default(DateTime?);
                    OriginalReleaseDate       = DateTime.TryParse(flactag.GetField("ORIGINALDATE").ExclusiveOrDefault(), out tempDate) ? tempDate : default(DateTime?);
                    Publisher                 = flactag.GetField("LABEL").ExclusiveOrDefault();
                    MusicBrainzAlbumComment   = flactag.GetField("MUSICBRAINZ_ALBUMCOMMENT").ExclusiveOrDefault();
                    MusicBrainzReleaseTrackId = flactag.GetField("MUSICBRAINZ_RELEASETRACKID").ExclusiveOrDefault();

                    // If we haven't managed to read status/type, try the alternate mapping
                    if (MusicBrainzReleaseStatus.IsNullOrWhiteSpace())
                    {
                        MusicBrainzReleaseStatus = flactag.GetField("RELEASESTATUS").ExclusiveOrDefault();
                    }

                    if (MusicBrainzReleaseType.IsNullOrWhiteSpace())
                    {
                        MusicBrainzReleaseType = flactag.GetField("RELEASETYPE").ExclusiveOrDefault();
                    }
                }
                else if (file.TagTypesOnDisk.HasFlag(TagTypes.Ape))
                {
                    var apetag = (TagLib.Ape.Tag)file.GetTag(TagTypes.Ape);
                    Media = apetag.GetItem("Media")?.ToString();
                    Date  = DateTime.TryParse(apetag.GetItem("Year")?.ToString(), out tempDate) ? tempDate : default(DateTime?);
                    OriginalReleaseDate       = DateTime.TryParse(apetag.GetItem("Original Date")?.ToString(), out tempDate) ? tempDate : default(DateTime?);
                    Publisher                 = apetag.GetItem("Label")?.ToString();
                    MusicBrainzAlbumComment   = apetag.GetItem("MUSICBRAINZ_ALBUMCOMMENT")?.ToString();
                    MusicBrainzReleaseTrackId = apetag.GetItem("MUSICBRAINZ_RELEASETRACKID")?.ToString();
                }
                else if (file.TagTypesOnDisk.HasFlag(TagTypes.Asf))
                {
                    var asftag = (TagLib.Asf.Tag)file.GetTag(TagTypes.Asf);
                    Media = asftag.GetDescriptorString("WM/Media");
                    Date  = DateTime.TryParse(asftag.GetDescriptorString("WM/Year"), out tempDate) ? tempDate : default(DateTime?);
                    OriginalReleaseDate       = DateTime.TryParse(asftag.GetDescriptorString("WM/OriginalReleaseTime"), out tempDate) ? tempDate : default(DateTime?);
                    Publisher                 = asftag.GetDescriptorString("WM/Publisher");
                    MusicBrainzAlbumComment   = asftag.GetDescriptorString("MusicBrainz/Album Comment");
                    MusicBrainzReleaseTrackId = asftag.GetDescriptorString("MusicBrainz/Release Track Id");
                }
                else if (file.TagTypesOnDisk.HasFlag(TagTypes.Apple))
                {
                    var appletag = (TagLib.Mpeg4.AppleTag)file.GetTag(TagTypes.Apple);
                    Media = appletag.GetDashBox("com.apple.iTunes", "MEDIA");
                    Date  = DateTime.TryParse(appletag.DataBoxes(FixAppleId("day")).FirstOrDefault()?.Text, out tempDate) ? tempDate : default(DateTime?);
                    OriginalReleaseDate       = DateTime.TryParse(appletag.GetDashBox("com.apple.iTunes", "Original Date"), out tempDate) ? tempDate : default(DateTime?);
                    MusicBrainzAlbumComment   = appletag.GetDashBox("com.apple.iTunes", "MusicBrainz Album Comment");
                    MusicBrainzReleaseTrackId = appletag.GetDashBox("com.apple.iTunes", "MusicBrainz Release Track Id");
                }

                OriginalYear = OriginalReleaseDate.HasValue ? (uint)OriginalReleaseDate?.Year : 0;

                foreach (ICodec codec in file.Properties.Codecs)
                {
                    IAudioCodec acodec = codec as IAudioCodec;

                    if (acodec != null && (acodec.MediaTypes & MediaTypes.Audio) != MediaTypes.None)
                    {
                        int bitrate = acodec.AudioBitrate;
                        if (bitrate == 0)
                        {
                            // Taglib can't read bitrate for Opus.
                            bitrate = EstimateBitrate(file, path);
                        }

                        Logger.Debug("Audio Properties: " + acodec.Description + ", Bitrate: " + bitrate + ", Sample Size: " +
                                     file.Properties.BitsPerSample + ", SampleRate: " + acodec.AudioSampleRate + ", Channels: " + acodec.AudioChannels);

                        Quality = QualityParser.ParseQuality(file.Name, acodec.Description, bitrate, file.Properties.BitsPerSample);
                        Logger.Debug($"Quality parsed: {Quality}, Source: {Quality.QualityDetectionSource}");

                        MediaInfo = new MediaInfoModel {
                            AudioFormat     = acodec.Description,
                            AudioBitrate    = bitrate,
                            AudioChannels   = acodec.AudioChannels,
                            AudioBits       = file.Properties.BitsPerSample,
                            AudioSampleRate = acodec.AudioSampleRate
                        };
                    }
                }

                IsValid = true;
            }
            catch (Exception ex)
            {
                if (ex is CorruptFileException)
                {
                    Logger.Warn(ex, $"Tag reading failed for {path}.  File is corrupt");
                }
                else
                {
                    // Log as error so it goes to sentry with correct fingerprint
                    Logger.Error(ex, "Tag reading failed for {0}", path);
                }
            }
            finally
            {
                file?.Dispose();
            }

            // make sure these are initialized to avoid errors later on
            if (Quality == null)
            {
                Quality = QualityParser.ParseQuality(path, null, EstimateBitrate(file, path));
                Logger.Debug($"Unable to parse qulity from tag, Quality parsed from file path: {Quality}, Source: {Quality.QualityDetectionSource}");
            }

            MediaInfo = MediaInfo ?? new MediaInfoModel();
        }
 public void should_parse_reality_from_title(string title, int reality)
 {
     QualityParser.ParseQuality(title).Revision.Real.Should().Be(reality);
 }
 public void should_parse_version_from_title(string title, int version)
 {
     QualityParser.ParseQuality(title).Revision.Version.Should().Be(version);
 }
Esempio n. 5
0
 public void should_parse_hardcoded_subs(string postTitle, string sub)
 {
     QualityParser.ParseQuality(postTitle).HardcodedSubs.Should().Be(sub);
 }