Пример #1
0
        /// <summary>
        /// Deslugs an artist name by finding the correct entry in the library
        /// </summary>
        /// <param name="name"></param>
        /// <param name="libraryManager"></param>
        /// <returns></returns>
        protected string DeSlugArtistName(string name, ILibraryManager libraryManager)
        {
            if (name.IndexOf(SlugChar) == -1)
            {
                return(name);
            }

            return(libraryManager.GetAllArtists()
                   .FirstOrDefault(i =>
            {
                i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));

                return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
            }) ?? name);
        }
Пример #2
0
        /// <summary>
        /// Gets all artists.
        /// </summary>
        /// <param name="allSongs">All songs.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="progress">The progress.</param>
        /// <returns>Task{Artist[]}.</returns>
        private async Task <List <MusicArtist> > GetAllArtists(IEnumerable <Audio> allSongs, CancellationToken cancellationToken, IProgress <double> progress)
        {
            var allArtists = _libraryManager.GetAllArtists(allSongs)
                             .ToList();

            var returnArtists = new List <MusicArtist>(allArtists.Count);

            var numComplete = 0;
            var numArtists  = allArtists.Count;

            foreach (var artist in allArtists)
            {
                cancellationToken.ThrowIfCancellationRequested();

                try
                {
                    var artistItem = _libraryManager.GetArtist(artist);

                    await artistItem.RefreshMetadata(cancellationToken).ConfigureAwait(false);

                    returnArtists.Add(artistItem);
                }
                catch (IOException ex)
                {
                    _logger.ErrorException("Error validating Artist {0}", ex, artist);
                }

                // Update progress
                numComplete++;
                double percent = numComplete;
                percent /= numArtists;

                progress.Report(100 * percent);
            }

            return(returnArtists);
        }
Пример #3
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 items = _libraryManager.GetAllArtists(new InternalItemsQuery())
                        .Items
                        .Select(i => i.Item1)
                        .ToList();

            var numComplete = 0;
            var count       = items.Count;

            foreach (var item in items)
            {
                try
                {
                    await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
                }
                catch (OperationCanceledException)
                {
                    // Don't clutter the log
                    break;
                }
                catch (Exception ex)
                {
                    _logger.ErrorException("Error refreshing {0}", ex, item.Name);
                }

                numComplete++;
                double percent = numComplete;
                percent /= count;
                percent *= 100;

                progress.Report(percent);
            }

            progress.Report(100);
        }
