Example #1
0
        /// <summary>
        /// Ensures the list.
        /// </summary>
        /// <param name="url">The URL.</param>
        /// <param name="file">The file.</param>
        /// <param name="httpClient">The HTTP client.</param>
        /// <param name="fileSystem">The file system.</param>
        /// <param name="semaphore">The semaphore.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        public static async Task EnsureList(string url, string file, IHttpClient httpClient, IFileSystem fileSystem, SemaphoreSlim semaphore, CancellationToken cancellationToken)
        {
            var fileInfo = fileSystem.GetFileInfo(file);

            if (!fileInfo.Exists || (DateTime.UtcNow - fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays > 1)
            {
                await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

                try
                {
                    var temp = await httpClient.GetTempFile(new HttpRequestOptions
                    {
                        CancellationToken = cancellationToken,
                        Progress = new Progress<double>(),
                        Url = url

                    }).ConfigureAwait(false);

					fileSystem.CreateDirectory(Path.GetDirectoryName(file));

					fileSystem.CopyFile(temp, file, true);
                }
                finally
                {
                    semaphore.Release();
                }
            }
        }
        public LocalFileStream(IFileSystem fileSystem, string relativePath, string contentType)
            : base(contentType)
        {
            Contract.Requires(fileSystem != null);

            RelativePath = relativePath;
            _fileInfo = fileSystem.GetFileInfo(relativePath);
            _stream = new Lazy<Stream>(() => fileSystem.Open(relativePath, FileMode.Open));
        }
Example #3
0
        public static Project FromFile(string input, IFileSystem fileSystem)
        {
            var jObject = JsonConvert.DeserializeObject<Dictionary<string, JToken>>(input);
            var project = new Project();

            foreach (var entry in jObject)
            {
                var kindObj = entry.Key;
                string[] list;
                if (entry.Value is JArray)
                    list = entry.Value.ToObject<string[]>();
                else
                    list = new[] {entry.Value.ToObject<string>()};

                foreach (var item in list)
                {
                    var info = fileSystem.GetFileInfo(PathInfo.Create(item));
                    if (info == null)
                    {
                        var globPattern = GlobPattern.Create(item);
                        if (!globPattern.IsWildcard)
                            throw new InvalidProjectFileException($"Could not find file {item}.");

                        var items = fileSystem.GetFiles(globPattern);
                        foreach (var file in items)
                        {
                            var fileItem = new FileProjectItem(kindObj, file, fileSystem);
                            ProjectItem existing;
                            if (!project.TryGetItemById(fileItem.Identifier, out existing))
                                project.AddItem(fileItem);
                        }

                        project.AddSubscription(fileSystem.Subscribe(globPattern, a =>
                        {
                            HandleChange(a, project, kindObj, fileSystem);
                        }));
                    }
                    else
                    {
                        AddFile(fileSystem, project, kindObj, info, item);
                    }
                }
            }

            return project;
        }
        public async Task <FileOrganizationResult> OrganizeMovieFile(string path, MovieFileOrganizationOptions options, bool overwriteExisting, CancellationToken cancellationToken)
        {
            _logger.Info("Sorting file {0}", path);

            var result = new FileOrganizationResult
            {
                Date             = DateTime.UtcNow,
                OriginalPath     = path,
                OriginalFileName = Path.GetFileName(path),
                Type             = FileOrganizerType.Unknown,
                FileSize         = _fileSystem.GetFileInfo(path).Length
            };

            try
            {
                if (_libraryMonitor.IsPathLocked(path))
                {
                    result.Status        = FileSortingStatus.Failure;
                    result.StatusMessage = "Path is locked by other processes. Please try again later.";
                    _logger.Info("Auto-organize Path is locked by other processes. Please try again later.");
                    return(result);
                }

                var namingOptions = GetNamingOptionsInternal();
                var resolver      = new VideoResolver(namingOptions);

                var movieInfo = resolver.Resolve(path, false) ??
                                new VideoFileInfo();

                var movieName = movieInfo.Name;

                if (!string.IsNullOrEmpty(movieName))
                {
                    var movieYear = movieInfo.Year;

                    _logger.Debug("Extracted information from {0}. Movie {1}, Year {2}", path, movieName, movieYear);

                    await OrganizeMovie(path,
                                        movieName,
                                        movieYear,
                                        options,
                                        overwriteExisting,
                                        result,
                                        cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    var msg = string.Format("Unable to determine movie name from {0}", path);
                    result.Status        = FileSortingStatus.Failure;
                    result.StatusMessage = msg;
                    _logger.Warn(msg);
                }

                // Handle previous result
                var previousResult = _organizationService.GetResultBySourcePath(path);

                if ((previousResult != null && result.Type == FileOrganizerType.Unknown) || (previousResult?.Status == result.Status &&
                                                                                             previousResult?.StatusMessage == result.StatusMessage &&
                                                                                             result.Status != FileSortingStatus.Success))
                {
                    // Don't keep saving the same result over and over if nothing has changed
                    return(previousResult);
                }
            }
            catch (Exception ex)
            {
                result.Status        = FileSortingStatus.Failure;
                result.StatusMessage = ex.Message;
                _logger.ErrorException("Error organizing file", ex);
            }

            await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);

            return(result);
        }
Example #5
0
        /// <summary>
        /// Fetches the data from XML node.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="result">The result.</param>
        protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult <Episode> result)
        {
            var item = result.Item;

            switch (reader.Name)
            {
            case "Episode":

                //MB generated metadata is within an "Episode" node
                using (var subTree = reader.ReadSubtree())
                {
                    subTree.MoveToContent();

                    // Loop through each element
                    while (subTree.Read())
                    {
                        if (subTree.NodeType == XmlNodeType.Element)
                        {
                            FetchDataFromXmlNode(subTree, result);
                        }
                    }
                }
                break;

            case "filename":
            {
                var filename = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(filename))
                {
                    // Strip off everything but the filename. Some metadata tools like MetaBrowser v1.0 will have an 'episodes' prefix
                    // even though it's actually using the metadata folder.
                    filename = Path.GetFileName(filename);

                    var parentFolder = Path.GetDirectoryName(_xmlPath);
                    filename = Path.Combine(parentFolder, filename);
                    var file = _fileSystem.GetFileInfo(filename);

                    if (file.Exists)
                    {
                        _imagesFound.Add(new LocalImageInfo
                            {
                                Type     = ImageType.Primary,
                                FileInfo = file
                            });
                    }
                }
                break;
            }

            case "SeasonNumber":
            {
                var number = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(number))
                {
                    int num;

                    if (int.TryParse(number, out num))
                    {
                        item.ParentIndexNumber = num;
                    }
                }
                break;
            }

            case "EpisodeNumber":
            {
                var number = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(number))
                {
                    int num;

                    if (int.TryParse(number, out num))
                    {
                        item.IndexNumber = num;
                    }
                }
                break;
            }

            case "EpisodeNumberEnd":
            {
                var number = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(number))
                {
                    int num;

                    if (int.TryParse(number, out num))
                    {
                        item.IndexNumberEnd = num;
                    }
                }
                break;
            }

            case "absolute_number":
            {
                var val = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(val))
                {
                    int rval;

                    // int.TryParse is local aware, so it can be probamatic, force us culture
                    if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
                    {
                        item.AbsoluteEpisodeNumber = rval;
                    }
                }

                break;
            }

            case "DVD_episodenumber":
            {
                var number = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(number))
                {
                    float num;

                    if (float.TryParse(number, NumberStyles.Any, UsCulture, out num))
                    {
                        item.DvdEpisodeNumber = num;
                    }
                }
                break;
            }

            case "DVD_season":
            {
                var number = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(number))
                {
                    float num;

                    if (float.TryParse(number, NumberStyles.Any, UsCulture, out num))
                    {
                        item.DvdSeasonNumber = Convert.ToInt32(num);
                    }
                }
                break;
            }

            case "airsbefore_episode":
            {
                var val = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(val))
                {
                    int rval;

                    // int.TryParse is local aware, so it can be probamatic, force us culture
                    if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
                    {
                        item.AirsBeforeEpisodeNumber = rval;
                    }
                }

                break;
            }

            case "airsafter_season":
            {
                var val = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(val))
                {
                    int rval;

                    // int.TryParse is local aware, so it can be probamatic, force us culture
                    if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
                    {
                        item.AirsAfterSeasonNumber = rval;
                    }
                }

                break;
            }

            case "airsbefore_season":
            {
                var val = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(val))
                {
                    int rval;

                    // int.TryParse is local aware, so it can be probamatic, force us culture
                    if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
                    {
                        item.AirsBeforeSeasonNumber = rval;
                    }
                }

                break;
            }

            case "EpisodeName":
            {
                var name = reader.ReadElementContentAsString();

                if (!string.IsNullOrWhiteSpace(name))
                {
                    item.Name = name;
                }
                break;
            }


            default:
                base.FetchDataFromXmlNode(reader, result);
                break;
            }
        }
