/// <summary> /// Main process method for the InnerBlock /// </summary> /// <remarks> /// - SingleResources are just passed to the next DataflowBlock /// - If it's not a SingleResource /// - it finds all the files in the current directory, /// - in case of a RefreshImport /// - it deletes all the files in the MediaLibrary that do not exist anymore in the filesystem, /// - it stores the DateOfLastImport of all the files in the <see cref="PendingImportResourceNewGen"/> /// </remarks> /// <param name="importResource"><see cref="PendingImportResourceNewGen"/> to be processed</param> /// <returns> /// a HashSet of <see cref="PendingImportResourceNewGen"/>s containing the current <see cref="PendingImportResource"/> /// after processing as well as <see cref="PendingImportResourceNewGen"/>s for all files in the current directory /// </returns> private async Task <IEnumerable <PendingImportResourceNewGen> > ProcessChanges(PendingImportResourceNewGen importResource) { var result = new HashSet <PendingImportResourceNewGen> { importResource }; try { if (ImportJobInformation.JobType == ImportJobType.Refresh) { // ReSharper disable once PossibleInvalidOperationException IEnumerable <MediaItem> mediaItems = await GetUpdatableMediaItems(PROVIDERRESOURCE_IMPORTER_MIA_ID_ENUMERATION, null); if (mediaItems != null) { foreach (MediaItem mi in mediaItems) { IList <MultipleMediaItemAspect> providerAspects = null; if (MediaItemAspect.TryGetAspects(mi.Aspects, ProviderResourceAspect.Metadata, out providerAspects)) { ResourcePath path = ResourcePath.Deserialize(providerAspects[0].GetAttributeValue <String>(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH)); Guid? directoryId = providerAspects[0].GetAttributeValue <Guid?>(ProviderResourceAspect.ATTR_PARENT_DIRECTORY_ID); IResourceAccessor ra; if (path.TryCreateLocalResourceAccessor(out ra) && ra is IFileSystemResourceAccessor) { IFileSystemResourceAccessor f = ra as IFileSystemResourceAccessor; string dirPath = ResourcePathHelper.GetDirectoryName(ra.Path); ResourcePath dirRa = ResourcePath.BuildBaseProviderPath(ra.ParentProvider.Metadata.ResourceProviderId, dirPath); PendingImportResourceNewGen pir = new PendingImportResourceNewGen(dirRa, f, ToString(), ParentImportJobController, directoryId, mi.MediaItemId); pir.DateOfLastImport = DateTime.MinValue; //Force update result.Add(pir); } } } } } return(result); } catch (TaskCanceledException) { return(result); } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Warn("ImporterWorker.{0}.{1}: Error while processing {2}", ex, ParentImportJobController, ToString(), importResource); importResource.IsValid = false; return(result); } }
/// <summary> /// Tries to create a <see cref="IFileSystemResourceAccessor"/> for the directory of a given file. /// </summary> /// <param name="fsra">IFileSystemResourceAccessor of file.</param> /// <returns>IFileSystemResourceAccessor or <c>null</c>, if no fsra could be created.</returns> private static IFileSystemResourceAccessor GetContainingDirectory(IFileSystemResourceAccessor fsra) { string filePath = fsra.CanonicalLocalResourcePath.ToString(); string directoryPath = ResourcePathHelper.GetDirectoryName(filePath); IResourceAccessor metaFileAccessor; if (!ResourcePath.Deserialize(directoryPath).TryCreateLocalResourceAccessor(out metaFileAccessor)) { return(null); } if (!(metaFileAccessor is IFileSystemResourceAccessor)) { metaFileAccessor.Dispose(); return(null); } return((IFileSystemResourceAccessor)metaFileAccessor); }
protected virtual async Task <bool> SaveSubtitleAsync(SubtitleInfo subtitle, IDictionary <BaseSubtitleMatch <TId>, byte[]> downloads, bool overwriteExisting) { var mediaFile = subtitle.MediaFiles.First(); var namingTemplate = ResourcePath.GetFileNameWithoutExtension(mediaFile.NativeResourcePath.FileName); var templatePartMatch = _regexMultiPartVideo.Match(namingTemplate); foreach (var subtitleMatch in downloads.Keys) { var subPartMatch = _regexMultiPartVideo.Match(subtitleMatch.ItemName); string subName = namingTemplate; if (subPartMatch.Success && templatePartMatch.Success) { if (!int.TryParse(templatePartMatch.Groups["disc"].Value, out var _) || !int.TryParse(subPartMatch.Groups["disc"].Value, out var partNum)) { continue; } subName = _regexMultiPartVideo.Replace(namingTemplate, "${1}${2}${4}" + partNum + "${3}"); } string lang = new CultureInfo(subtitleMatch.Language).EnglishName; var dir = ResourcePathHelper.GetDirectoryName(mediaFile.NativeResourcePath.Serialize()); var sub = $"{subName}.{lang}{Path.GetExtension(subtitleMatch.ItemName)}"; ResourcePath subtitlePath = ResourcePath.Deserialize(dir); //File based access var resLoc = new ResourceLocator(mediaFile.NativeSystemId, subtitlePath); using (IResourceAccessor mediaItemAccessor = resLoc.CreateAccessor()) using (LocalFsResourceAccessorHelper rah = new LocalFsResourceAccessorHelper(mediaItemAccessor)) using (rah.LocalFsResourceAccessor.EnsureLocalFileSystemAccess()) { using (var stream = rah.LocalFsResourceAccessor.CreateOpenWrite(sub, overwriteExisting)) { var bytes = downloads[subtitleMatch]; if (stream != null) { await stream.WriteAsync(bytes, 0, bytes.Length); } } } } return(true); }
/// <summary> /// Tries to read a valid IMDB id from additional .nfo or .txt files. /// </summary> /// <param name="fsra">FileSystemResourceAccessor</param> /// <param name="imdbId">Returns a valid IMDB or <c>null</c></param> /// <returns>true if matched</returns> public static bool TryMatchImdbId(IFileSystemResourceAccessor fsra, out string imdbId) { imdbId = null; if (fsra == null) { return(false); } // First try to find a nfo file that has the same name as our main movie. if (fsra.IsFile) { foreach (string extension in NFO_EXTENSIONS) { string metaFilePath = ResourcePathHelper.ChangeExtension(fsra.CanonicalLocalResourcePath.ToString(), extension); if (TryRead(metaFilePath, out imdbId)) { return(true); } } } // Prepare a list of paths to check: for chained resource path we will also check relative parent paths (like for DVD-ISO files) List <string> pathsToCheck = new List <string> { fsra.CanonicalLocalResourcePath.ToString() }; if (fsra.CanonicalLocalResourcePath.PathSegments.Count > 1) { string canocialPath = fsra.CanonicalLocalResourcePath.ToString(); pathsToCheck.Add(canocialPath.Substring(0, canocialPath.LastIndexOf('>'))); } // Then test for special named files, like "movie.nfo" foreach (string path in pathsToCheck) { foreach (string fileName in NFO_FILENAMES) { string metaFilePath = ResourcePathHelper.GetDirectoryName(path); metaFilePath = ResourcePathHelper.Combine(metaFilePath, fileName); if (TryRead(metaFilePath, out imdbId)) { return(true); } } } // Now check siblings of movie for any IMDB id containing filename. // Morpheus_xx, 2014-01-04: disabled code because it leads to false detections if there are multiple video files in same folder. In this case the first // video with TT-number is wrongly used. // TODO: this part could be reworked based on different ideas: // - Exclude known video extensions from file name matching (this would require a reference to VideoMDE's settings for extension list) // - Only use folder lookup for chained resources, i.e. for a DVD-ISO, where any "TT000000.bla" is located next to it //IFileSystemResourceAccessor directoryFsra = null; //if (!fsra.IsFile) // directoryFsra = fsra.Clone() as IFileSystemResourceAccessor; //if (fsra.IsFile) // directoryFsra = GetContainingDirectory(fsra); //if (directoryFsra == null) // return false; //using (directoryFsra) // foreach (IFileSystemResourceAccessor file in directoryFsra.GetFiles()) // using (file) // if (ImdbIdMatcher.TryMatchImdbId(file.ResourceName, out imdbId)) // return true; return(false); }
/// <summary> /// Tries to read a valid IMDB id from additional .nfo or .txt files. /// </summary> /// <param name="fsra">FileSystemResourceAccessor</param> /// <param name="imdbId">Returns a valid IMDB or <c>null</c></param> /// <returns>true if matched</returns> public static bool TryMatchImdbId(IFileSystemResourceAccessor fsra, out string imdbId) { imdbId = null; if (fsra == null) { return(false); } // First try to find a nfo file that has the same name as our main movie. if (fsra.IsFile) { foreach (string extension in NFO_EXTENSIONS) { string metaFilePath = ResourcePathHelper.ChangeExtension(fsra.CanonicalLocalResourcePath.ToString(), extension); if (TryRead(metaFilePath, out imdbId)) { return(true); } } } // Prepare a list of paths to check: for chained resource path we will also check relative parent paths (like for DVD-ISO files) List <string> pathsToCheck = new List <string> { fsra.CanonicalLocalResourcePath.ToString() }; if (fsra.CanonicalLocalResourcePath.PathSegments.Count > 1) { string canocialPath = fsra.CanonicalLocalResourcePath.ToString(); pathsToCheck.Add(canocialPath.Substring(0, canocialPath.LastIndexOf('>'))); } // Then test for special named files, like "movie.nfo" foreach (string path in pathsToCheck) { foreach (string fileName in NFO_FILENAMES) { string metaFilePath = ResourcePathHelper.GetDirectoryName(path); metaFilePath = ResourcePathHelper.Combine(metaFilePath, fileName); if (TryRead(metaFilePath, out imdbId)) { return(true); } } } // Now check siblings of movie for any IMDB id containing filename. IFileSystemResourceAccessor directoryFsra = null; if (fsra.IsDirectory) { directoryFsra = fsra.Clone() as IFileSystemResourceAccessor; } if (fsra.IsFile) { directoryFsra = GetContainingDirectory(fsra); } if (directoryFsra == null) { return(false); } using (directoryFsra) foreach (IFileSystemResourceAccessor file in directoryFsra.GetFiles()) { using (file) if (ImdbIdMatcher.TryMatchImdbId(file.ResourceName, out imdbId)) { return(true); } } return(false); }