Пример #4
0
        private void CheckForMetadata(object sender, ElapsedEventArgs eventArgs)
        {
            try
            {
                queuedUpdateCheck.ToList().ForEach(async updateCheck =>
                {
                    Guid itemId = updateCheck.Key;

                    _logger.Debug("{0} queued for recheck", itemId.ToString());

                    BaseItem item = _libraryManager.GetItemById(itemId);

                    LibraryOptions itemLibraryOptions = _libraryManager.GetLibraryOptions(item);
                    DiscordOptions options            = Plugin.Instance.Configuration.Options.FirstOrDefault(opt => opt.MediaAddedOverride == true);
                    PublicSystemInfo sysInfo          = await _applicationHost.GetPublicSystemInfo(CancellationToken.None);
                    ServerConfiguration serverConfig  = _serverConfiguration.Configuration;

                    if (!isInVisibleLibrary(options.MediaBrowserUserId, item))
                    {
                        queuedUpdateCheck.Remove(itemId);
                        _logger.Debug("User does not have access to library, skipping...");
                        return;
                    }

                    // for whatever reason if you have extraction on during library scans then it waits for the extraction to finish before populating the metadata.... I don't get why the f**k it goes in that order
                    // its basically impossible to make a prediction on how long it could take as its dependent on the bitrate, duration, codec, and processing power of the system
                    Boolean localMetadataFallback = queuedUpdateCheck[itemId] >= (itemLibraryOptions.ExtractChapterImagesDuringLibraryScan ? Constants.MaxRetriesBeforeFallback * 5.5 : Constants.MaxRetriesBeforeFallback);

                    if (item.ProviderIds.Count > 0 || localMetadataFallback)
                    {
                        _logger.Debug("{0}[{1}] has metadata, sending notification", item.Id, item.Name);

                        string serverName  = options.ServerNameOverride ? serverConfig.ServerName : "Emby Server";
                        string LibraryType = item.GetType().Name;

                        // build primary info
                        DiscordMessage mediaAddedEmbed = new DiscordMessage
                        {
                            username   = options.Username,
                            avatar_url = options.AvatarUrl,
                            embeds     = new List <DiscordEmbed>()
                            {
                                new DiscordEmbed()
                                {
                                    color  = DiscordWebhookHelper.FormatColorCode(options.EmbedColor),
                                    footer = new Footer
                                    {
                                        text     = $"From {serverName}",
                                        icon_url = options.AvatarUrl
                                    },
                                    timestamp = DateTime.Now
                                }
                            },
                        };

                        // populate title

                        string titleText;

                        if (LibraryType == "Episode")
                        {
                            titleText = $"{item.Parent.Parent.Name} {(item.ParentIndexNumber != null ? $"S{formatIndex(item.ParentIndexNumber)}" : "")}{(item.IndexNumber != null ? $"E{formatIndex(item.IndexNumber)}" : "")} {item.Name}";
                        }
                        else
                        {
                            titleText = $"{item.Name} {(!String.IsNullOrEmpty(item.ProductionYear.ToString()) ? $"({item.ProductionYear.ToString()})" : "")}";
                        }

                        mediaAddedEmbed.embeds.First().title = _localizationManager.GetLocalizedString("ValueHasBeenAddedToLibrary").Replace("{0}", titleText).Replace("{1}", serverName);

                        // populate description
                        if (LibraryType == "Audio")
                        {
                            List <BaseItem> artists = _libraryManager.GetAllArtists(item);

                            IEnumerable <string> artistsFormat = artists.Select(artist =>
                            {
                                if (artist.ProviderIds.Count() > 0)
                                {
                                    KeyValuePair <string, string> firstProvider = artist.ProviderIds.FirstOrDefault();

                                    string providerUrl = firstProvider.Key == "MusicBrainzArtist" ? $"https://musicbrainz.org/artist/{firstProvider.Value}" : $"https://theaudiodb.com/artist/{firstProvider.Value}";

                                    return($"[{artist.Name}]({providerUrl})");
                                }
                                else
                                {
                                    return(artist.Name);
                                }
                            });

                            if (artists.Count() > 0)
                            {
                                mediaAddedEmbed.embeds.First().description = $"By {string.Join(", ", artistsFormat)}";
                            }
                        }
                        else
                        {
                            if (!String.IsNullOrEmpty(item.Overview))
                            {
                                mediaAddedEmbed.embeds.First().description = item.Overview;
                            }
                        }

                        // populate title URL
                        if (!String.IsNullOrEmpty(sysInfo.WanAddress) && !options.ExcludeExternalServerLinks)
                        {
                            mediaAddedEmbed.embeds.First().url = $"{sysInfo.WanAddress}/web/index.html#!/item?id={itemId}&serverId={sysInfo.Id}";
                        }

                        // populate images
                        if (item.HasImage(ImageType.Primary))
                        {
                            string imageUrl = "";

                            if (!item.GetImageInfo(ImageType.Primary, 0).IsLocalFile)
                            {
                                imageUrl = item.GetImagePath(ImageType.Primary);
                            }
                            else if (serverConfig.EnableRemoteAccess == true && !options.ExcludeExternalServerLinks) // in the future we can proxy images through memester server if people want to hide their server address
                            {
                                imageUrl = $"{sysInfo.WanAddress}/emby/Items/{itemId}/Images/Primary";
                            }
                            else
                            {
                                string localPath = item.GetImagePath(ImageType.Primary);
                                Stream imageData = _fileSystem.OpenRead(localPath);

                                try
                                {
                                    imageUrl = await MemesterServiceHelper.UploadImage(imageData, _jsonSerializer, _httpClient);
                                }
                                catch (Exception e)
                                {
                                    _logger.ErrorException("Failed to proxy image", e);
                                }
                            }

                            mediaAddedEmbed.embeds.First().thumbnail = new Thumbnail
                            {
                                url = imageUrl
                            };
                        }


                        if (options.MentionType == MentionTypes.Everyone)
                        {
                            mediaAddedEmbed.content = "@everyone";
                        }
                        else if (options.MentionType == MentionTypes.Here)
                        {
                            mediaAddedEmbed.content = "@here";
                        }

                        // populate external URLs
                        List <Field> providerFields = new List <Field>();

                        if (!localMetadataFallback)
                        {
                            item.ProviderIds.ToList().ForEach(provider =>
                            {
                                Field field = new Field
                                {
                                    name = "External Details"
                                };

                                Boolean didPopulate = true;

                                switch (provider.Key.ToLower())
                                {
                                case "imdb":
                                    field.value = $"[IMDb](https://www.imdb.com/title/{provider.Value}/)";
                                    break;

                                case "tmdb":
                                    field.value = $"[TMDb](https://www.themoviedb.org/{(LibraryType == "Movie" ? "movie" : "tv")}/{provider.Value})";
                                    break;

                                case "musicbrainztrack":
                                    field.value = $"[MusicBrainz Track](https://musicbrainz.org/track/{provider.Value})";
                                    break;

                                case "musicbrainzalbum":
                                    field.value = $"[MusicBrainz Album](https://musicbrainz.org/release/{provider.Value})";
                                    break;

                                case "theaudiodbalbum":
                                    field.value = $"[TADb Album](https://theaudiodb.com/album/{provider.Value})";
                                    break;

                                default:
                                    didPopulate = false;
                                    break;
                                }

                                if (didPopulate == true)
                                {
                                    providerFields.Add(field);
                                }
                            });

                            if (providerFields.Count() > 0)
                            {
                                mediaAddedEmbed.embeds.First().fields = providerFields;
                            }
                        }

                        pendingSendQueue.Add(mediaAddedEmbed, options);

                        queuedUpdateCheck.Remove(itemId);
                    }
                    else
                    {
                        queuedUpdateCheck[itemId]++;

                        _logger.Debug("Attempt: {0}", queuedUpdateCheck[itemId]);
                    }
                });
            }
            catch (Exception e)
            {
                _logger.ErrorException("Something unexpected happened in the update checker", e);
            }
        }