Example #6
0
        /// <inheritdoc />
        public async Task <IEnumerable <RemoteSubtitleInfo> > Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
        {
            var  imdbIdText = request.GetProviderId(MetadataProvider.Imdb);
            long imdbId     = 0;

            switch (request.ContentType)
            {
            case VideoContentType.Episode:
                if (!request.IndexNumber.HasValue || !request.ParentIndexNumber.HasValue || string.IsNullOrEmpty(request.SeriesName))
                {
                    _logger.LogDebug("Episode information missing");
                    return(Enumerable.Empty <RemoteSubtitleInfo>());
                }

                break;

            case VideoContentType.Movie:
                if (string.IsNullOrEmpty(request.Name))
                {
                    _logger.LogDebug("Movie name missing");
                    return(Enumerable.Empty <RemoteSubtitleInfo>());
                }

                if (string.IsNullOrWhiteSpace(imdbIdText) || !long.TryParse(imdbIdText.TrimStart('t'), NumberStyles.Any, UsCulture, out imdbId))
                {
                    _logger.LogDebug("Imdb id missing");
                    return(Enumerable.Empty <RemoteSubtitleInfo>());
                }

                break;
            }

            if (string.IsNullOrEmpty(request.MediaPath))
            {
                _logger.LogDebug("Path Missing");
                return(Enumerable.Empty <RemoteSubtitleInfo>());
            }

            await Login(cancellationToken).ConfigureAwait(false);

            var subLanguageId = NormalizeLanguage(request.Language);

            string hash;

            using (var fileStream = File.OpenRead(request.MediaPath))
            {
                hash = Utilities.ComputeHash(fileStream);
            }

            var fileInfo                 = _fileSystem.GetFileInfo(request.MediaPath);
            var movieByteSize            = fileInfo.Length;
            var searchImdbId             = request.ContentType == VideoContentType.Movie ? imdbId.ToString(UsCulture) : string.Empty;
            var subtitleSearchParameters = request.ContentType == VideoContentType.Episode
                ? new List <SubtitleSearchParameters>
            {
                new SubtitleSearchParameters(
                    subLanguageId,
                    query: request.SeriesName,
                    season: request.ParentIndexNumber !.Value.ToString(UsCulture),
                    episode: request.IndexNumber !.Value.ToString(UsCulture))
            }
        private List <FileSystemMetadata> GetEpisodeXmlFiles(int?seasonNumber, int?episodeNumber, int?endingEpisodeNumber, string seriesDataPath)
        {
            var files = new List <FileSystemMetadata>();

            if (episodeNumber == null)
            {
                return(files);
            }

            var usingAbsoluteData = false;

            if (seasonNumber.HasValue)
            {
                var file     = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
                var fileInfo = _fileSystem.GetFileInfo(file);

                if (fileInfo.Exists)
                {
                    files.Add(fileInfo);
                }
            }
            else
            {
                usingAbsoluteData = true;
                var file     = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
                var fileInfo = _fileSystem.GetFileInfo(file);
                if (fileInfo.Exists)
                {
                    files.Add(fileInfo);
                }
            }

            var end = endingEpisodeNumber ?? episodeNumber;

            episodeNumber++;

            while (episodeNumber <= end)
            {
                string file;

                if (usingAbsoluteData)
                {
                    file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
                }
                else
                {
                    file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
                }

                var fileInfo = _fileSystem.GetFileInfo(file);
                if (fileInfo.Exists)
                {
                    files.Add(fileInfo);
                }
                else
                {
                    break;
                }

                episodeNumber++;
            }

            return(files);
        }
Example #8
0
        private async Task DownloadBackdrops(BaseItem item, LibraryOptions libraryOptions, ImageType imageType, int limit, IRemoteImageProvider provider, RefreshResult result, IEnumerable <RemoteImageInfo> images, int minWidth, CancellationToken cancellationToken)
        {
            foreach (var image in images.Where(i => i.Type == imageType))
            {
                if (item.GetImages(imageType).Count() >= limit)
                {
                    break;
                }

                if (image.Width.HasValue && image.Width.Value < minWidth)
                {
                    continue;
                }

                var url = image.Url;

                if (EnableImageStub(item, libraryOptions))
                {
                    SaveImageStub(item, imageType, new[] { url });
                    result.UpdateType |= ItemUpdateType.ImageUpdate;
                    continue;
                }

                try
                {
                    using var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false);

                    // If there's already an image of the same size, skip it
                    if (response.Content.Headers.ContentLength.HasValue)
                    {
                        try
                        {
                            if (item.GetImages(imageType).Any(i => _fileSystem.GetFileInfo(i.Path).Length == response.Content.Headers.ContentLength.Value))
                            {
                                response.Content.Dispose();
                                continue;
                            }
                        }
                        catch (IOException ex)
                        {
                            _logger.LogError(ex, "Error examining images");
                        }
                    }

                    await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

                    await _providerManager.SaveImage(
                        item,
                        stream,
                        response.Content.Headers.ContentType.MediaType,
                        imageType,
                        null,
                        cancellationToken).ConfigureAwait(false);

                    result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
                }
                catch (HttpRequestException ex)
                {
                    // Sometimes providers send back bad urls. Just move onto the next image
                    if (ex.StatusCode.HasValue &&
                        (ex.StatusCode.Value == HttpStatusCode.NotFound || ex.StatusCode.Value == HttpStatusCode.Forbidden))
                    {
                        continue;
                    }

                    break;
                }
            }
        }
