/// <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); }
/// <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); }
/// <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); }
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); } }
/// <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)); }
/// <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)); }
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); } }
/// <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); }
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)); }