Пример #5
0
        /// <summary>
        /// Gets the search hints.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="user">The user.</param>
        /// <returns>IEnumerable{SearchHintResult}.</returns>
        /// <exception cref="System.ArgumentNullException">searchTerm</exception>
        private List <SearchHintInfo> GetSearchHints(SearchQuery query, User user)
        {
            var searchTerm = query.SearchTerm;

            if (string.IsNullOrEmpty(searchTerm))
            {
                throw new ArgumentNullException("searchTerm");
            }

            searchTerm = searchTerm.Trim().RemoveDiacritics();

            var excludeItemTypes = query.ExcludeItemTypes.ToList();
            var includeItemTypes = (query.IncludeItemTypes ?? Array.Empty <string>()).ToList();

            excludeItemTypes.Add(typeof(Year).Name);
            excludeItemTypes.Add(typeof(Folder).Name);

            if (query.IncludeGenres && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Genre", StringComparer.OrdinalIgnoreCase)))
            {
                if (!query.IncludeMedia)
                {
                    AddIfMissing(includeItemTypes, typeof(Genre).Name);
                    AddIfMissing(includeItemTypes, typeof(GameGenre).Name);
                    AddIfMissing(includeItemTypes, typeof(MusicGenre).Name);
                }
            }
            else
            {
                AddIfMissing(excludeItemTypes, typeof(Genre).Name);
                AddIfMissing(excludeItemTypes, typeof(GameGenre).Name);
                AddIfMissing(excludeItemTypes, typeof(MusicGenre).Name);
            }

            if (query.IncludePeople && (includeItemTypes.Count == 0 || includeItemTypes.Contains("People", StringComparer.OrdinalIgnoreCase) || includeItemTypes.Contains("Person", StringComparer.OrdinalIgnoreCase)))
            {
                if (!query.IncludeMedia)
                {
                    AddIfMissing(includeItemTypes, typeof(Person).Name);
                }
            }
            else
            {
                AddIfMissing(excludeItemTypes, typeof(Person).Name);
            }

            if (query.IncludeStudios && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Studio", StringComparer.OrdinalIgnoreCase)))
            {
                if (!query.IncludeMedia)
                {
                    AddIfMissing(includeItemTypes, typeof(Studio).Name);
                }
            }
            else
            {
                AddIfMissing(excludeItemTypes, typeof(Studio).Name);
            }

            if (query.IncludeArtists && (includeItemTypes.Count == 0 || includeItemTypes.Contains("MusicArtist", StringComparer.OrdinalIgnoreCase)))
            {
                if (!query.IncludeMedia)
                {
                    AddIfMissing(includeItemTypes, typeof(MusicArtist).Name);
                }
            }
            else
            {
                AddIfMissing(excludeItemTypes, typeof(MusicArtist).Name);
            }

            AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name);
            AddIfMissing(excludeItemTypes, typeof(Folder).Name);
            var mediaTypes = query.MediaTypes.ToList();

            if (includeItemTypes.Count > 0)
            {
                excludeItemTypes.Clear();
                mediaTypes.Clear();
            }

            var searchQuery = new InternalItemsQuery(user)
            {
                SearchTerm         = searchTerm,
                ExcludeItemTypes   = excludeItemTypes.ToArray(),
                IncludeItemTypes   = includeItemTypes.ToArray(),
                Limit              = query.Limit,
                IncludeItemsByName = string.IsNullOrEmpty(query.ParentId),
                ParentId           = string.IsNullOrEmpty(query.ParentId) ? Guid.Empty : new Guid(query.ParentId),
                OrderBy            = new[] { new ValueTuple <string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) },
                Recursive          = true,

                IsKids     = query.IsKids,
                IsMovie    = query.IsMovie,
                IsNews     = query.IsNews,
                IsSeries   = query.IsSeries,
                IsSports   = query.IsSports,
                MediaTypes = mediaTypes.ToArray(),

                DtoOptions = new DtoOptions
                {
                    Fields = new ItemFields[]
                    {
                        ItemFields.AirTime,
                        ItemFields.DateCreated,
                        ItemFields.ChannelInfo,
                        ItemFields.ParentId
                    }
                }
            };

            List <BaseItem> mediaItems;

            if (searchQuery.IncludeItemTypes.Length == 1 && string.Equals(searchQuery.IncludeItemTypes[0], "MusicArtist", StringComparison.OrdinalIgnoreCase))
            {
                if (!searchQuery.ParentId.Equals(Guid.Empty))
                {
                    searchQuery.AncestorIds = new[] { searchQuery.ParentId };
                }
                searchQuery.ParentId           = Guid.Empty;
                searchQuery.IncludeItemsByName = true;
                searchQuery.IncludeItemTypes   = Array.Empty <string>();
                mediaItems = _libraryManager.GetAllArtists(searchQuery).Items.Select(i => i.Item1).ToList();
            }
            else
            {
                mediaItems = _libraryManager.GetItemList(searchQuery);
            }

            return(mediaItems.Select(i => new SearchHintInfo
            {
                Item = i
            }).ToList());
        }
        /// <summary>
        /// Gets the search hints.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="user">The user.</param>
        /// <returns>IEnumerable{SearchHintResult}.</returns>
        /// <exception cref="System.ArgumentNullException">searchTerm</exception>
        private Task <IEnumerable <SearchHintInfo> > GetSearchHints(SearchQuery query, User user)
        {
            var searchTerm = query.SearchTerm;

            if (string.IsNullOrEmpty(searchTerm))
            {
                throw new ArgumentNullException("searchTerm");
            }

            searchTerm = searchTerm.Trim().RemoveDiacritics();

            searchTerm = this.FixUnicodeChars(searchTerm);

            var terms = GetWords(searchTerm);

            var excludeItemTypes = query.ExcludeItemTypes.ToList();
            var includeItemTypes = (query.IncludeItemTypes ?? Array.Empty <string>()).ToList();

            excludeItemTypes.Add(typeof(Year).Name);
            excludeItemTypes.Add(typeof(Folder).Name);

            if (query.IncludeGenres && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Genre", StringComparer.OrdinalIgnoreCase)))
            {
                if (!query.IncludeMedia)
                {
                    AddIfMissing(includeItemTypes, typeof(Genre).Name);
                    AddIfMissing(includeItemTypes, typeof(GameGenre).Name);
                    AddIfMissing(includeItemTypes, typeof(MusicGenre).Name);
                }
            }
            else
            {
                AddIfMissing(excludeItemTypes, typeof(Genre).Name);
                AddIfMissing(excludeItemTypes, typeof(GameGenre).Name);
                AddIfMissing(excludeItemTypes, typeof(MusicGenre).Name);
            }

            if (query.IncludePeople && (includeItemTypes.Count == 0 || includeItemTypes.Contains("People", StringComparer.OrdinalIgnoreCase) || includeItemTypes.Contains("Person", StringComparer.OrdinalIgnoreCase)))
            {
                if (!query.IncludeMedia)
                {
                    AddIfMissing(includeItemTypes, typeof(Person).Name);
                }
            }
            else
            {
                AddIfMissing(excludeItemTypes, typeof(Person).Name);
            }

            if (query.IncludeStudios && (includeItemTypes.Count == 0 || includeItemTypes.Contains("Studio", StringComparer.OrdinalIgnoreCase)))
            {
                if (!query.IncludeMedia)
                {
                    AddIfMissing(includeItemTypes, typeof(Studio).Name);
                }
            }
            else
            {
                AddIfMissing(excludeItemTypes, typeof(Studio).Name);
            }

            if (query.IncludeArtists && (includeItemTypes.Count == 0 || includeItemTypes.Contains("MusicArtist", StringComparer.OrdinalIgnoreCase)))
            {
                if (!query.IncludeMedia)
                {
                    AddIfMissing(includeItemTypes, typeof(MusicArtist).Name);
                }
            }
            else
            {
                AddIfMissing(excludeItemTypes, typeof(MusicArtist).Name);
            }

            AddIfMissing(excludeItemTypes, typeof(CollectionFolder).Name);
            AddIfMissing(excludeItemTypes, typeof(Folder).Name);
            var mediaTypes = query.MediaTypes.ToList();

            if (includeItemTypes.Count > 0)
            {
                excludeItemTypes.Clear();
                mediaTypes.Clear();
            }

            var searchQuery = new InternalItemsQuery(user)
            {
                NameContains       = searchTerm,
                ExcludeItemTypes   = excludeItemTypes.ToArray(excludeItemTypes.Count),
                IncludeItemTypes   = includeItemTypes.ToArray(includeItemTypes.Count),
                Limit              = query.Limit,
                IncludeItemsByName = string.IsNullOrEmpty(query.ParentId),
                ParentId           = string.IsNullOrEmpty(query.ParentId) ? (Guid?)null : new Guid(query.ParentId),
                OrderBy            = new[] { new Tuple <string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) },
                Recursive          = true,

                IsKids     = query.IsKids,
                IsMovie    = query.IsMovie,
                IsNews     = query.IsNews,
                IsSeries   = query.IsSeries,
                IsSports   = query.IsSports,
                MediaTypes = mediaTypes.ToArray(),

                DtoOptions = new DtoOptions
                {
                    Fields = new ItemFields[]
                    {
                        ItemFields.AirTime,
                        ItemFields.DateCreated,
                        ItemFields.ChannelInfo,
                        ItemFields.ParentId
                    }
                }
            };

            List <BaseItem> mediaItems;

            if (searchQuery.IncludeItemTypes.Length == 1 && string.Equals(searchQuery.IncludeItemTypes[0], "MusicArtist", StringComparison.OrdinalIgnoreCase))
            {
                if (searchQuery.ParentId.HasValue)
                {
                    searchQuery.AncestorIds = new Guid[] { searchQuery.ParentId.Value };
                }
                searchQuery.ParentId           = null;
                searchQuery.IncludeItemsByName = true;
                searchQuery.IncludeItemTypes   = Array.Empty <string>();
                mediaItems = _libraryManager.GetAllArtists(searchQuery).Items.Select(i => i.Item1).ToList();
            }
            else
            {
                mediaItems = _libraryManager.GetItemList(searchQuery);
            }

            var returnValue = mediaItems.Select(item =>
            {
                var index = GetIndex(item.Name, searchTerm, terms);

                return(new Tuple <BaseItem, string, int>(item, index.Item1, index.Item2));
            }).OrderBy(i => i.Item3).ThenBy(i => i.Item1.SortName).Select(i => new SearchHintInfo
            {
                Item        = i.Item1,
                MatchedTerm = i.Item2
            });

            return(Task.FromResult(returnValue));
        }