Example #9
0
        /// <summary>
        /// Runs the specified progress.
        /// </summary>
        /// <param name="progress">The progress.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        public async Task Run(IProgress <double> progress, CancellationToken cancellationToken)
        {
            var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase));

            if (seriesConfig != null && seriesConfig.DisabledMetadataFetchers.Contains(TvdbSeriesProvider.Current.Name, StringComparer.OrdinalIgnoreCase))
            {
                progress.Report(100);
                return;
            }

            var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);

            _fileSystem.CreateDirectory(path);

            var timestampFile = Path.Combine(path, "time.txt");

            var timestampFileInfo = _fileSystem.GetFileInfo(timestampFile);

            // Don't check for tvdb updates anymore frequently than 24 hours
            if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
            {
                return;
            }

            // Find out the last time we queried tvdb for updates
            var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;

            string newUpdateTime;

            var existingDirectories = _fileSystem.GetDirectoryPaths(path)
                                      .Select(Path.GetFileName)
                                      .ToList();

            var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
            {
                IncludeItemTypes             = new[] { typeof(Series).Name },
                Recursive                    = true,
                GroupByPresentationUniqueKey = false,
                DtoOptions                   = new DtoOptions(false)
                {
                    EnableImages = false
                }
            }).Cast <Series>()
                             .ToList();

            var seriesIdsInLibrary = seriesList
                                     .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb)))
                                     .Select(i => i.GetProviderId(MetadataProviders.Tvdb))
                                     .ToList();

            var missingSeries = seriesIdsInLibrary.Except(existingDirectories, StringComparer.OrdinalIgnoreCase)
                                .ToList();

            var enableInternetProviders = seriesList.Count == 0 ? false : seriesList[0].IsInternetMetadataEnabled();

            if (!enableInternetProviders)
            {
                progress.Report(100);
                return;
            }

            // If this is our first time, update all series
            if (string.IsNullOrEmpty(lastUpdateTime))
            {
                // First get tvdb server time
                using (var stream = await _httpClient.Get(new HttpRequestOptions
                {
                    Url = ServerTimeUrl,
                    CancellationToken = cancellationToken,
                    EnableHttpCompression = true,
                    BufferContent = false
                }).ConfigureAwait(false))
                {
                    newUpdateTime = GetUpdateTime(stream);
                }

                existingDirectories.AddRange(missingSeries);

                await UpdateSeries(existingDirectories, path, null, progress, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false);

                newUpdateTime = seriesToUpdate.Item2;

                long lastUpdateValue;

                long.TryParse(lastUpdateTime, NumberStyles.Any, UsCulture, out lastUpdateValue);

                var nullableUpdateValue = lastUpdateValue == 0 ? (long?)null : lastUpdateValue;

                var listToUpdate = seriesToUpdate.Item1.ToList();
                listToUpdate.AddRange(missingSeries);

                await UpdateSeries(listToUpdate, path, nullableUpdateValue, progress, cancellationToken).ConfigureAwait(false);
            }

            _fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
            progress.Report(100);
        }
Example #10
0
        public async Task SaveImage(IHasImages item, Stream source, string mimeType, ImageType type, int?imageIndex, bool?saveLocallyWithMedia, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(mimeType))
            {
                throw new ArgumentNullException("mimeType");
            }

            var saveLocally = item.SupportsLocalMetadata && item.IsSaveLocalMetadataEnabled() && !item.IsOwnedItem && !(item is Audio);

            if (item is User)
            {
                saveLocally = true;
            }

            if (type != ImageType.Primary && item is Episode)
            {
                saveLocally = false;
            }

            var locationType = item.LocationType;

            if (locationType == LocationType.Remote || locationType == LocationType.Virtual)
            {
                saveLocally = false;

                var season = item as Season;

                // If season is virtual under a physical series, save locally if using compatible convention
                if (season != null && _config.Configuration.ImageSavingConvention == ImageSavingConvention.Compatible)
                {
                    var series = season.Series;

                    if (series != null && series.SupportsLocalMetadata && series.IsSaveLocalMetadataEnabled())
                    {
                        saveLocally = true;
                    }
                }
            }
            if (saveLocallyWithMedia.HasValue && !saveLocallyWithMedia.Value)
            {
                saveLocally = saveLocallyWithMedia.Value;
            }

            if (!imageIndex.HasValue && item.AllowsMultipleImages(type))
            {
                imageIndex = item.GetImages(type).Count();
            }

            var index = imageIndex ?? 0;

            var paths = GetSavePaths(item, type, imageIndex, mimeType, saveLocally);

            var retryPaths = GetSavePaths(item, type, imageIndex, mimeType, false);

            // If there are more than one output paths, the stream will need to be seekable
            var memoryStream = _memoryStreamProvider.CreateNew();

            using (source)
            {
                await source.CopyToAsync(memoryStream).ConfigureAwait(false);
            }

            source = memoryStream;

            var currentImage            = GetCurrentImage(item, type, index);
            var currentImageIsLocalFile = currentImage != null && currentImage.IsLocalFile;
            var currentImagePath        = currentImage == null ? null : currentImage.Path;

            var savedPaths = new List <string>();

            using (source)
            {
                var currentPathIndex = 0;

                foreach (var path in paths)
                {
                    source.Position = 0;
                    string retryPath = null;
                    if (paths.Length == retryPaths.Length)
                    {
                        retryPath = retryPaths[currentPathIndex];
                    }
                    var savedPath = await SaveImageToLocation(source, path, retryPath, cancellationToken).ConfigureAwait(false);

                    savedPaths.Add(savedPath);
                    currentPathIndex++;
                }
            }

            // Set the path into the item
            SetImagePath(item, type, imageIndex, savedPaths[0]);

            // Delete the current path
            if (currentImageIsLocalFile && !savedPaths.Contains(currentImagePath, StringComparer.OrdinalIgnoreCase))
            {
                var currentPath = currentImagePath;

                _logger.Debug("Deleting previous image {0}", currentPath);

                _libraryMonitor.ReportFileSystemChangeBeginning(currentPath);

                try
                {
                    var currentFile = _fileSystem.GetFileInfo(currentPath);

                    // This will fail if the file is hidden
                    if (currentFile.Exists)
                    {
                        if (currentFile.IsHidden)
                        {
                            _fileSystem.SetHidden(currentFile.FullName, false);
                        }

                        _fileSystem.DeleteFile(currentFile.FullName);
                    }
                }
                finally
                {
                    _libraryMonitor.ReportFileSystemChangeComplete(currentPath, false);
                }
            }
        }
Example #11
0
        public async Task <FileOrganizationResult> OrganizeEpisodeFile(string path, AutoOrganizeOptions options, bool overwriteExisting, CancellationToken cancellationToken)
        {
            _logger.Info("Sorting file {0}", path);

            var result = new FileOrganizationResult
            {
                Date             = DateTime.UtcNow,
                OriginalPath     = path,
                OriginalFileName = Path.GetFileName(path),
                Type             = FileOrganizerType.Episode,
                FileSize         = _fileSystem.GetFileInfo(path).Length
            };

            try
            {
                if (_libraryMonitor.IsPathLocked(path))
                {
                    result.Status        = FileSortingStatus.Failure;
                    result.StatusMessage = "Path is locked by other processes. Please try again later.";
                    return(result);
                }

                var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
                var resolver      = new EpisodeResolver(namingOptions, new NullLogger());

                var episodeInfo = resolver.Resolve(path, false) ??
                                  new MediaBrowser.Naming.TV.EpisodeInfo();

                var seriesName = episodeInfo.SeriesName;

                if (!string.IsNullOrEmpty(seriesName))
                {
                    var seasonNumber = episodeInfo.SeasonNumber;

                    result.ExtractedSeasonNumber = seasonNumber;

                    // Passing in true will include a few extra regex's
                    var episodeNumber = episodeInfo.EpisodeNumber;

                    result.ExtractedEpisodeNumber = episodeNumber;

                    var premiereDate = episodeInfo.IsByDate ?
                                       new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value) :
                                       (DateTime?)null;

                    if (episodeInfo.IsByDate || (seasonNumber.HasValue && episodeNumber.HasValue))
                    {
                        if (episodeInfo.IsByDate)
                        {
                            _logger.Debug("Extracted information from {0}. Series name {1}, Date {2}", path, seriesName, premiereDate.Value);
                        }
                        else
                        {
                            _logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, seasonNumber, episodeNumber);
                        }

                        var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;

                        result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;

                        await OrganizeEpisode(path,
                                              seriesName,
                                              seasonNumber,
                                              episodeNumber,
                                              endingEpisodeNumber,
                                              premiereDate,
                                              options,
                                              overwriteExisting,
                                              false,
                                              result,
                                              cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        var msg = string.Format("Unable to determine episode number from {0}", path);
                        result.Status        = FileSortingStatus.Failure;
                        result.StatusMessage = msg;
                        _logger.Warn(msg);
                    }
                }
                else
                {
                    var msg = string.Format("Unable to determine series name from {0}", path);
                    result.Status        = FileSortingStatus.Failure;
                    result.StatusMessage = msg;
                    _logger.Warn(msg);
                }

                var previousResult = _organizationService.GetResultBySourcePath(path);

                if (previousResult != null)
                {
                    // Don't keep saving the same result over and over if nothing has changed
                    if (previousResult.Status == result.Status && previousResult.StatusMessage == result.StatusMessage && result.Status != FileSortingStatus.Success)
                    {
                        return(previousResult);
                    }
                }

                await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                result.Status        = FileSortingStatus.Failure;
                result.StatusMessage = ex.Message;
            }

            return(result);
        }
