internal GameMetadata ProcessField( Game game, MetadataFieldSettings fieldSettings, MetadataField gameField, Func <GameMetadata, object> propertySelector, Dictionary <Guid, GameMetadata> existingStoreData, Dictionary <Guid, OnDemandMetadataProvider> existingPluginData, CancellationToken cancelToken) { if (fieldSettings.Sources.Any() == false) { return(null); } var getFieldArgs = new GetMetadataFieldArgs { CancelToken = cancelToken }; foreach (var source in fieldSettings.Sources) { if (cancelToken.IsCancellationRequested) { return(null); } try { // Skip Store source for manually added games. if (source == Guid.Empty && game.PluginId == Guid.Empty) { continue; } // Check if metadata from this source are already downloaded. if (existingStoreData.ContainsKey(source)) { if (existingStoreData[source] != null && propertySelector(existingStoreData[source]) != null) { return(existingStoreData[source]); } else { continue; } } // Check if downloader supports this game field. if (source != Guid.Empty) { var downloader = metadataDownloaders.FirstOrDefault(a => a.Id == source); if (downloader == null) { continue; } else if (downloader.SupportedFields?.Contains(gameField) != true) { continue; } } // Download metadata. GameMetadata metadata = null; if (source == Guid.Empty) { metadata = ProcessStoreDownload(game); existingStoreData.Add(source, metadata); } else { var downloader = metadataDownloaders.FirstOrDefault(a => a.Id == source); if (downloader == null) { continue; } OnDemandMetadataProvider provider = null; if (existingPluginData.ContainsKey(source)) { provider = existingPluginData[source]; } else { provider = downloader.GetMetadataProvider(new MetadataRequestOptions(game, true)); existingPluginData.Add(source, provider); } if (provider == null) { continue; } if (!provider.AvailableFields.Contains(gameField)) { continue; } metadata = new GameMetadata(); switch (gameField) { case MetadataField.Name: metadata.Name = provider.GetName(getFieldArgs); break; case MetadataField.Genres: metadata.Genres = provider.GetGenres(getFieldArgs)?.Where(a => a != null).ToHashSet(); break; case MetadataField.ReleaseDate: metadata.ReleaseDate = provider.GetReleaseDate(getFieldArgs); break; case MetadataField.Developers: metadata.Developers = provider.GetDevelopers(getFieldArgs)?.Where(a => a != null).ToHashSet(); break; case MetadataField.Publishers: metadata.Publishers = provider.GetPublishers(getFieldArgs)?.Where(a => a != null).ToHashSet(); break; case MetadataField.Tags: metadata.Tags = provider.GetTags(getFieldArgs)?.Where(a => a != null).ToHashSet(); break; case MetadataField.Description: metadata.Description = provider.GetDescription(getFieldArgs); break; case MetadataField.Links: metadata.Links = provider.GetLinks(getFieldArgs)?.Where(a => a != null).ToList(); break; case MetadataField.CriticScore: metadata.CriticScore = provider.GetCriticScore(getFieldArgs); break; case MetadataField.CommunityScore: metadata.CommunityScore = provider.GetCommunityScore(getFieldArgs); break; case MetadataField.Icon: metadata.Icon = provider.GetIcon(getFieldArgs); break; case MetadataField.CoverImage: metadata.CoverImage = provider.GetCoverImage(getFieldArgs); break; case MetadataField.BackgroundImage: metadata.BackgroundImage = provider.GetBackgroundImage(getFieldArgs); break; case MetadataField.Features: metadata.Features = provider.GetFeatures(getFieldArgs)?.Where(a => a != null).ToHashSet(); break; case MetadataField.AgeRating: metadata.AgeRatings = provider.GetAgeRatings(getFieldArgs)?.Where(a => a != null).ToHashSet(); break; case MetadataField.Region: metadata.Regions = provider.GetRegions(getFieldArgs)?.Where(a => a != null).ToHashSet(); break; case MetadataField.Series: metadata.Series = provider.GetSeries(getFieldArgs)?.Where(a => a != null).ToHashSet(); break; case MetadataField.Platform: metadata.Platforms = provider.GetPlatforms(getFieldArgs)?.Where(a => a != null).ToHashSet(); break; default: throw new NotImplementedException(); } } if (metadata != null && propertySelector(metadata) != null) { return(metadata); } else { continue; } } catch (Exception e) when(!PlayniteEnvironment.ThrowAllErrors) { logger.Error(e, $"Failed to process metadata download: {gameField}, {source}"); } } return(null); }