Пример #7
0
        /// <summary>
        /// Gets the search hints.
        /// </summary>
        /// <param name="inputItems">The input items.</param>
        /// <param name="query">The query.</param>
        /// <returns>IEnumerable{SearchHintResult}.</returns>
        /// <exception cref="System.ArgumentNullException">searchTerm</exception>
        private Task <IEnumerable <SearchHintInfo> > GetSearchHints(IEnumerable <BaseItem> inputItems, SearchQuery query)
        {
            var searchTerm = query.SearchTerm;

            if (string.IsNullOrEmpty(searchTerm))
            {
                throw new ArgumentNullException("searchTerm");
            }

            var terms = GetWords(searchTerm);

            var hints = new List <Tuple <BaseItem, string, int> >();

            var items = inputItems.Where(i => !(i is MusicArtist)).ToList();

            if (query.IncludeMedia)
            {
                // Add search hints based on item name
                hints.AddRange(items.Where(i => !string.IsNullOrEmpty(i.Name)).Select(item =>
                {
                    var index = GetIndex(item.Name, searchTerm, terms);

                    return(new Tuple <BaseItem, string, int>(item, index.Item1, index.Item2));
                }));
            }

            if (query.IncludeArtists)
            {
                // Find artists
                var artists = _libraryManager.GetAllArtists(items)
                              .ToList();

                foreach (var item in artists)
                {
                    var index = GetIndex(item, searchTerm, terms);

                    if (index.Item2 != -1)
                    {
                        try
                        {
                            var artist = _libraryManager.GetArtist(item);

                            hints.Add(new Tuple <BaseItem, string, int>(artist, index.Item1, index.Item2));
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error getting {0}", ex, item);
                        }
                    }
                }
            }

            if (query.IncludeGenres)
            {
                // Find genres, from non-audio items
                var genres = items.Where(i => !(i is IHasMusicGenres) && !(i is Game))
                             .SelectMany(i => i.Genres)
                             .Where(i => !string.IsNullOrEmpty(i))
                             .Distinct(StringComparer.OrdinalIgnoreCase)
                             .ToList();

                foreach (var item in genres)
                {
                    var index = GetIndex(item, searchTerm, terms);

                    if (index.Item2 != -1)
                    {
                        try
                        {
                            var genre = _libraryManager.GetGenre(item);

                            hints.Add(new Tuple <BaseItem, string, int>(genre, index.Item1, index.Item2));
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error getting {0}", ex, item);
                        }
                    }
                }

                // Find music genres
                var musicGenres = items.Where(i => i is IHasMusicGenres)
                                  .SelectMany(i => i.Genres)
                                  .Where(i => !string.IsNullOrEmpty(i))
                                  .Distinct(StringComparer.OrdinalIgnoreCase)
                                  .ToList();

                foreach (var item in musicGenres)
                {
                    var index = GetIndex(item, searchTerm, terms);

                    if (index.Item2 != -1)
                    {
                        try
                        {
                            var genre = _libraryManager.GetMusicGenre(item);

                            hints.Add(new Tuple <BaseItem, string, int>(genre, index.Item1, index.Item2));
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error getting {0}", ex, item);
                        }
                    }
                }

                // Find music genres
                var gameGenres = items.OfType <Game>()
                                 .SelectMany(i => i.Genres)
                                 .Where(i => !string.IsNullOrEmpty(i))
                                 .Distinct(StringComparer.OrdinalIgnoreCase)
                                 .ToList();

                foreach (var item in gameGenres)
                {
                    var index = GetIndex(item, searchTerm, terms);

                    if (index.Item2 != -1)
                    {
                        try
                        {
                            var genre = _libraryManager.GetGameGenre(item);

                            hints.Add(new Tuple <BaseItem, string, int>(genre, index.Item1, index.Item2));
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error getting {0}", ex, item);
                        }
                    }
                }
            }

            if (query.IncludeStudios)
            {
                // Find studios
                var studios = items.SelectMany(i => i.Studios)
                              .Where(i => !string.IsNullOrEmpty(i))
                              .Distinct(StringComparer.OrdinalIgnoreCase)
                              .ToList();

                foreach (var item in studios)
                {
                    var index = GetIndex(item, searchTerm, terms);

                    if (index.Item2 != -1)
                    {
                        try
                        {
                            var studio = _libraryManager.GetStudio(item);

                            hints.Add(new Tuple <BaseItem, string, int>(studio, index.Item1, index.Item2));
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error getting {0}", ex, item);
                        }
                    }
                }
            }

            if (query.IncludePeople)
            {
                // Find persons
                var persons = items.SelectMany(i => i.People)
                              .Select(i => i.Name)
                              .Where(i => !string.IsNullOrEmpty(i))
                              .Distinct(StringComparer.OrdinalIgnoreCase)
                              .ToList();

                foreach (var item in persons)
                {
                    var index = GetIndex(item, searchTerm, terms);

                    if (index.Item2 != -1)
                    {
                        try
                        {
                            var person = _libraryManager.GetPerson(item);

                            hints.Add(new Tuple <BaseItem, string, int>(person, index.Item1, index.Item2));
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error getting {0}", ex, item);
                        }
                    }
                }
            }

            var returnValue = hints.Where(i => i.Item3 >= 0).OrderBy(i => i.Item3).Select(i => new SearchHintInfo
            {
                Item        = i.Item1,
                MatchedTerm = i.Item2
            });

            return(Task.FromResult(returnValue));
        }