Example #12
0
        private bool IsFileReference(string reference)
        {
            var fileInfo = _fileSystem.GetFileInfo(reference);

            return(fileInfo.Exists && fileInfo.Extension.Equals(".dll", StringComparison.InvariantCultureIgnoreCase));
        }
Example #13
0
        protected void InsertFileContent(object sender, WriterCommandEventArgs args)
        {
            if (args.Mode == WriterCommandEventMode.QueryState)
            {
                args.Enabled = args.DocumentControler != null &&
                               args.Document != null &&
                               args.DocumentControler.CanInsertElementAtCurrentPosition(
                    typeof(DomElement));
            }
            else if (args.Mode == WriterCommandEventMode.Invoke)
            {
                args.Result = false;
                DomDocument document = null;
                string      fileName = null;
                if (args.Parameter is string)
                {
                    fileName = (string)args.Parameter;
                }
                else if (args.Parameter is DomDocument)
                {
                    document = (DomDocument)args.Parameter;
                }
                if (document == null)
                {
                    IFileSystem fs = args.Host.FileSystems.Docuemnt;
                    if (fs != null)
                    {
                        if (args.ShowUI)
                        {
                            // 浏览文件
                            fileName = fs.BrowseOpen(args.Host.Services, fileName);
                        }
                        if (string.IsNullOrEmpty(fileName))
                        {
                            return;
                        }
                        VFileInfo info = fs.GetFileInfo(args.Host.Services, fileName);
                        if (info.Exists == false)
                        {
                            // 文件不存在
                            return;
                        }
                        //打开文件
                        if (args.Host.Debuger != null)
                        {
                            args.Host.Debuger.DebugLoadingFile(fileName);
                        }
                        System.IO.Stream stream = fs.Open(args.Host.Services, fileName);
                        if (stream != null)
                        {
                            FileFormat format = WriterUtils.ParseFileFormat(info.Format);
                            using (stream)
                            {
                                // 读取文件,加载文档对象
                                document         = new DomDocument();
                                document.Options = args.Document.Options;

                                document.ServerObject = args.Document.ServerObject;
                                document.Load(stream, format);
                                if (args.Host.Debuger != null)
                                {
                                    args.Host.Debuger.DebugLoadFileComplete((int)stream.Length);
                                }
                            }
                        }
                    }
                }
                if (document != null &&
                    document.Body != null &&
                    document.Body.Elements.Count > 0)
                {
                    // 导入文档内容
                    DomElementList list = document.Body.Elements;
                    args.Document.ImportElements(list);
                    args.DocumentControler.InsertElements(list);
                    args.Result = list;
                }
            }
        }
Example #14
0
        private async Task DownloadMultiImages(BaseItem item, ImageType imageType, ImageRefreshOptions refreshOptions, int limit, IRemoteImageProvider provider, RefreshResult result, IEnumerable <RemoteImageInfo> images, int minWidth, CancellationToken cancellationToken)
        {
            foreach (var image in images.Where(i => i.Type == imageType))
            {
                if (item.GetImages(imageType).Count() >= limit)
                {
                    break;
                }

                if (image.Width.HasValue && image.Width.Value < minWidth)
                {
                    continue;
                }

                var url = image.Url;

                if (EnableImageStub(item))
                {
                    SaveImageStub(item, imageType, new[] { url });
                    result.UpdateType |= ItemUpdateType.ImageUpdate;
                    continue;
                }

                try
                {
                    using var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false);

                    // Sometimes providers send back bad urls. Just move to the next image
                    if (response.StatusCode == HttpStatusCode.NotFound || response.StatusCode == HttpStatusCode.Forbidden)
                    {
                        _logger.LogDebug("{Url} returned {StatusCode}, ignoring", url, response.StatusCode);
                        continue;
                    }

                    if (!response.IsSuccessStatusCode)
                    {
                        _logger.LogWarning("{Url} returned {StatusCode}, skipping all remaining requests", url, response.StatusCode);
                        break;
                    }

                    // If there's already an image of the same file size, skip it unless doing a full refresh
                    if (response.Content.Headers.ContentLength.HasValue && !refreshOptions.IsReplacingImage(imageType))
                    {
                        try
                        {
                            if (item.GetImages(imageType).Any(i => _fileSystem.GetFileInfo(i.Path).Length == response.Content.Headers.ContentLength.Value))
                            {
                                response.Content.Dispose();
                                continue;
                            }
                        }
                        catch (IOException ex)
                        {
                            _logger.LogError(ex, "Error examining images");
                        }
                    }

                    await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);

                    await _providerManager.SaveImage(
                        item,
                        stream,
                        response.Content.Headers.ContentType?.MediaType,
                        imageType,
                        null,
                        cancellationToken).ConfigureAwait(false);

                    result.UpdateType |= ItemUpdateType.ImageUpdate;
                }
                catch (HttpRequestException)
                {
                    break;
                }
            }
        }
Example #15
0
        /// <summary>
        /// 获取图片
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="type">类型</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task <HttpResponseInfo> GetImageResponse(string url, ImageType type, CancellationToken cancellationToken)
        {
            //  /emby/Plugins/JavScraper/Image?url=&type=xx
            if (url.IndexOf("Plugins/JavScraper/Image", StringComparison.OrdinalIgnoreCase) >= 0) //本地的链接
            {
                var uri  = new Uri(url);
                var q    = HttpUtility.ParseQueryString(uri.Query);
                var url2 = q["url"];
                if (url2.IsWebUrl())
                {
                    url = url2;
                    var tt = q.Get("type");
                    if (!string.IsNullOrWhiteSpace(tt) && Enum.TryParse <ImageType>(tt.Trim(), out var t2))
                    {
                        type = t2;
                    }
                }
            }

            logger?.Info($"{nameof(GetImageResponse)}-{url}");

            var key        = WebUtility.UrlEncode(url);
            var cache_file = Path.Combine(appPaths.GetImageCachePath().ToString(), key);

            byte[] bytes = null;

            //尝试从缓存中读取
            try
            {
                var fi = fileSystem.GetFileInfo(cache_file);

                //图片文件存在,且是24小时之内的
                if (fi.Exists && fileSystem.GetFileInfo(cache_file).LastWriteTimeUtc > DateTime.Now.AddDays(-1).ToUniversalTime())
                {
                    bytes = await fileSystem.ReadAllBytesAsync(cache_file);

                    logger?.Info($"Hit image cache {url} {cache_file}");
                    if (type == ImageType.Primary)
                    {
                        var ci = await CutImage(bytes, url);

                        if (ci != null)
                        {
                            return(ci);
                        }
                    }

                    fileExtensionContentTypeProvider.TryGetContentType(url, out var contentType);

                    return(new HttpResponseInfo()
                    {
                        Content = new MemoryStream(bytes),
                        ContentLength = bytes.Length,
                        ContentType = contentType ?? "image/jpeg",
                        StatusCode = HttpStatusCode.OK,
                    });
                }
            }
            catch (Exception ex)
            {
                logger?.Warn($"Read image cache error. {url} {cache_file} {ex.Message}");
            }

            try
            {
                var resp = await client.GetAsync(url, cancellationToken);

                if (resp.IsSuccessStatusCode == false)
                {
                    return(await Parse(resp));
                }

                try
                {
                    fileSystem.WriteAllBytes(cache_file, await resp.Content.ReadAsByteArrayAsync());
                    logger?.Info($"Save image cache {url} {cache_file} ");
                }
                catch (Exception ex)
                {
                    logger?.Warn($"Save image cache error. {url} {cache_file} {ex.Message}");
                }

                if (type == ImageType.Primary)
                {
                    var ci = await CutImage(await resp.Content.ReadAsByteArrayAsync(), url);

                    if (ci != null)
                    {
                        return(ci);
                    }
                }

                return(await Parse(resp));
            }
            catch (Exception ex)
            {
                logger?.Error(ex.ToString());
            }
            return(new HttpResponseInfo());
        }
Example #16
0
        public async Task <IEnumerable <RemoteSubtitleInfo> > Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
        {
            var  imdbIdText = request.GetProviderId(MetadataProviders.Imdb);
            long imdbId     = 0;

            switch (request.ContentType)
            {
            case VideoContentType.Episode:
                if (!request.IndexNumber.HasValue || !request.ParentIndexNumber.HasValue || string.IsNullOrEmpty(request.SeriesName))
                {
                    _logger.LogDebug("Episode information missing");
                    return(new List <RemoteSubtitleInfo>());
                }
                break;

            case VideoContentType.Movie:
                if (string.IsNullOrEmpty(request.Name))
                {
                    _logger.LogDebug("Movie name missing");
                    return(new List <RemoteSubtitleInfo>());
                }
                if (string.IsNullOrWhiteSpace(imdbIdText) || !long.TryParse(imdbIdText.TrimStart('t'), NumberStyles.Any, _usCulture, out imdbId))
                {
                    _logger.LogDebug("Imdb id missing");
                    return(new List <RemoteSubtitleInfo>());
                }
                break;
            }

            if (string.IsNullOrEmpty(request.MediaPath))
            {
                _logger.LogDebug("Path Missing");
                return(new List <RemoteSubtitleInfo>());
            }

            await Login(cancellationToken).ConfigureAwait(false);

            var    subLanguageId = NormalizeLanguage(request.Language);
            string hash;

            using (var fileStream = _fileSystem.OpenRead(request.MediaPath))
            {
                hash = Utilities.ComputeHash(fileStream);
            }
            var fileInfo                 = _fileSystem.GetFileInfo(request.MediaPath);
            var movieByteSize            = fileInfo.Length;
            var searchImdbId             = request.ContentType == VideoContentType.Movie ? imdbId.ToString(_usCulture) : "";
            var subtitleSearchParameters = request.ContentType == VideoContentType.Episode
                ? new List <SubtitleSearchParameters> {
                new SubtitleSearchParameters(subLanguageId,
                                             query: request.SeriesName,
                                             season: request.ParentIndexNumber.Value.ToString(_usCulture),
                                             episode: request.IndexNumber.Value.ToString(_usCulture))
            }
                : new List <SubtitleSearchParameters> {
                new SubtitleSearchParameters(subLanguageId, imdbid: searchImdbId),
                new SubtitleSearchParameters(subLanguageId, query: request.Name, imdbid: searchImdbId)
            };
            var parms = new List <SubtitleSearchParameters> {
                new SubtitleSearchParameters(subLanguageId,
                                             movieHash: hash,
                                             movieByteSize: movieByteSize,
                                             imdbid: searchImdbId),
            };

            parms.AddRange(subtitleSearchParameters);
            var result = await OpenSubtitles.SearchSubtitlesAsync(parms.ToArray(), cancellationToken).ConfigureAwait(false);

            if (!(result is MethodResponseSubtitleSearch))
            {
                _logger.LogError("Invalid response type");
                return(new List <RemoteSubtitleInfo>());
            }

            Predicate <SubtitleSearchResult> mediaFilter =
                x =>
                request.ContentType == VideoContentType.Episode
                        ? !string.IsNullOrEmpty(x.SeriesSeason) && !string.IsNullOrEmpty(x.SeriesEpisode) &&
                int.Parse(x.SeriesSeason, _usCulture) == request.ParentIndexNumber &&
                int.Parse(x.SeriesEpisode, _usCulture) == request.IndexNumber
                        : !string.IsNullOrEmpty(x.IDMovieImdb) && long.Parse(x.IDMovieImdb, _usCulture) == imdbId;

            var results = ((MethodResponseSubtitleSearch)result).Results;

            // Avoid implicitly captured closure
            var hasCopy = hash;

            return(results.Where(x => x.SubBad == "0" && mediaFilter(x) && (!request.IsPerfectMatch || string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase)))
                   .OrderBy(x => (string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase) ? 0 : 1))
                   .ThenBy(x => Math.Abs(long.Parse(x.MovieByteSize, _usCulture) - movieByteSize))
                   .ThenByDescending(x => int.Parse(x.SubDownloadsCnt, _usCulture))
                   .ThenByDescending(x => double.Parse(x.SubRating, _usCulture))
                   .Select(i => new RemoteSubtitleInfo
            {
                Author = i.UserNickName,
                Comment = i.SubAuthorComment,
                CommunityRating = float.Parse(i.SubRating, _usCulture),
                DownloadCount = int.Parse(i.SubDownloadsCnt, _usCulture),
                Format = i.SubFormat,
                ProviderName = Name,
                ThreeLetterISOLanguageName = i.SubLanguageID,

                Id = i.SubFormat + "-" + i.SubLanguageID + "-" + i.IDSubtitleFile,

                Name = i.SubFileName,
                DateCreated = DateTime.Parse(i.SubAddDate, _usCulture),
                IsHashMatch = i.MovieHash == hasCopy
            }).Where(i => !string.Equals(i.Format, "sub", StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Format, "idx", StringComparison.OrdinalIgnoreCase)));
        }