Пример #8
0
        private void CheckForMetadata(object sender, ElapsedEventArgs eventArgs)
        {
            try
            {
                int queueCount = queuedUpdateCheck.Count();
                if (queueCount > 0)
                {
                    _logger.Debug("Item in queue : {0}", queueCount);
                }

                queuedUpdateCheck.ToList().ForEach(async queuedItem =>
                {
                    // sometimes an update check might execute while another one is hanging and causes crash !
                    if (queuedUpdateCheck.ContainsKey(queuedItem.Key))
                    {
                        DiscordOptions options = queuedItem.Value.Configuration;
                        Guid itemId            = queuedItem.Value.ItemId;

                        _logger.Debug("{0} queued for recheck", itemId.ToString());

                        BaseItem item = _libraryManager.GetItemById(itemId);

                        LibraryOptions itemLibraryOptions = _libraryManager.GetLibraryOptions(item);
                        PublicSystemInfo sysInfo          = await _applicationHost.GetPublicSystemInfo(CancellationToken.None);
                        ServerConfiguration serverConfig  = _serverConfiguration.Configuration;

                        string LibraryType = item.GetType().Name;
                        string serverName  = options.ServerNameOverride ? serverConfig.ServerName : "Emby Server";

                        if (string.IsNullOrEmpty(serverName))
                        {
                            serverName = "Emby Server";
                        }

                        // for whatever reason if you have extraction on during library scans then it waits for the extraction to finish before populating the metadata.... I don't get why the f**k it goes in that order
                        // its basically impossible to make a prediction on how long it could take as its dependent on the bitrate, duration, codec, and processing power of the system
                        Boolean localMetadataFallback = queuedUpdateCheck[queuedItem.Key].Retries >= (itemLibraryOptions.ExtractChapterImagesDuringLibraryScan ? Constants.MaxRetriesBeforeFallback * 5.5 : Constants.MaxRetriesBeforeFallback);

                        if (item.ProviderIds.Count > 0 || localMetadataFallback)
                        {
                            _logger.Debug("{0}[{1}] has metadata (Local fallback: {2}), adding to queue", item.Id, item.Name, localMetadataFallback, options.MediaBrowserUserId);

                            if (queuedUpdateCheck.ContainsKey(queuedItem.Key))
                            {
                                queuedUpdateCheck.Remove(queuedItem.Key);                                                // remove it beforehand because if some operation takes any longer amount of time it might allow enough time for another notification to slip through
                            }
                            // build primary info
                            DiscordMessage mediaAddedEmbed = new DiscordMessage
                            {
                                username   = options.Username,
                                avatar_url = options.AvatarUrl,
                                embeds     = new List <DiscordEmbed>()
                                {
                                    new DiscordEmbed()
                                    {
                                        color  = DiscordWebhookHelper.FormatColorCode(options.EmbedColor),
                                        footer = new Footer
                                        {
                                            text     = $"From {serverName}",
                                            icon_url = options.AvatarUrl
                                        },
                                        timestamp = DateTime.Now
                                    }
                                },
                            };

                            // populate title
                            string titleText;
                            if (LibraryType == "Episode")
                            {
                                titleText = $"{item.Parent.Parent.Name}{(item.ParentIndexNumber.HasValue ? $" S{formatIndex(item.ParentIndexNumber)}" : "")}{(item.IndexNumber.HasValue ? $"E{formatIndex(item.IndexNumber)}" : "")} {item.Name}";
                            }
                            else if (LibraryType == "Season")
                            {
                                titleText = $"{item.Parent.Name} {item.Name}";
                            }
                            else
                            {
                                titleText = $"{item.Name}{(item.ProductionYear.HasValue ? $" ({item.ProductionYear.ToString()})" : "")}";
                            }

                            mediaAddedEmbed.embeds.First().title = $"{titleText} has been added to {serverName.Trim()}";

                            // populate description
                            if (LibraryType == "Audio")
                            {
                                List <BaseItem> artists = _libraryManager.GetAllArtists(item);

                                IEnumerable <string> artistsFormat = artists.Select(artist =>
                                {
                                    string formattedArtist = artist.Name;

                                    if (artist.ProviderIds.Count() > 0)
                                    {
                                        KeyValuePair <string, string> firstProvider = artist.ProviderIds.FirstOrDefault();

                                        string providerUrl = firstProvider.Key == "MusicBrainzArtist" ? $"https://musicbrainz.org/artist/{firstProvider.Value}" : $"https://theaudiodb.com/artist/{firstProvider.Value}";

                                        formattedArtist += $" [(Music Brainz)]({providerUrl})";
                                    }

                                    if (serverConfig.EnableRemoteAccess && !options.ExcludeExternalServerLinks)
                                    {
                                        formattedArtist += $" [(Emby)]({sysInfo.WanAddress}/web/index.html#!/item?id={itemId}&serverId={artist.InternalId})";
                                    }

                                    return(formattedArtist);
                                });

                                if (artists.Count() > 0)
                                {
                                    mediaAddedEmbed.embeds.First().description = $"By {string.Join(", ", artistsFormat)}";
                                }
                            }
                            else
                            {
                                if (!String.IsNullOrEmpty(item.Overview))
                                {
                                    mediaAddedEmbed.embeds.First().description = item.Overview;
                                }
                            }

                            // populate title URL
                            if (serverConfig.EnableRemoteAccess && !options.ExcludeExternalServerLinks)
                            {
                                mediaAddedEmbed.embeds.First().url = $"{sysInfo.WanAddress}/web/index.html#!/item?id={itemId}&serverId={sysInfo.Id}";
                            }

                            // populate images
                            if (item.HasImage(ImageType.Primary))
                            {
                                string imageUrl = "";

                                if (!item.GetImageInfo(ImageType.Primary, 0).IsLocalFile)
                                {
                                    imageUrl = item.GetImagePath(ImageType.Primary);
                                }
                                else if (serverConfig.EnableRemoteAccess == true && !options.ExcludeExternalServerLinks) // in the future we can proxy images through memester server if people want to hide their server address
                                {
                                    imageUrl = $"{sysInfo.WanAddress}/emby/Items/{itemId}/Images/Primary";
                                }
                                else
                                {
                                    string localPath = item.GetImagePath(ImageType.Primary);

                                    try
                                    {
                                        ImageServiceResponse response = MemesterServiceHelper.UploadImage(localPath, _jsonSerializer);
                                        imageUrl = response.filePath;
                                    }
                                    catch (Exception e)
                                    {
                                        _logger.ErrorException("Failed to proxy image", e);
                                    }
                                }

                                mediaAddedEmbed.embeds.First().thumbnail = new Thumbnail
                                {
                                    url = imageUrl
                                };
                            }

                            if (options.MentionType == MentionTypes.Everyone)
                            {
                                mediaAddedEmbed.content = "@everyone";
                            }
                            else if (options.MentionType == MentionTypes.Here)
                            {
                                mediaAddedEmbed.content = "@here";
                            }

                            // populate external URLs
                            List <Field> providerFields = new List <Field>();

                            if (!localMetadataFallback)
                            {
                                item.ProviderIds.ToList().ForEach(provider =>
                                {
                                    Field field = new Field
                                    {
                                        name = "External Links"
                                    };

                                    Boolean didPopulate = true;
                                    switch (provider.Key.ToLower())
                                    {
                                    case "imdb":
                                        field.value = $"[IMDb](https://www.imdb.com/title/{provider.Value}/)";
                                        break;

                                    case "tmdb":
                                        field.value = $"[TMDb](https://www.themoviedb.org/{(LibraryType == "Movie" ? "movie" : "tv")}/{provider.Value})";
                                        break;

                                    case "musicbrainztrack":
                                        field.value = $"[MusicBrainz Track](https://musicbrainz.org/track/{provider.Value})";
                                        break;

                                    case "musicbrainzalbum":
                                        field.value = $"[MusicBrainz Album](https://musicbrainz.org/release/{provider.Value})";
                                        break;

                                    case "theaudiodbalbum":
                                        field.value = $"[TADb Album](https://theaudiodb.com/album/{provider.Value})";
                                        break;

                                    default:
                                        didPopulate = false;
                                        break;
                                    }

                                    if (didPopulate == true)
                                    {
                                        providerFields.Add(field);
                                    }
                                });

                                if (providerFields.Count() > 0)
                                {
                                    mediaAddedEmbed.embeds.First().fields = providerFields;
                                }
                            }

                            pendingSendQueue.Add(mediaAddedEmbed, options);
                        }
                        else
                        {
                            if (queuedUpdateCheck.ContainsKey(queuedItem.Key))
                            {
                                queuedUpdateCheck[queuedItem.Key].Retries++;
                            }
                        }
                    }
                });
            }
            catch (Exception e)
            {
                _logger.ErrorException("Something unexpected happened in the item update checker", e);
            }
        }