Example #17
0
        public async Task <FileOrganizationResult> OrganizeEpisodeFile(
            string path,
            TvFileOrganizationOptions options,
            CancellationToken cancellationToken)
        {
            _logger.Info("Sorting file {0}", path);

            var result = new FileOrganizationResult
            {
                Date             = DateTime.UtcNow,
                OriginalPath     = path,
                OriginalFileName = Path.GetFileName(path),
                Type             = FileOrganizerType.Unknown,
                FileSize         = _fileSystem.GetFileInfo(path).Length
            };

            try
            {
                if (_libraryMonitor.IsPathLocked(path))
                {
                    result.Status        = FileSortingStatus.Failure;
                    result.StatusMessage = "Path is locked by other processes. Please try again later.";
                    _logger.Info("Auto-organize Path is locked by other processes. Please try again later.");
                    return(result);
                }

                var namingOptions = GetNamingOptionsInternal();
                var resolver      = new EpisodeResolver(namingOptions);

                var episodeInfo = resolver.Resolve(path, false) ??
                                  new Naming.TV.EpisodeInfo();

                var seriesName = episodeInfo.SeriesName;
                int?seriesYear = null;

                if (!string.IsNullOrEmpty(seriesName))
                {
                    var seriesParseResult = _libraryManager.ParseName(seriesName);

                    seriesName = seriesParseResult.Name;
                    seriesYear = seriesParseResult.Year;
                }

                if (string.IsNullOrWhiteSpace(seriesName))
                {
                    seriesName = episodeInfo.SeriesName;
                }

                if (!string.IsNullOrEmpty(seriesName))
                {
                    var seasonNumber = episodeInfo.SeasonNumber;

                    result.ExtractedSeasonNumber = seasonNumber;

                    // Passing in true will include a few extra regex's
                    var episodeNumber = episodeInfo.EpisodeNumber;

                    result.ExtractedEpisodeNumber = episodeNumber;

                    var premiereDate = episodeInfo.IsByDate ?
                                       new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value) :
                                       (DateTime?)null;

                    if (episodeInfo.IsByDate || (seasonNumber.HasValue && episodeNumber.HasValue))
                    {
                        if (episodeInfo.IsByDate)
                        {
                            _logger.Debug("Extracted information from {0}. Series name {1}, Date {2}", path, seriesName, premiereDate.Value);
                        }
                        else
                        {
                            _logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, seasonNumber, episodeNumber);
                        }

                        // We detected an airdate or (an season number and an episode number)
                        // We have all the chance that the media type is an Episode
                        // if an earlier result exist with an different type, we update it
                        result.Type = CurrentFileOrganizerType;

                        var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;

                        result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;

                        await OrganizeEpisode(path,
                                              seriesName,
                                              seriesYear,
                                              seasonNumber,
                                              episodeNumber,
                                              endingEpisodeNumber,
                                              premiereDate,
                                              options,
                                              false,
                                              result,
                                              cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        var msg = string.Format("Unable to determine episode number from {0}", path);
                        result.Status        = FileSortingStatus.Failure;
                        result.StatusMessage = msg;
                        _logger.Warn(msg);
                    }
                }
                else
                {
                    var msg = string.Format("Unable to determine series name from {0}", path);
                    result.Status        = FileSortingStatus.Failure;
                    result.StatusMessage = msg;
                    _logger.Warn(msg);
                }

                // Handle previous result
                var previousResult = _organizationService.GetResultBySourcePath(path);

                if ((previousResult != null && result.Type == FileOrganizerType.Unknown) || (previousResult?.Status == result.Status &&
                                                                                             previousResult?.StatusMessage == result.StatusMessage &&
                                                                                             result.Status != FileSortingStatus.Success))
                {
                    // Don't keep saving the same result over and over if nothing has changed
                    return(previousResult);
                }
            }
            catch (OrganizationException ex)
            {
                result.Status        = FileSortingStatus.Failure;
                result.StatusMessage = ex.Message;
            }
            catch (Exception ex)
            {
                result.Status        = FileSortingStatus.Failure;
                result.StatusMessage = ex.Message;
                _logger.ErrorException("Error organizing file", ex);
            }

            await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);

            return(result);
        }
Example #18
0
        private bool IsThrottleAllowed(TranscodingJobDto job, int thresholdSeconds)
        {
            var bytesDownloaded          = job.BytesDownloaded;
            var transcodingPositionTicks = job.TranscodingPositionTicks ?? 0;
            var downloadPositionTicks    = job.DownloadPositionTicks ?? 0;

            var path = job.Path ?? throw new ArgumentException("Path can't be null.");

            var gapLengthInTicks = TimeSpan.FromSeconds(thresholdSeconds).Ticks;

            if (downloadPositionTicks > 0 && transcodingPositionTicks > 0)
            {
                // HLS - time-based consideration

                var targetGap = gapLengthInTicks;
                var gap       = transcodingPositionTicks - downloadPositionTicks;

                if (gap < targetGap)
                {
                    _logger.LogDebug("Not throttling transcoder gap {0} target gap {1}", gap, targetGap);
                    return(false);
                }

                _logger.LogDebug("Throttling transcoder gap {0} target gap {1}", gap, targetGap);
                return(true);
            }

            if (bytesDownloaded > 0 && transcodingPositionTicks > 0)
            {
                // Progressive Streaming - byte-based consideration

                try
                {
                    var bytesTranscoded = job.BytesTranscoded ?? _fileSystem.GetFileInfo(path).Length;

                    // Estimate the bytes the transcoder should be ahead
                    double gapFactor = gapLengthInTicks;
                    gapFactor /= transcodingPositionTicks;
                    var targetGap = bytesTranscoded * gapFactor;

                    var gap = bytesTranscoded - bytesDownloaded;

                    if (gap < targetGap)
                    {
                        _logger.LogDebug("Not throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded);
                        return(false);
                    }

                    _logger.LogDebug("Throttling transcoder gap {0} target gap {1} bytes downloaded {2}", gap, targetGap, bytesDownloaded);
                    return(true);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error getting output size");
                    return(false);
                }
            }

            _logger.LogDebug("No throttle data for {Path}", path);
            return(false);
        }
Example #19
0
        async Task <IEnumerable <RemoteSubtitleInfo> > ISubtitleProvider.Search(SubtitleSearchRequest request,
                                                                                CancellationToken cancellationToken)
        {
            var  imdbIdText = request.GetProviderId(MetadataProviders.Imdb);
            long imdbId     = 0;

            _logger.LogDebug($"{ToDump(request)}");
            //_logger.LogDebug($"Imdb id: {imdbIdText}");
            switch (request.ContentType)
            {
            case VideoContentType.Episode:
                if (!request.IndexNumber.HasValue || !request.ParentIndexNumber.HasValue ||
                    string.IsNullOrEmpty(request.SeriesName))
                {
                    _logger.LogDebug("Episode information missing");
                    return(Enumerable.Empty <RemoteSubtitleInfo>());
                }

                break;

            case VideoContentType.Movie:
                if (string.IsNullOrEmpty(request.Name))
                {
                    _logger.LogDebug("Movie name missing");
                    return(Enumerable.Empty <RemoteSubtitleInfo>());
                }

                if (string.IsNullOrWhiteSpace(imdbIdText) || !long.TryParse(imdbIdText.TrimStart('t'),
                                                                            NumberStyles.Any, _usCulture, out imdbId))
                {
                    //_logger.LogDebug($"Imdb id: `{imdbIdText}` - media name: {request.Name}");
                    _logger.LogDebug("Imdb id missing");
                    //return Enumerable.Empty<RemoteSubtitleInfo>();
                }

                break;
            }

            if (string.IsNullOrEmpty(request.MediaPath))
            {
                _logger.LogDebug("Path Missing");
                return(Enumerable.Empty <RemoteSubtitleInfo>());
            }

            await Login(cancellationToken).ConfigureAwait(false);

            var subLanguageId = NormalizeLanguage(request.Language);

            string hash;

            using (var fileStream = File.OpenRead(request.MediaPath))
            {
                hash = Utilities.ComputeHash(fileStream);
            }

            var fileInfo      = _fileSystem.GetFileInfo(request.MediaPath);
            var movieByteSize = fileInfo.Length;
            //For movies, the imdb id is ued.
            var searchImdbId             = request.ContentType == VideoContentType.Movie && imdbId != 0 ? imdbId.ToString(_usCulture) : "";
            var subtitleSearchParameters = new List <SubtitleSearchParameters>();

            switch (request.ContentType)
            {
            case VideoContentType.Episode:
                subtitleSearchParameters = new List <SubtitleSearchParameters>
                {
                    new SubtitleSearchParameters(subLanguageId,
                                                 query: request.SeriesName,
                                                 season: request.ParentIndexNumber.Value.ToString(_usCulture),
                                                 episode: request.IndexNumber.Value.ToString(_usCulture))
                };
                break;

            case VideoContentType.Movie:
                subtitleSearchParameters = new List <SubtitleSearchParameters> {
                };
                if (!string.IsNullOrEmpty(searchImdbId))
                {
                    subtitleSearchParameters.Add(new SubtitleSearchParameters(subLanguageId, imdbid: searchImdbId));
                    subtitleSearchParameters.Add(new SubtitleSearchParameters(subLanguageId, query: request.Name, imdbid: searchImdbId));
                }
                else
                {
                    subtitleSearchParameters.Add(new SubtitleSearchParameters(subLanguageId, query: request.Name));
                }

                break;
            }

            var parms = new List <SubtitleSearchParameters>
            {
                new SubtitleSearchParameters(subLanguageId,
                                             movieHash: hash,
                                             movieByteSize: movieByteSize,
                                             imdbid: searchImdbId),
            };

            parms.AddRange(subtitleSearchParameters);

            if (_rateLimitLeft == 0)
            {
                await Task.Delay(1000);
            }
            //_logger.LogDebug($"Search params: {ToDump(parms)}");
            IMethodResponse searchResult = null;

            try
            {
                var searchResponse = await OpenSubtitlesHandler.OpenSubtitles
                                     .SearchSubtitlesAsync(parms.ToArray(), cancellationToken)
                                     .ConfigureAwait(false);

                searchResult = searchResponse.Item1;
                //_logger.LogDebug($"Search result: {ToDump(searchResult)}");
                _rateLimitLeft = searchResponse.Item2 ?? _rateLimitLeft;
                if (searchResponse.Item2 != null)
                {
                    if (_rateLimitLeft <= 4)
                    {
                        await Task.Delay(250);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"Error while fetching subtitles from opensubtitles.\n{ex}\n{ex.StackTrace}");
            }


            if (!(searchResult is MethodResponseSubtitleSearch))
            {
                _logger.LogError("Invalid response type");
                return(Enumerable.Empty <RemoteSubtitleInfo>());
            }

            //Check if we got a 401 error from opensubtitles
            if (searchResult.Status.Contains("401"))
            {
                _logger.LogError("Not authorized to OpenSubtitles");
                return(Enumerable.Empty <RemoteSubtitleInfo>());
            }

            Predicate <SubtitleSearchResult> mediaFilter = x =>
            {
                switch (request.ContentType)
                {
                case VideoContentType.Episode:
                    return(!string.IsNullOrEmpty(x.SeriesSeason) && !string.IsNullOrEmpty(x.SeriesEpisode) &&
                           int.Parse(x.SeriesSeason, _usCulture) == request.ParentIndexNumber &&
                           int.Parse(x.SeriesEpisode, _usCulture) == request.IndexNumber);

                case VideoContentType.Movie:
                    if (imdbId == 0)
                    {
                        return(x.MovieName.Contains(request.Name));
                    }
                    else
                    {
                        return(!string.IsNullOrEmpty(x.IDMovieImdb) &&
                               long.Parse(x.IDMovieImdb, _usCulture) == imdbId);
                    }
                }
                return(false);
            };


            var results = ((MethodResponseSubtitleSearch)searchResult).Results;

            // Avoid implicitly captured closure
            var hasCopy = hash;

            return(results.Where(x =>
                                 x.SubBad == "0" && mediaFilter(x) &&
                                 (!request.IsPerfectMatch || string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase)))
                   .OrderBy(x => (string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase) ? 0 : 1))
                   .ThenBy(x => Math.Abs(long.Parse(x.MovieByteSize, _usCulture) - movieByteSize))
                   .ThenByDescending(x => int.Parse(x.SubDownloadsCnt, _usCulture))
                   .ThenByDescending(x => double.Parse(x.SubRating, _usCulture))
                   .Select(i => new RemoteSubtitleInfo
            {
                Author = i.UserNickName,
                Comment = i.SubAuthorComment,
                CommunityRating = float.Parse(i.SubRating, _usCulture),
                DownloadCount = int.Parse(i.SubDownloadsCnt, _usCulture),
                Format = i.SubFormat,
                ProviderName = Name,
                ThreeLetterISOLanguageName = i.SubLanguageID,
                Id = i.SubFormat + "-" + i.SubLanguageID + "-" + i.IDSubtitleFile,
                Name = i.SubFileName,
                DateCreated = DateTime.Parse(i.SubAddDate, _usCulture),
                IsHashMatch = i.MovieHash == hasCopy
            }).Where(i =>
                     !string.Equals(i.Format, "sub", StringComparison.OrdinalIgnoreCase) &&
                     !string.Equals(i.Format, "idx", StringComparison.OrdinalIgnoreCase)));
        }
            private bool VerifyResource(VerifyInfo verifyInfo)
            {
                if (verifyInfo.UseFileSystem)
                {
                    IFileSystem         fileSystem = m_ResourceManager.GetFileSystem(verifyInfo.FileSystemName, false);
                    string              fileName   = verifyInfo.ResourceName.FullName;
                    FileSystem.FileInfo fileInfo   = fileSystem.GetFileInfo(fileName);
                    if (!fileInfo.IsValid)
                    {
                        return(false);
                    }

                    int length = fileInfo.Length;
                    if (length == verifyInfo.Length)
                    {
                        m_ResourceManager.PrepareCachedStream();
                        fileSystem.ReadFile(fileName, m_ResourceManager.m_CachedStream);
                        m_ResourceManager.m_CachedStream.Position = 0L;
                        int hashCode = 0;
                        if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt ||
                            verifyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt)
                        {
                            Utility.Converter.GetBytes(verifyInfo.HashCode, m_CachedHashBytes);
                            if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt)
                            {
                                hashCode = Utility.Verifier.GetCrc32(m_ResourceManager.m_CachedStream, m_CachedHashBytes, Utility.Encryption.QuickEncryptLength);
                            }
                            else if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt)
                            {
                                hashCode = Utility.Verifier.GetCrc32(m_ResourceManager.m_CachedStream, m_CachedHashBytes, length);
                            }

                            Array.Clear(m_CachedHashBytes, 0, CachedHashBytesLength);
                        }
                        else
                        {
                            hashCode = Utility.Verifier.GetCrc32(m_ResourceManager.m_CachedStream);
                        }

                        if (hashCode == verifyInfo.HashCode)
                        {
                            return(true);
                        }
                    }

                    fileSystem.DeleteFile(fileName);
                    return(false);
                }
                else
                {
                    string resourcePath = Utility.Path.GetRegularPath(Path.Combine(m_ResourceManager.ReadWritePath, verifyInfo.ResourceName.FullName));
                    if (!File.Exists(resourcePath))
                    {
                        return(false);
                    }

                    using (FileStream fileStream = new FileStream(resourcePath, FileMode.Open, FileAccess.Read))
                    {
                        int length = (int)fileStream.Length;
                        if (length == verifyInfo.Length)
                        {
                            int hashCode = 0;
                            if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt ||
                                verifyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt)
                            {
                                Utility.Converter.GetBytes(verifyInfo.HashCode, m_CachedHashBytes);
                                if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt)
                                {
                                    hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, Utility.Encryption.QuickEncryptLength);
                                }
                                else if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt)
                                {
                                    hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, length);
                                }

                                Array.Clear(m_CachedHashBytes, 0, CachedHashBytesLength);
                            }
                            else
                            {
                                hashCode = Utility.Verifier.GetCrc32(fileStream);
                            }

                            if (hashCode == verifyInfo.HashCode)
                            {
                                return(true);
                            }
                        }
                    }

                    File.Delete(resourcePath);
                    return(false);
                }
            }