Пример #9
0
        /// <summary>
        /// Gets the search hint result.
        /// </summary>
        /// <param name="hintInfo">The hint info.</param>
        /// <returns>SearchHintResult.</returns>
        private SearchHint GetSearchHintResult(SearchHintInfo hintInfo)
        {
            var item = hintInfo.Item;

            var result = new SearchHint
            {
                Name              = item.Name,
                IndexNumber       = item.IndexNumber,
                ParentIndexNumber = item.ParentIndexNumber,
                ItemId            = _dtoService.GetDtoId(item),
                Type              = item.GetClientTypeName(),
                MediaType         = item.MediaType,
                MatchedTerm       = hintInfo.MatchedTerm,
                DisplayMediaType  = item.DisplayMediaType,
                RunTimeTicks      = item.RunTimeTicks,
                ProductionYear    = item.ProductionYear
            };

            var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);

            if (primaryImageTag.HasValue)
            {
                result.PrimaryImageTag = primaryImageTag.Value;
            }

            SetThumbImageInfo(result, item);
            SetBackdropImageInfo(result, item);

            var episode = item as Episode;

            if (episode != null)
            {
                result.Series = episode.Series.Name;
            }

            var season = item as Season;

            if (season != null)
            {
                result.Series = season.Series.Name;

                result.EpisodeCount = season.GetRecursiveChildren(i => i is Episode).Count;
            }

            var series = item as Series;

            if (series != null)
            {
                result.EpisodeCount = series.GetRecursiveChildren(i => i is Episode).Count;
            }

            var album = item as MusicAlbum;

            if (album != null)
            {
                var songs = album.GetRecursiveChildren().OfType <Audio>().ToList();

                result.SongCount = songs.Count;

                result.Artists = _libraryManager.GetAllArtists(songs)
                                 .ToArray();

                result.AlbumArtist = songs.Select(i => i.AlbumArtist).FirstOrDefault(i => !string.IsNullOrEmpty(i));
            }

            var song = item as Audio;

            if (song != null)
            {
                result.Album       = song.Album;
                result.AlbumArtist = song.AlbumArtist;
                result.Artists     = song.Artists.ToArray();
            }

            return(result);
        }