Example #21
0
        private async Task RefreshGuestNames(List <ServerUserAuthorizationResponse> list, bool refreshImages)
        {
            var users = _userManager.Users
                        .Where(i => !string.IsNullOrEmpty(i.ConnectUserId) && i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.Guest)
                        .ToList();

            foreach (var user in users)
            {
                var authorization = list.FirstOrDefault(i => string.Equals(i.UserId, user.ConnectUserId, StringComparison.Ordinal));

                if (authorization == null)
                {
                    _logger.Warn("Unable to find connect authorization record for user {0}", user.Name);
                    continue;
                }

                var syncConnectName  = true;
                var syncConnectImage = true;

                if (syncConnectName)
                {
                    var changed = !string.Equals(authorization.UserName, user.Name, StringComparison.OrdinalIgnoreCase);

                    if (changed)
                    {
                        await user.Rename(authorization.UserName).ConfigureAwait(false);
                    }
                }

                if (syncConnectImage)
                {
                    var imageUrl = authorization.UserImageUrl;

                    if (!string.IsNullOrWhiteSpace(imageUrl))
                    {
                        var changed = false;

                        if (!user.HasImage(ImageType.Primary))
                        {
                            changed = true;
                        }
                        else if (refreshImages)
                        {
                            using (var response = await _httpClient.SendAsync(new HttpRequestOptions
                            {
                                Url = imageUrl,
                                BufferContent = false
                            }, "HEAD").ConfigureAwait(false))
                            {
                                var length = response.ContentLength;

                                if (length != _fileSystem.GetFileInfo(user.GetImageInfo(ImageType.Primary, 0).Path).Length)
                                {
                                    changed = true;
                                }
                            }
                        }

                        if (changed)
                        {
                            await _providerManager.SaveImage(user, imageUrl, ImageType.Primary, null, CancellationToken.None).ConfigureAwait(false);

                            await user.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
                            {
                                ForceSave = true,
                            }, CancellationToken.None).ConfigureAwait(false);
                        }
                    }
                }
            }
        }
Example #22
0
        public async Task <HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
        {
            logger?.Info($"{nameof(GetImageResponse)}-{url}");
            int type = 0;
            var i    = url.IndexOf(image_type_param_name, StringComparison.OrdinalIgnoreCase);

            if (i > 0)
            {
                try
                {
                    var p = url.Substring(i + image_type_param_name.Length).Trim('=').Trim();
                    url = url.Substring(0, i - 1);//减去一个连接符
                    int.TryParse(p, out type);
                }
                catch (Exception ex)
                {
                    logger?.Error(ex.ToString());
                }
            }

            var key        = WebUtility.UrlEncode(url);
            var cache_file = Path.Combine(appPaths.GetImageCachePath().ToString(), key);

            byte[] bytes = null;

            //尝试从缓存中读取
            try
            {
                var fi = fileSystem.GetFileInfo(cache_file);

                //图片文件存在,且是24小时之内的
                if (fi.Exists && fileSystem.GetFileInfo(cache_file).LastWriteTimeUtc > DateTime.Now.AddDays(-1).ToUniversalTime())
                {
                    bytes = await fileSystem.ReadAllBytesAsync(cache_file);

                    logger?.Info($"Hit image cache {url} {cache_file}");
                    if (type == 1)
                    {
                        var ci = await CutImage(bytes);

                        if (ci != null)
                        {
                            return(ci);
                        }
                    }

                    fileExtensionContentTypeProvider.TryGetContentType(url, out var contentType);

                    return(new HttpResponseInfo()
                    {
                        Content = new MemoryStream(bytes),
                        ContentLength = bytes.Length,
                        ContentType = contentType ?? "image/jpeg",
                        StatusCode = HttpStatusCode.OK,
                    });
                }
            }
            catch (Exception ex)
            {
                logger?.Warn($"Read image cache error. {url} {cache_file} {ex.Message}");
            }

            try
            {
                var resp = await client.GetAsync(url, cancellationToken);

                if (resp.IsSuccessStatusCode == false)
                {
                    return(await Parse(resp));
                }

                try
                {
                    fileSystem.WriteAllBytes(cache_file, await resp.Content.ReadAsByteArrayAsync());
                    logger?.Info($"Save image cache {url} {cache_file} ");
                }
                catch (Exception ex)
                {
                    logger?.Warn($"Save image cache error. {url} {cache_file} {ex.Message}");
                }

                if (type == 1)
                {
                    var ci = await CutImage(await resp.Content.ReadAsByteArrayAsync());

                    if (ci != null)
                    {
                        return(ci);
                    }
                }

                return(await Parse(resp));
            }
            catch (Exception ex)
            {
                logger?.Error(ex.ToString());
            }
            return(new HttpResponseInfo());
        }
Example #23
0
 /// <summary>
 /// Sets the image path.
 /// </summary>
 /// <param name="item">The item.</param>
 /// <param name="type">The type.</param>
 /// <param name="imageIndex">Index of the image.</param>
 /// <param name="path">The path.</param>
 /// <exception cref="System.ArgumentNullException">imageIndex
 /// or
 /// imageIndex</exception>
 private void SetImagePath(IHasImages item, ImageType type, int?imageIndex, string path)
 {
     item.SetImagePath(type, imageIndex ?? 0, _fileSystem.GetFileInfo(path));
 }
        private void InnerFileOpen(object sender, WriterCommandEventArgs args)
        {
            if (args.Mode == WriterCommandEventMode.QueryState)
            {
                args.Enabled = args.Document != null && args.EditorControl != null;
            }
            if (args.Mode == WriterCommandEventMode.Invoke)
            {
                IFileSystem fs = args.Host.FileSystems.Docuemnt;
                args.Result = false;
                if (args.Document.Modified)
                {
                    if (QuerySave(args) == false)
                    {
                        return;
                    }
                }


                if (args.Parameter is System.IO.Stream)
                {
                    // 用户参数为一个文件流对象,则以XML的格式从这个流中加载数据
                    System.IO.Stream stream = (System.IO.Stream)args.Parameter;
                    args.EditorControl.LoadDocument(stream, FileFormat.XML);
                    args.Document.FileName = null;
                    args.Result            = true;
                    args.Document.OnSelectionChanged();
                    args.Document.OnDocumentContentChanged();
                    return;
                }

                string fileName = null;
                if (args.Parameter is string)
                {
                    // 用户指定文件名了
                    fileName = (string)args.Parameter;
                    if (fileName.StartsWith("rawxml:"))
                    {
                        // 认为是原生态的XML字符串
                        fileName = fileName.Substring("rawxml:".Length);
                        System.IO.StringReader myStr = new System.IO.StringReader(fileName);
                        args.EditorControl.LoadDocument(myStr, FileFormat.XML);
                        args.Document.FileName = null;
                        args.Result            = true;
                        args.Document.OnSelectionChanged();
                        args.Document.OnDocumentContentChanged();
                        return;
                    }
                }
                if (args.ShowUI)
                {
                    fileName = fs.BrowseOpen(args.Host.Services, fileName);
                    if (string.IsNullOrEmpty(fileName))
                    {
                        // 用户取消操作
                        return;
                    }
                }
                VFileInfo info = fs.GetFileInfo(args.Host.Services, fileName);
                if (info.Exists)
                {
                    FileFormat       format = WriterUtils.ParseFileFormat(info.Format);
                    System.IO.Stream stream = fs.Open(args.Host.Services, fileName);
                    if (args.Host.Debuger != null)
                    {
                        args.Host.Debuger.DebugLoadingFile(fileName);
                    }
                    if (stream != null)
                    {
                        int length = 0;
                        using (stream)
                        {
                            //args.Document.FileName = fileName;
                            args.EditorControl.Document.BaseUrl = System.IO.Path.GetDirectoryName(fileName) + "\\";
                            args.Document.FileName = fileName;
                            args.EditorControl.LoadDocument(stream, format);
                            args.Document.FileName = fileName;
                            length = (int)stream.Length;
                        }
                        if (args.Host.Debuger != null)
                        {
                            args.Host.Debuger.DebugLoadFileComplete(length);
                        }
                        args.Document.OnSelectionChanged();
                        args.Document.OnDocumentContentChanged();
                        args.Document.FileName = fileName;
                        args.Result            = true;
                        args.RefreshLevel      = UIStateRefreshLevel.All;
                    }
                    else
                    {
                        args.Result       = false;
                        args.RefreshLevel = UIStateRefreshLevel.None;
                        return;
                    }
                }
                else
                {
                    if (args.ShowUI)
                    {
                        MessageBox.Show(
                            args.EditorControl,
                            string.Format(WriterStrings.FileNotExist_FileName, fileName),
                            WriterStrings.SystemAlert,
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Information);
                    }
                    args.Result = false;
                }
            }
        }