Пример #10
0
        public object Get(GetFavoritesView request)
        {
            var user = _userManager.GetUserById(request.UserId);

            var allItems = user.RootFolder.GetRecursiveChildren(user)
                           .ToList();

            var allFavoriteItems = allItems.Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite)
                                   .ToList();

            var itemsWithImages = allFavoriteItems.Where(i => !string.IsNullOrEmpty(i.PrimaryImagePath))
                                  .ToList();

            var itemsWithBackdrops = allFavoriteItems.Where(i => i.GetImages(ImageType.Backdrop).Any())
                                     .ToList();

            var view = new FavoritesView();

            var fields = new List <ItemFields>();

            view.BackdropItems = FilterItemsForBackdropDisplay(itemsWithBackdrops)
                                 .Randomize("backdrop")
                                 .Take(10)
                                 .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                                 .ToList();

            var spotlightItems = itemsWithBackdrops.Randomize("spotlight")
                                 .Take(10)
                                 .ToList();

            view.SpotlightItems = spotlightItems
                                  .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                                  .ToList();

            fields.Add(ItemFields.PrimaryImageAspectRatio);

            view.Albums = itemsWithImages
                          .OfType <MusicAlbum>()
                          .Randomize()
                          .Take(4)
                          .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                          .ToList();

            view.Books = itemsWithImages
                         .OfType <Book>()
                         .Randomize()
                         .Take(6)
                         .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                         .ToList();

            view.Episodes = itemsWithImages
                            .OfType <Episode>()
                            .Randomize()
                            .Take(6)
                            .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                            .ToList();

            view.Games = itemsWithImages
                         .OfType <Game>()
                         .Randomize()
                         .Take(6)
                         .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                         .ToList();

            view.Movies = itemsWithImages
                          .OfType <Movie>()
                          .Randomize()
                          .Take(6)
                          .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                          .ToList();

            view.Series = itemsWithImages
                          .OfType <Series>()
                          .Randomize()
                          .Take(6)
                          .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                          .ToList();

            view.Songs = itemsWithImages
                         .OfType <Audio>()
                         .Randomize()
                         .Take(4)
                         .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                         .ToList();

            view.MiniSpotlights = itemsWithBackdrops
                                  .Except(spotlightItems)
                                  .Randomize()
                                  .Take(5)
                                  .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                                  .ToList();

            var artists = _libraryManager.GetAllArtists(allItems)
                          .Randomize()
                          .Select(i =>
            {
                try
                {
                    return(_libraryManager.GetArtist(i));
                }
                catch
                {
                    return(null);
                }
            })
                          .Where(i => i != null && _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite)
                          .Take(4)
                          .ToList();

            view.Artists = artists
                           .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
                           .ToList();

            return(ToOptimizedSerializedResultUsingCache(view));
        }