diff --git a/gaseous-server/Classes/Collections.cs b/gaseous-server/Classes/Collections.cs index ec9c90d..f9e5341 100644 --- a/gaseous-server/Classes/Collections.cs +++ b/gaseous-server/Classes/Collections.cs @@ -345,7 +345,7 @@ namespace gaseous_server.Classes ) && alwaysIncludeItem.PlatformId == platform.Id ) { - MinimalGameItem AlwaysIncludeGame = new MinimalGameItem(Games.GetGame(Communications.MetadataSource, alwaysIncludeItem.GameId)); + MinimalGameItem AlwaysIncludeGame = new MinimalGameItem(Games.GetGame(HasheousClient.Models.MetadataSources.IGDB, alwaysIncludeItem.GameId)); CollectionContents.CollectionPlatformItem.CollectionGameItem gameItem = new CollectionContents.CollectionPlatformItem.CollectionGameItem(AlwaysIncludeGame); gameItem.InclusionStatus = new CollectionItem.AlwaysIncludeItem(); gameItem.InclusionStatus.PlatformId = alwaysIncludeItem.PlatformId; diff --git a/gaseous-server/Classes/Config.cs b/gaseous-server/Classes/Config.cs index 88237f0..1b65dd0 100644 --- a/gaseous-server/Classes/Config.cs +++ b/gaseous-server/Classes/Config.cs @@ -114,7 +114,12 @@ namespace gaseous_server.Classes if (File.Exists(ConfigurationFilePath)) { string configRaw = File.ReadAllText(ConfigurationFilePath); - ConfigFile? _tempConfig = Newtonsoft.Json.JsonConvert.DeserializeObject(configRaw); + Newtonsoft.Json.JsonSerializerSettings serializerSettings = new Newtonsoft.Json.JsonSerializerSettings + { + NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore, + MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore + }; + ConfigFile? _tempConfig = Newtonsoft.Json.JsonConvert.DeserializeObject(configRaw, serializerSettings); if (_tempConfig != null) { _config = _tempConfig; @@ -130,7 +135,8 @@ namespace gaseous_server.Classes _config.DatabaseConfiguration.Password = (string)Common.GetEnvVar("dbpass", _config.DatabaseConfiguration.Password); _config.DatabaseConfiguration.DatabaseName = (string)Common.GetEnvVar("dbname", _config.DatabaseConfiguration.DatabaseName); _config.DatabaseConfiguration.Port = int.Parse((string)Common.GetEnvVar("dbport", _config.DatabaseConfiguration.Port.ToString())); - _config.MetadataConfiguration.MetadataSource = (HasheousClient.Models.MetadataModel.MetadataSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.MetadataSources), (string)Common.GetEnvVar("metadatasource", _config.MetadataConfiguration.MetadataSource.ToString())); + _config.MetadataConfiguration.DefaultMetadataSource = (HasheousClient.Models.MetadataSources)Enum.Parse(typeof(HasheousClient.Models.MetadataSources), (string)Common.GetEnvVar("metadatasource", _config.MetadataConfiguration.DefaultMetadataSource.ToString())); + _config.MetadataConfiguration.MetadataUseHasheousProxy = bool.Parse((string)Common.GetEnvVar("metadatausehasheousproxy", _config.MetadataConfiguration.MetadataUseHasheousProxy.ToString())); _config.MetadataConfiguration.SignatureSource = (HasheousClient.Models.MetadataModel.SignatureSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.SignatureSources), (string)Common.GetEnvVar("signaturesource", _config.MetadataConfiguration.SignatureSource.ToString())); ; _config.MetadataConfiguration.MaxLibraryScanWorkers = int.Parse((string)Common.GetEnvVar("maxlibraryscanworkers", _config.MetadataConfiguration.MaxLibraryScanWorkers.ToString())); _config.MetadataConfiguration.HasheousHost = (string)Common.GetEnvVar("hasheoushost", _config.MetadataConfiguration.HasheousHost); @@ -684,17 +690,32 @@ namespace gaseous_server.Classes } } - private static HasheousClient.Models.MetadataModel.MetadataSources _MetadataSource + private static HasheousClient.Models.MetadataSources _MetadataSource { get { if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("metadatasource"))) { - return (HasheousClient.Models.MetadataModel.MetadataSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.MetadataSources), Environment.GetEnvironmentVariable("metadatasource")); + return (HasheousClient.Models.MetadataSources)Enum.Parse(typeof(HasheousClient.Models.MetadataSources), Environment.GetEnvironmentVariable("metadatasource")); } else { - return HasheousClient.Models.MetadataModel.MetadataSources.IGDB; + return HasheousClient.Models.MetadataSources.IGDB; + } + } + } + + private static bool _MetadataUseHasheousProxy + { + get + { + if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("metadatausehasheousproxy"))) + { + return bool.Parse(Environment.GetEnvironmentVariable("metadatausehasheousproxy")); + } + else + { + return true; } } } @@ -748,7 +769,9 @@ namespace gaseous_server.Classes } } - public HasheousClient.Models.MetadataModel.MetadataSources MetadataSource = _MetadataSource; + public HasheousClient.Models.MetadataSources DefaultMetadataSource = _MetadataSource; + + public bool MetadataUseHasheousProxy = _MetadataUseHasheousProxy; public HasheousClient.Models.MetadataModel.SignatureSources SignatureSource = _SignatureSource; diff --git a/gaseous-server/Classes/DatabaseMigration.cs b/gaseous-server/Classes/DatabaseMigration.cs index 863041b..87ffd98 100644 --- a/gaseous-server/Classes/DatabaseMigration.cs +++ b/gaseous-server/Classes/DatabaseMigration.cs @@ -394,7 +394,7 @@ namespace gaseous_server.Classes ); HasheousClient.Models.Metadata.IGDB.Platform platform = Platforms.GetPlatform((long)row["PlatformId"]); - Game game = Games.GetGame(Communications.MetadataSource, (long)row["GameId"]); + Game game = Games.GetGame(HasheousClient.Models.MetadataSources.IGDB, (long)row["GameId"]); ImportGame.StoreROM(library, hash, game, platform, signature, (string)row["Path"], (long)row["Id"]); diff --git a/gaseous-server/Classes/FileSignature.cs b/gaseous-server/Classes/FileSignature.cs index c634c73..a9c4f81 100644 --- a/gaseous-server/Classes/FileSignature.cs +++ b/gaseous-server/Classes/FileSignature.cs @@ -3,6 +3,7 @@ using System.IO.Compression; using System.Net; using gaseous_server.Classes.Metadata; using HasheousClient.Models; +using HasheousClient.Models.Metadata.IGDB; using Microsoft.CodeAnalysis.CSharp.Syntax; using NuGet.Common; using SevenZip; @@ -185,6 +186,22 @@ namespace gaseous_server.Classes } } + // get discovered platform + Platform? determinedPlatform = null; + if (library.DefaultPlatformId == null || library.DefaultPlatformId == 0) + { + determinedPlatform = Metadata.Platforms.GetPlatform((long)discoveredSignature.Flags.PlatformId); + if (determinedPlatform == null) + { + determinedPlatform = new Platform(); + } + } + else + { + determinedPlatform = Metadata.Platforms.GetPlatform((long)library.DefaultPlatformId); + discoveredSignature.MetadataSources.AddPlatform((long)determinedPlatform.Id, determinedPlatform.Name, MetadataSources.None); + } + return discoveredSignature; } @@ -237,7 +254,7 @@ namespace gaseous_server.Classes gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, ImageExtension, false); Logging.Log(Logging.LogType.Information, "Import Game", " Determined import file as: " + discoveredSignature.Game.Name + " (" + discoveredSignature.Game.Year + ") " + discoveredSignature.Game.System); - Logging.Log(Logging.LogType.Information, "Import Game", " Platform determined to be: " + discoveredSignature.Flags.IGDBPlatformName + " (" + discoveredSignature.Flags.IGDBPlatformId + ")"); + Logging.Log(Logging.LogType.Information, "Import Game", " Platform determined to be: " + discoveredSignature.Flags.PlatformName + " (" + discoveredSignature.Flags.PlatformId + ")"); return discoveredSignature; } @@ -319,12 +336,8 @@ namespace gaseous_server.Classes { if (metadataResult.Id.Length > 0) { - switch (metadataResult.Source) - { - case HasheousClient.Models.MetadataSources.IGDB: - signature.Flags.IGDBPlatformId = (long)Platforms.GetPlatform(metadataResult.Id).Id; - break; - } + Platform hasheousPlatform = Platforms.GetPlatform(metadataResult.Id); + signature.MetadataSources.AddPlatform((long)hasheousPlatform.Id, hasheousPlatform.Name, metadataResult.Source); } } } @@ -339,12 +352,8 @@ namespace gaseous_server.Classes { if (metadataResult.Id.Length > 0) { - switch (metadataResult.Source) - { - case HasheousClient.Models.MetadataSources.IGDB: - signature.Flags.IGDBGameId = (long)Games.GetGame(Communications.MetadataSource, metadataResult.Id).Id; - break; - } + Game hasheousGame = Games.GetGame(MetadataSources.IGDB, metadataResult.Id); + signature.MetadataSources.AddGame((long)hasheousGame.Id, hasheousGame.Name, metadataResult.Source); } } } diff --git a/gaseous-server/Classes/ImportGames.cs b/gaseous-server/Classes/ImportGames.cs index 2575a15..2a4916f 100644 --- a/gaseous-server/Classes/ImportGames.cs +++ b/gaseous-server/Classes/ImportGames.cs @@ -159,30 +159,15 @@ namespace gaseous_server.Classes FileSignature fileSignature = new FileSignature(); gaseous_server.Models.Signatures_Games discoveredSignature = fileSignature.GetFileSignature(GameLibrary.GetDefaultLibrary, Hash, fi, FilePath); - // get discovered platform - Platform? determinedPlatform = null; - if (OverridePlatform == null) - { - determinedPlatform = Metadata.Platforms.GetPlatform(discoveredSignature.Flags.IGDBPlatformId); - if (determinedPlatform == null) - { - determinedPlatform = new Platform(); - } - } - else - { - determinedPlatform = OverridePlatform; - discoveredSignature.Flags.IGDBPlatformId = (long)determinedPlatform.Id; - discoveredSignature.Flags.IGDBPlatformName = determinedPlatform.Name; - } - // add to database - long RomId = StoreGame(GameLibrary.GetDefaultLibrary, Hash, discoveredSignature, determinedPlatform, FilePath, 0, false); + Platform? determinedPlatform = Metadata.Platforms.GetPlatform((long)discoveredSignature.Flags.PlatformId); + Models.Game? determinedGame = Metadata.Games.GetGame(discoveredSignature.Flags.GameMetadataSource, discoveredSignature.Flags.GameId); + long RomId = StoreGame(GameLibrary.GetDefaultLibrary, Hash, discoveredSignature, determinedPlatform, FilePath, 0, true); // build return value GameFileInfo.Add("romid", RomId); GameFileInfo.Add("platform", determinedPlatform); - GameFileInfo.Add("game", discoveredSignature.Game.Name); + GameFileInfo.Add("game", determinedGame); GameFileInfo.Add("signature", discoveredSignature); GameFileInfo.Add("status", "imported"); } @@ -217,34 +202,45 @@ namespace gaseous_server.Classes Dictionary dbDict = new Dictionary(); - // add the metadata map - // check if the map exists already - long mapId = 0; - sql = "SELECT ParentMapId FROM MetadataMapBridge WHERE SignatureGameName=@gamename AND SignaturePlatformId=@platformid;"; - dbDict = new Dictionary(){ - { "gamename", signature.Game.Name }, - { "platformid", platform.Id } - }; - DataTable mapDT = db.ExecuteCMD(sql, dbDict); + // add/get the metadata map + MetadataMap? map = MetadataManagement.NewMetadataMap((long)platform.Id, signature.Game.Name); - if (mapDT.Rows.Count > 0) + // populate map with the sources from the signature if they don't already exist + bool reloadMap = false; + foreach (MetadataSources source in Enum.GetValues(typeof(MetadataSources))) { - mapId = (long)mapDT.Rows[0]["ParentMapId"]; + if (source != MetadataSources.None) + { + // check the signature for the source, and if it exists, add it to the map if it's not already there + foreach (Signatures_Games.SourceValues.SourceValueItem signatureSource in signature.MetadataSources.Games) + { + // check if the metadata map contains the source + bool sourceExists = false; + foreach (MetadataMap.MetadataMapItem mapSource in map.MetadataMapItems) + { + if (mapSource.SourceType == source) + { + sourceExists = true; + } + } + + if (sourceExists == false) + { + // add the source to the map + bool preferred = false; + if (source == Config.MetadataConfiguration.DefaultMetadataSource) + { + preferred = true; + } + MetadataManagement.AddMetadataMapItem((long)map.Id, source, signatureSource.Id, preferred); + reloadMap = true; + } + } + } } - else + if (reloadMap == true) { - sql = "INSERT INTO MetadataMapBridge (ParentMapId, SignatureGameName, SignaturePlatformId, MetadataSourceType, MetadataSourceId, Preferred, ProcessedAtImport) VALUES (@parentmapid, @gamename, @platformid, @metadatasourcetype, @metadatasourceid, @preferred, @processedatimport); SELECT CAST(LAST_INSERT_ID() AS SIGNED);"; - dbDict = new Dictionary(){ - { "parentmapid", 0 }, - { "gamename", signature.Game.Name }, - { "platformid", platform.Id }, - { "metadatasourcetype", MetadataModel.MetadataSources.None }, - { "metadatasourceid", 0 }, // set to zero as an initial value - another process will update this later - { "preferred", 1 }, - { "processedatimport", 0 } - }; - DataTable mapInsert = db.ExecuteCMD(sql, dbDict); - mapId = (long)mapInsert.Rows[0][0]; + map = MetadataManagement.GetMetadataMap((long)map.Id); } // add or update the rom @@ -271,7 +267,7 @@ namespace gaseous_server.Classes dbDict.Add("metadataversion", 2); dbDict.Add("libraryid", library.Id); dbDict.Add("romdataversion", 2); - dbDict.Add("metadatamapid", mapId); + dbDict.Add("metadatamapid", map.Id); if (signature.Rom.Attributes != null) { @@ -308,7 +304,7 @@ namespace gaseous_server.Classes // move to destination if (library.IsDefaultLibrary == true) { - //MoveGameFile(romId, SourceIsExternal); + MoveGameFile(romId, SourceIsExternal); } return romId; @@ -318,12 +314,12 @@ namespace gaseous_server.Classes { if (Signature.Flags != null) { - if (Signature.Flags.IGDBGameId != null && Signature.Flags.IGDBGameId != 0) + if (Signature.Flags.GameId != null && Signature.Flags.GameId != 0) { // game was determined elsewhere - probably a Hasheous server try { - return Games.GetGame(Communications.MetadataSource, Signature.Flags.IGDBGameId); + return Games.GetGame(MetadataSources.IGDB, Signature.Flags.GameId); } catch (Exception ex) { @@ -354,7 +350,7 @@ namespace gaseous_server.Classes if (games.Length == 1) { // exact match! - determinedGame = Metadata.Games.GetGame(Communications.MetadataSource, (long)games[0].Id); + determinedGame = Metadata.Games.GetGame(MetadataSources.IGDB, (long)games[0].Id); Logging.Log(Logging.LogType.Information, "Import Game", " IGDB game: " + determinedGame.Name); GameFound = true; break; @@ -369,7 +365,7 @@ namespace gaseous_server.Classes if (game.Name == SearchCandidate) { // found game title matches the search candidate - determinedGame = Metadata.Games.GetGame(Communications.MetadataSource, (long)games[0].Id); + determinedGame = Metadata.Games.GetGame(MetadataSources.IGDB, (long)games[0].Id); Logging.Log(Logging.LogType.Information, "Import Game", "Found exact match!"); GameFound = true; break; @@ -551,8 +547,8 @@ namespace gaseous_server.Classes Classes.Roms.GameRomItem rom = Classes.Roms.GetRom(RomId); // get metadata - Platform platform = gaseous_server.Classes.Metadata.Platforms.GetPlatform(rom.PlatformId); - gaseous_server.Models.Game game = gaseous_server.Classes.Metadata.Games.GetGame(Communications.MetadataSource, rom.GameId); + Platform? platform = gaseous_server.Classes.Metadata.Platforms.GetPlatform(rom.PlatformId); + gaseous_server.Models.Game? game = gaseous_server.Classes.Metadata.Games.GetGame(Config.MetadataConfiguration.DefaultMetadataSource, rom.GameId); // build path string platformSlug = "Unknown Platform"; @@ -866,7 +862,7 @@ namespace gaseous_server.Classes long PlatformId; Platform determinedPlatform; - if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0) + if (sig.Flags.PlatformId == null || sig.Flags.PlatformId == 0) { // no platform discovered in the signature PlatformId = library.DefaultPlatformId; @@ -874,7 +870,7 @@ namespace gaseous_server.Classes else { // use the platform discovered in the signature - PlatformId = sig.Flags.IGDBPlatformId; + PlatformId = (long)sig.Flags.PlatformId; } determinedPlatform = Platforms.GetPlatform(PlatformId); @@ -992,7 +988,7 @@ namespace gaseous_server.Classes long PlatformId; Platform determinedPlatform; - if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0) + if (sig.Flags.PlatformId == null || sig.Flags.PlatformId == 0) { // no platform discovered in the signature PlatformId = library.DefaultPlatformId; @@ -1000,7 +996,7 @@ namespace gaseous_server.Classes else { // use the platform discovered in the signature - PlatformId = sig.Flags.IGDBPlatformId; + PlatformId = (long)sig.Flags.PlatformId; } determinedPlatform = Platforms.GetPlatform(PlatformId); diff --git a/gaseous-server/Classes/Metadata/AgeGroups.cs b/gaseous-server/Classes/Metadata/AgeGroups.cs index ac92f9b..7777981 100644 --- a/gaseous-server/Classes/Metadata/AgeGroups.cs +++ b/gaseous-server/Classes/Metadata/AgeGroups.cs @@ -23,7 +23,7 @@ namespace gaseous_server.Classes.Metadata else { Storage.CacheStatus? cacheStatus = new Storage.CacheStatus(); - cacheStatus = Storage.GetCacheStatus(Communications.MetadataSource, "AgeGroup", (long)game.Id); + cacheStatus = Storage.GetCacheStatus(HasheousClient.Models.MetadataSources.IGDB, "AgeGroup", (long)game.Id); AgeGroup? RetVal = new AgeGroup(); @@ -31,16 +31,16 @@ namespace gaseous_server.Classes.Metadata { case Storage.CacheStatus.NotPresent: RetVal = _GetAgeGroup(game); - Storage.NewCacheValue(Communications.MetadataSource, RetVal, false); + Storage.NewCacheValue(HasheousClient.Models.MetadataSources.IGDB, RetVal, false); break; case Storage.CacheStatus.Expired: RetVal = _GetAgeGroup(game); - Storage.NewCacheValue(Communications.MetadataSource, RetVal, true); + Storage.NewCacheValue(HasheousClient.Models.MetadataSources.IGDB, RetVal, true); break; case Storage.CacheStatus.Current: - RetVal = Storage.GetCacheValue(Communications.MetadataSource, RetVal, "Id", game.Id); + RetVal = Storage.GetCacheValue(HasheousClient.Models.MetadataSources.IGDB, RetVal, "Id", game.Id); break; default: diff --git a/gaseous-server/Classes/Metadata/AgeRating.cs b/gaseous-server/Classes/Metadata/AgeRating.cs index 597a7bc..c9f1541 100644 --- a/gaseous-server/Classes/Metadata/AgeRating.cs +++ b/gaseous-server/Classes/Metadata/AgeRating.cs @@ -15,7 +15,7 @@ namespace gaseous_server.Classes.Metadata { } - public static AgeRating? GetAgeRating(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static AgeRating? GetAgeRating(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { @@ -28,7 +28,7 @@ namespace gaseous_server.Classes.Metadata } } - public static GameAgeRating GetConsolidatedAgeRating(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long RatingId) + public static GameAgeRating GetConsolidatedAgeRating(HasheousClient.Models.MetadataSources SourceType, long RatingId) { GameAgeRating gameAgeRating = new GameAgeRating(); diff --git a/gaseous-server/Classes/Metadata/AgeRatingContentDescriptions.cs b/gaseous-server/Classes/Metadata/AgeRatingContentDescriptions.cs index 0be7086..f610301 100644 --- a/gaseous-server/Classes/Metadata/AgeRatingContentDescriptions.cs +++ b/gaseous-server/Classes/Metadata/AgeRatingContentDescriptions.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static AgeRatingContentDescription? GetAgeRatingContentDescriptions(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static AgeRatingContentDescription? GetAgeRatingContentDescriptions(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/AlternativeNames.cs b/gaseous-server/Classes/Metadata/AlternativeNames.cs index 9163d46..2713cf9 100644 --- a/gaseous-server/Classes/Metadata/AlternativeNames.cs +++ b/gaseous-server/Classes/Metadata/AlternativeNames.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static AlternativeName? GetAlternativeNames(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static AlternativeName? GetAlternativeNames(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/Artworks.cs b/gaseous-server/Classes/Metadata/Artworks.cs index 3326cc5..62c92ef 100644 --- a/gaseous-server/Classes/Metadata/Artworks.cs +++ b/gaseous-server/Classes/Metadata/Artworks.cs @@ -11,7 +11,7 @@ namespace gaseous_server.Classes.Metadata { } - public static Artwork? GetArtwork(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static Artwork? GetArtwork(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/Collections.cs b/gaseous-server/Classes/Metadata/Collections.cs index 2adb518..ec63cbf 100644 --- a/gaseous-server/Classes/Metadata/Collections.cs +++ b/gaseous-server/Classes/Metadata/Collections.cs @@ -11,7 +11,7 @@ namespace gaseous_server.Classes.Metadata { } - public static Collection? GetCollections(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static Collection? GetCollections(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/Communications.cs b/gaseous-server/Classes/Metadata/Communications.cs index 43ec8fa..590639e 100644 --- a/gaseous-server/Classes/Metadata/Communications.cs +++ b/gaseous-server/Classes/Metadata/Communications.cs @@ -45,7 +45,7 @@ namespace gaseous_server.Classes.Metadata /// /// Configure metadata API communications /// - public static HasheousClient.Models.MetadataModel.MetadataSources MetadataSource + public static HasheousClient.Models.MetadataSources MetadataSource { get { @@ -57,25 +57,27 @@ namespace gaseous_server.Classes.Metadata switch (value) { - case HasheousClient.Models.MetadataModel.MetadataSources.IGDB: - // set rate limiter avoidance values - RateLimitAvoidanceWait = 1500; - RateLimitAvoidanceThreshold = 3; - RateLimitAvoidancePeriod = 1; + case HasheousClient.Models.MetadataSources.IGDB: + if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false) + { + // set rate limiter avoidance values + RateLimitAvoidanceWait = 1500; + RateLimitAvoidanceThreshold = 3; + RateLimitAvoidancePeriod = 1; - // set rate limiter recovery values - RateLimitRecoveryWaitTime = 10000; + // set rate limiter recovery values + RateLimitRecoveryWaitTime = 10000; + } + else + { + // set rate limiter avoidance values + RateLimitAvoidanceWait = 1500; + RateLimitAvoidanceThreshold = 6; + RateLimitAvoidancePeriod = 1; - break; - - case HasheousClient.Models.MetadataModel.MetadataSources.Hasheous: - // set rate limiter avoidance values - RateLimitAvoidanceWait = 1500; - RateLimitAvoidanceThreshold = 6; - RateLimitAvoidancePeriod = 1; - - // set rate limiter recovery values - RateLimitRecoveryWaitTime = 10000; + // set rate limiter recovery values + RateLimitRecoveryWaitTime = 10000; + } break; @@ -85,7 +87,7 @@ namespace gaseous_server.Classes.Metadata } } } - private static HasheousClient.Models.MetadataModel.MetadataSources _MetadataSource = HasheousClient.Models.MetadataModel.MetadataSources.None; + private static HasheousClient.Models.MetadataSources _MetadataSource = HasheousClient.Models.MetadataSources.None; // rate limit avoidance - what can we do to ensure that rate limiting is avoided? // these values affect all communications @@ -245,40 +247,44 @@ namespace gaseous_server.Classes.Metadata /// /// The object requested /// - public async Task APIComm(HasheousClient.Models.MetadataModel.MetadataSources SourceType, MetadataEndpoint Endpoint, string Slug) + public async Task APIComm(HasheousClient.Models.MetadataSources SourceType, MetadataEndpoint Endpoint, string Slug) { switch (SourceType) { - case HasheousClient.Models.MetadataModel.MetadataSources.None: + case HasheousClient.Models.MetadataSources.None: return null; - case HasheousClient.Models.MetadataModel.MetadataSources.IGDB: - string fieldList = ""; - string query = "where slug = \"" + Slug + "\""; - string EndpointString = ""; - - switch (Endpoint) + case HasheousClient.Models.MetadataSources.IGDB: + if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false) { - case MetadataEndpoint.Platform: - fieldList = Platforms.fieldList; - EndpointString = IGDBClient.Endpoints.Platforms; - break; + string fieldList = ""; + string query = "where slug = \"" + Slug + "\""; + string EndpointString = ""; - case MetadataEndpoint.Game: - fieldList = Games.fieldList; - EndpointString = IGDBClient.Endpoints.Games; - break; + switch (Endpoint) + { + case MetadataEndpoint.Platform: + fieldList = Platforms.fieldList; + EndpointString = IGDBClient.Endpoints.Platforms; + break; - default: - throw new Exception("Endpoint must be either Platform or Game"); + case MetadataEndpoint.Game: + fieldList = Games.fieldList; + EndpointString = IGDBClient.Endpoints.Games; + break; + default: + throw new Exception("Endpoint must be either Platform or Game"); + + } + + return await IGDBAPI(EndpointString, fieldList, query); } + else + { + ConfigureHasheousClient(ref hasheous); - return await IGDBAPI(EndpointString, fieldList, query); - - case HasheousClient.Models.MetadataModel.MetadataSources.Hasheous: - ConfigureHasheousClient(ref hasheous); - - return await HasheousAPI(Endpoint.ToString(), "slug", Slug); + return await HasheousAPI(Endpoint.ToString(), "slug", Slug); + } default: return null; @@ -323,145 +329,149 @@ namespace gaseous_server.Classes.Metadata /// /// The object requested /// - public async Task APIComm(HasheousClient.Models.MetadataModel.MetadataSources SourceType, MetadataEndpoint Endpoint, long Id) + public async Task APIComm(HasheousClient.Models.MetadataSources SourceType, MetadataEndpoint Endpoint, long Id) { switch (SourceType) { - case HasheousClient.Models.MetadataModel.MetadataSources.None: + case HasheousClient.Models.MetadataSources.None: return null; - case HasheousClient.Models.MetadataModel.MetadataSources.IGDB: - string fieldList = ""; - string query = "where id = " + Id; - string EndpointString = ""; - - switch (Endpoint) + case HasheousClient.Models.MetadataSources.IGDB: + if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false) { - case MetadataEndpoint.AgeRating: - fieldList = AgeRatings.fieldList; - EndpointString = IGDBClient.Endpoints.AgeRating; - break; + string fieldList = ""; + string query = "where id = " + Id; + string EndpointString = ""; - case MetadataEndpoint.AgeRatingContentDescription: - fieldList = AgeRatingContentDescriptions.fieldList; - EndpointString = IGDBClient.Endpoints.AgeRatingContentDescriptions; - break; + switch (Endpoint) + { + case MetadataEndpoint.AgeRating: + fieldList = AgeRatings.fieldList; + EndpointString = IGDBClient.Endpoints.AgeRating; + break; - case MetadataEndpoint.AlternativeName: - fieldList = AlternativeNames.fieldList; - EndpointString = IGDBClient.Endpoints.AlternativeNames; - break; + case MetadataEndpoint.AgeRatingContentDescription: + fieldList = AgeRatingContentDescriptions.fieldList; + EndpointString = IGDBClient.Endpoints.AgeRatingContentDescriptions; + break; - case MetadataEndpoint.Artwork: - fieldList = Artworks.fieldList; - EndpointString = IGDBClient.Endpoints.Artworks; - break; + case MetadataEndpoint.AlternativeName: + fieldList = AlternativeNames.fieldList; + EndpointString = IGDBClient.Endpoints.AlternativeNames; + break; - case MetadataEndpoint.Collection: - fieldList = Collections.fieldList; - EndpointString = IGDBClient.Endpoints.Collections; - break; + case MetadataEndpoint.Artwork: + fieldList = Artworks.fieldList; + EndpointString = IGDBClient.Endpoints.Artworks; + break; - case MetadataEndpoint.Company: - fieldList = Companies.fieldList; - EndpointString = IGDBClient.Endpoints.Companies; - break; + case MetadataEndpoint.Collection: + fieldList = Collections.fieldList; + EndpointString = IGDBClient.Endpoints.Collections; + break; - case MetadataEndpoint.CompanyLogo: - fieldList = CompanyLogos.fieldList; - EndpointString = IGDBClient.Endpoints.CompanyLogos; - break; + case MetadataEndpoint.Company: + fieldList = Companies.fieldList; + EndpointString = IGDBClient.Endpoints.Companies; + break; - case MetadataEndpoint.Cover: - fieldList = Covers.fieldList; - EndpointString = IGDBClient.Endpoints.Covers; - break; + case MetadataEndpoint.CompanyLogo: + fieldList = CompanyLogos.fieldList; + EndpointString = IGDBClient.Endpoints.CompanyLogos; + break; - case MetadataEndpoint.ExternalGame: - fieldList = ExternalGames.fieldList; - EndpointString = IGDBClient.Endpoints.ExternalGames; - break; + case MetadataEndpoint.Cover: + fieldList = Covers.fieldList; + EndpointString = IGDBClient.Endpoints.Covers; + break; - case MetadataEndpoint.Franchise: - fieldList = Franchises.fieldList; - EndpointString = IGDBClient.Endpoints.Franchies; - break; + case MetadataEndpoint.ExternalGame: + fieldList = ExternalGames.fieldList; + EndpointString = IGDBClient.Endpoints.ExternalGames; + break; - case MetadataEndpoint.GameMode: - fieldList = GameModes.fieldList; - EndpointString = IGDBClient.Endpoints.GameModes; - break; + case MetadataEndpoint.Franchise: + fieldList = Franchises.fieldList; + EndpointString = IGDBClient.Endpoints.Franchies; + break; - case MetadataEndpoint.Game: - fieldList = Games.fieldList; - EndpointString = IGDBClient.Endpoints.Games; - break; + case MetadataEndpoint.GameMode: + fieldList = GameModes.fieldList; + EndpointString = IGDBClient.Endpoints.GameModes; + break; - case MetadataEndpoint.GameVideo: - fieldList = GamesVideos.fieldList; - EndpointString = IGDBClient.Endpoints.GameVideos; - break; + case MetadataEndpoint.Game: + fieldList = Games.fieldList; + EndpointString = IGDBClient.Endpoints.Games; + break; - case MetadataEndpoint.Genre: - fieldList = Genres.fieldList; - EndpointString = IGDBClient.Endpoints.Genres; - break; + case MetadataEndpoint.GameVideo: + fieldList = GamesVideos.fieldList; + EndpointString = IGDBClient.Endpoints.GameVideos; + break; - case MetadataEndpoint.InvolvedCompany: - fieldList = InvolvedCompanies.fieldList; - EndpointString = IGDBClient.Endpoints.InvolvedCompanies; - break; + case MetadataEndpoint.Genre: + fieldList = Genres.fieldList; + EndpointString = IGDBClient.Endpoints.Genres; + break; - case MetadataEndpoint.MultiplayerMode: - fieldList = MultiplayerModes.fieldList; - EndpointString = IGDBClient.Endpoints.MultiplayerModes; - break; + case MetadataEndpoint.InvolvedCompany: + fieldList = InvolvedCompanies.fieldList; + EndpointString = IGDBClient.Endpoints.InvolvedCompanies; + break; - case MetadataEndpoint.PlatformLogo: - fieldList = PlatformLogos.fieldList; - EndpointString = IGDBClient.Endpoints.PlatformLogos; - break; + case MetadataEndpoint.MultiplayerMode: + fieldList = MultiplayerModes.fieldList; + EndpointString = IGDBClient.Endpoints.MultiplayerModes; + break; - case MetadataEndpoint.Platform: - fieldList = Platforms.fieldList; - EndpointString = IGDBClient.Endpoints.Platforms; - break; + case MetadataEndpoint.PlatformLogo: + fieldList = PlatformLogos.fieldList; + EndpointString = IGDBClient.Endpoints.PlatformLogos; + break; - case MetadataEndpoint.PlatformVersion: - fieldList = PlatformVersions.fieldList; - EndpointString = IGDBClient.Endpoints.PlatformVersions; - break; + case MetadataEndpoint.Platform: + fieldList = Platforms.fieldList; + EndpointString = IGDBClient.Endpoints.Platforms; + break; - case MetadataEndpoint.PlayerPerspective: - fieldList = PlayerPerspectives.fieldList; - EndpointString = IGDBClient.Endpoints.PlayerPerspectives; - break; + case MetadataEndpoint.PlatformVersion: + fieldList = PlatformVersions.fieldList; + EndpointString = IGDBClient.Endpoints.PlatformVersions; + break; - case MetadataEndpoint.ReleaseDate: - fieldList = ReleaseDates.fieldList; - EndpointString = IGDBClient.Endpoints.ReleaseDates; - break; + case MetadataEndpoint.PlayerPerspective: + fieldList = PlayerPerspectives.fieldList; + EndpointString = IGDBClient.Endpoints.PlayerPerspectives; + break; - case MetadataEndpoint.Screenshot: - fieldList = Screenshots.fieldList; - EndpointString = IGDBClient.Endpoints.Screenshots; - break; + case MetadataEndpoint.ReleaseDate: + fieldList = ReleaseDates.fieldList; + EndpointString = IGDBClient.Endpoints.ReleaseDates; + break; - case MetadataEndpoint.Theme: - fieldList = Themes.fieldList; - EndpointString = IGDBClient.Endpoints.Themes; - break; + case MetadataEndpoint.Screenshot: + fieldList = Screenshots.fieldList; + EndpointString = IGDBClient.Endpoints.Screenshots; + break; - default: - throw new Exception("Endpoint must be either Platform or Game"); + case MetadataEndpoint.Theme: + fieldList = Themes.fieldList; + EndpointString = IGDBClient.Endpoints.Themes; + break; + default: + throw new Exception("Endpoint must be either Platform or Game"); + + } + + return await IGDBAPI(EndpointString, fieldList, query); } + else + { + ConfigureHasheousClient(ref hasheous); - return await IGDBAPI(EndpointString, fieldList, query); - - case HasheousClient.Models.MetadataModel.MetadataSources.Hasheous: - ConfigureHasheousClient(ref hasheous); - - return await HasheousAPI(Endpoint.ToString(), "id", Id.ToString()); + return await HasheousAPI(Endpoint.ToString(), "id", Id.ToString()); + } default: return null; } @@ -514,12 +524,17 @@ namespace gaseous_server.Classes.Metadata { switch (_MetadataSource) { - case HasheousClient.Models.MetadataModel.MetadataSources.None: - return null; - case HasheousClient.Models.MetadataModel.MetadataSources.IGDB: - return await IGDBAPI(Endpoint, Fields, Query); - case HasheousClient.Models.MetadataModel.MetadataSources.Hasheous: + case HasheousClient.Models.MetadataSources.None: return null; + case HasheousClient.Models.MetadataSources.IGDB: + if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false) + { + return await IGDBAPI(Endpoint, Fields, Query); + } + else + { + return null; + } default: return null; } @@ -1132,12 +1147,15 @@ namespace gaseous_server.Classes.Metadata Communications comms = new Communications(); switch (_MetadataSource) { - case HasheousClient.Models.MetadataModel.MetadataSources.IGDB: - await comms.IGDBAPI_GetImage(ImageId, ImagePath); - break; - - case HasheousClient.Models.MetadataModel.MetadataSources.Hasheous: - await comms.HasheousAPI_GetImage(ImageId, ImagePath); + case HasheousClient.Models.MetadataSources.IGDB: + if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false) + { + await comms.IGDBAPI_GetImage(ImageId, ImagePath); + } + else + { + await comms.HasheousAPI_GetImage(ImageId, ImagePath); + } break; default: diff --git a/gaseous-server/Classes/Metadata/Company.cs b/gaseous-server/Classes/Metadata/Company.cs index 74c68a3..bad5512 100644 --- a/gaseous-server/Classes/Metadata/Company.cs +++ b/gaseous-server/Classes/Metadata/Company.cs @@ -11,7 +11,7 @@ namespace gaseous_server.Classes.Metadata { } - public static Company? GetCompanies(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static Company? GetCompanies(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/Covers.cs b/gaseous-server/Classes/Metadata/Covers.cs index c5da931..f92c0ce 100644 --- a/gaseous-server/Classes/Metadata/Covers.cs +++ b/gaseous-server/Classes/Metadata/Covers.cs @@ -11,7 +11,7 @@ namespace gaseous_server.Classes.Metadata { } - public static Cover? GetCover(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static Cover? GetCover(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/ExternalGames.cs b/gaseous-server/Classes/Metadata/ExternalGames.cs index bddf097..eebb9fa 100644 --- a/gaseous-server/Classes/Metadata/ExternalGames.cs +++ b/gaseous-server/Classes/Metadata/ExternalGames.cs @@ -11,7 +11,7 @@ namespace gaseous_server.Classes.Metadata { } - public static ExternalGame? GetExternalGames(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static ExternalGame? GetExternalGames(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/Franchises.cs b/gaseous-server/Classes/Metadata/Franchises.cs index a34c176..4e19098 100644 --- a/gaseous-server/Classes/Metadata/Franchises.cs +++ b/gaseous-server/Classes/Metadata/Franchises.cs @@ -11,7 +11,7 @@ namespace gaseous_server.Classes.Metadata { } - public static Franchise? GetFranchises(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static Franchise? GetFranchises(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/GameModes.cs b/gaseous-server/Classes/Metadata/GameModes.cs index 002160a..1ef7640 100644 --- a/gaseous-server/Classes/Metadata/GameModes.cs +++ b/gaseous-server/Classes/Metadata/GameModes.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static GameMode? GetGame_Modes(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static GameMode? GetGame_Modes(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/GameVideos.cs b/gaseous-server/Classes/Metadata/GameVideos.cs index 33ef710..2e07b70 100644 --- a/gaseous-server/Classes/Metadata/GameVideos.cs +++ b/gaseous-server/Classes/Metadata/GameVideos.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static GameVideo? GetGame_Videos(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static GameVideo? GetGame_Videos(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/Games.cs b/gaseous-server/Classes/Metadata/Games.cs index 65b8ee2..edab952 100644 --- a/gaseous-server/Classes/Metadata/Games.cs +++ b/gaseous-server/Classes/Metadata/Games.cs @@ -20,7 +20,7 @@ namespace gaseous_server.Classes.Metadata { } } - public static Game? GetGame(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static Game? GetGame(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { @@ -35,7 +35,7 @@ namespace gaseous_server.Classes.Metadata } } - public static Game? GetGame(HasheousClient.Models.MetadataModel.MetadataSources SourceType, string? Slug) + public static Game? GetGame(HasheousClient.Models.MetadataSources SourceType, string? Slug) { Game? RetVal = Metadata.GetMetadata(SourceType, Slug, false); RetVal.MetadataSource = SourceType; @@ -157,67 +157,70 @@ namespace gaseous_server.Classes.Metadata private static async Task _SearchForGameRemote(string SearchString, long PlatformId, SearchType searchType) { - switch (Communications.MetadataSource) + switch (Config.MetadataConfiguration.DefaultMetadataSource) { - case HasheousClient.Models.MetadataModel.MetadataSources.None: + case HasheousClient.Models.MetadataSources.None: return new Game[0]; - case HasheousClient.Models.MetadataModel.MetadataSources.IGDB: - string searchBody = ""; - string searchFields = "fields id,name,slug,platforms,summary; "; - bool allowSearch = true; - switch (searchType) + case HasheousClient.Models.MetadataSources.IGDB: + if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false) { - case SearchType.searchNoPlatform: - searchBody = "search \"" + SearchString + "\"; "; - - allowSearch = AllowNoPlatformSearch; - break; - case SearchType.search: - searchBody = "search \"" + SearchString + "\"; where platforms = (" + PlatformId + ");"; - break; - case SearchType.wherefuzzy: - searchBody = "where platforms = (" + PlatformId + ") & name ~ *\"" + SearchString + "\"*;"; - break; - case SearchType.where: - searchBody = "where platforms = (" + PlatformId + ") & name ~ \"" + SearchString + "\";"; - break; - } - - // check search cache - Game[]? games = Communications.GetSearchCache(searchFields, searchBody); - - if (games == null) - { - // cache miss - // get Game metadata - Communications comms = new Communications(); - Game[]? results = new Game[0]; - if (allowSearch == true) + string searchBody = ""; + string searchFields = "fields id,name,slug,platforms,summary; "; + bool allowSearch = true; + switch (searchType) { - results = await comms.APIComm(IGDB.IGDBClient.Endpoints.Games, searchFields, searchBody); + case SearchType.searchNoPlatform: + searchBody = "search \"" + SearchString + "\"; "; - Communications.SetSearchCache(searchFields, searchBody, results); + allowSearch = AllowNoPlatformSearch; + break; + case SearchType.search: + searchBody = "search \"" + SearchString + "\"; where platforms = (" + PlatformId + ");"; + break; + case SearchType.wherefuzzy: + searchBody = "where platforms = (" + PlatformId + ") & name ~ *\"" + SearchString + "\"*;"; + break; + case SearchType.where: + searchBody = "where platforms = (" + PlatformId + ") & name ~ \"" + SearchString + "\";"; + break; } - return results; + // check search cache + Game[]? games = Communications.GetSearchCache(searchFields, searchBody); + + if (games == null) + { + // cache miss + // get Game metadata + Communications comms = new Communications(); + Game[]? results = new Game[0]; + if (allowSearch == true) + { + results = await comms.APIComm(IGDB.IGDBClient.Endpoints.Games, searchFields, searchBody); + + Communications.SetSearchCache(searchFields, searchBody, results); + } + + return results; + } + else + { + return games.ToArray(); + } } else { - return games.ToArray(); + HasheousClient.Hasheous hasheous = new HasheousClient.Hasheous(); + HasheousClient.Models.Metadata.IGDB.Game[] hResults = hasheous.GetMetadataProxy_SearchGame(HasheousClient.Hasheous.MetadataProvider.IGDB, PlatformId.ToString(), SearchString); + + List hGames = new List(); + foreach (HasheousClient.Models.Metadata.IGDB.Game hResult in hResults) + { + hGames.Add(Communications.ConvertToIGDBModel(hResult)); + } + + return hGames.ToArray(); } - - case HasheousClient.Models.MetadataModel.MetadataSources.Hasheous: - HasheousClient.Hasheous hasheous = new HasheousClient.Hasheous(); - HasheousClient.Models.Metadata.IGDB.Game[] hResults = hasheous.GetMetadataProxy_SearchGame(HasheousClient.Hasheous.MetadataProvider.IGDB, PlatformId.ToString(), SearchString); - - List hGames = new List(); - foreach (HasheousClient.Models.Metadata.IGDB.Game hResult in hResults) - { - hGames.Add(Communications.ConvertToIGDBModel(hResult)); - } - - return hGames.ToArray(); - default: return new Game[0]; } @@ -396,6 +399,7 @@ ORDER BY Platform.`Name`;"; public MinimalGameItem(Game gameObject) { this.Id = gameObject.Id; + this.MetadataMapId = gameObject.MetadataMapId; this.Name = gameObject.Name; this.Slug = gameObject.Slug; this.Summary = gameObject.Summary; @@ -421,6 +425,7 @@ ORDER BY Platform.`Name`;"; } public long? Id { get; set; } + public long? MetadataMapId { get; set; } public long Index { get; set; } public string Name { get; set; } public string Slug { get; set; } diff --git a/gaseous-server/Classes/Metadata/Genres.cs b/gaseous-server/Classes/Metadata/Genres.cs index fbc5201..4e7fed1 100644 --- a/gaseous-server/Classes/Metadata/Genres.cs +++ b/gaseous-server/Classes/Metadata/Genres.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static Genre? GetGenres(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static Genre? GetGenres(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/InvolvedCompany.cs b/gaseous-server/Classes/Metadata/InvolvedCompany.cs index e77671d..3fafc6b 100644 --- a/gaseous-server/Classes/Metadata/InvolvedCompany.cs +++ b/gaseous-server/Classes/Metadata/InvolvedCompany.cs @@ -19,7 +19,7 @@ namespace gaseous_server.Classes.Metadata } else { - InvolvedCompany? RetVal = Metadata.GetMetadata(Communications.MetadataSource, (long)Id, false); + InvolvedCompany? RetVal = Metadata.GetMetadata(HasheousClient.Models.MetadataSources.IGDB, (long)Id, false); return RetVal; } } diff --git a/gaseous-server/Classes/Metadata/Metadata.cs b/gaseous-server/Classes/Metadata/Metadata.cs index 3bb2635..3af5891 100644 --- a/gaseous-server/Classes/Metadata/Metadata.cs +++ b/gaseous-server/Classes/Metadata/Metadata.cs @@ -5,19 +5,19 @@ namespace gaseous_server.Classes.Metadata #region Exception Handling public class InvalidMetadataId : Exception { - public InvalidMetadataId(long Id) : base("Invalid Metadata id: " + Id + " from source: " + Communications.MetadataSource + " (default)") + public InvalidMetadataId(long Id) : base("Invalid Metadata id: " + Id + " from source: " + HasheousClient.Models.MetadataSources.IGDB + " (default)") { } - public InvalidMetadataId(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long Id) : base("Invalid Metadata id: " + Id + " from source: " + SourceType) + public InvalidMetadataId(HasheousClient.Models.MetadataSources SourceType, long Id) : base("Invalid Metadata id: " + Id + " from source: " + SourceType) { } - public InvalidMetadataId(string Id) : base("Invalid Metadata id: " + Id + " from source: " + Communications.MetadataSource + " (default)") + public InvalidMetadataId(string Id) : base("Invalid Metadata id: " + Id + " from source: " + HasheousClient.Models.MetadataSources.IGDB + " (default)") { } - public InvalidMetadataId(HasheousClient.Models.MetadataModel.MetadataSources SourceType, string Id) : base("Invalid Metadata id: " + Id + " from source: " + SourceType) + public InvalidMetadataId(HasheousClient.Models.MetadataSources SourceType, string Id) : base("Invalid Metadata id: " + Id + " from source: " + SourceType) { } } @@ -46,7 +46,7 @@ namespace gaseous_server.Classes.Metadata throw new InvalidMetadataId(Id); } - return _GetMetadata(Communications.MetadataSource, Id, ForceRefresh); + return _GetMetadata(HasheousClient.Models.MetadataSources.IGDB, Id, ForceRefresh); } /// @@ -67,7 +67,7 @@ namespace gaseous_server.Classes.Metadata /// /// Thrown when the id is invalid /// - public static T? GetMetadata(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long Id, Boolean ForceRefresh = false) where T : class + public static T? GetMetadata(HasheousClient.Models.MetadataSources SourceType, long Id, Boolean ForceRefresh = false) where T : class { if (Id < 0) { @@ -77,12 +77,12 @@ namespace gaseous_server.Classes.Metadata return _GetMetadata(SourceType, Id, ForceRefresh); } - public static T? GetMetadata(HasheousClient.Models.MetadataModel.MetadataSources SourceType, string Slug, Boolean ForceRefresh = false) where T : class + public static T? GetMetadata(HasheousClient.Models.MetadataSources SourceType, string Slug, Boolean ForceRefresh = false) where T : class { return _GetMetadata(SourceType, Slug, ForceRefresh); } - private static T? _GetMetadata(HasheousClient.Models.MetadataModel.MetadataSources SourceType, object Id, Boolean ForceRefresh) where T : class + private static T? _GetMetadata(HasheousClient.Models.MetadataSources SourceType, object Id, Boolean ForceRefresh) where T : class { // get T type as string string type = typeof(T).Name; @@ -160,7 +160,7 @@ namespace gaseous_server.Classes.Metadata String } - private static async Task GetMetadataFromServer(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long Id) where T : class + private static async Task GetMetadataFromServer(HasheousClient.Models.MetadataSources SourceType, long Id) where T : class { // get T type as string string type = typeof(T).Name; @@ -178,7 +178,7 @@ namespace gaseous_server.Classes.Metadata return results.FirstOrDefault(); } - private static async Task GetMetadataFromServer(HasheousClient.Models.MetadataModel.MetadataSources SourceType, string Id) where T : class + private static async Task GetMetadataFromServer(HasheousClient.Models.MetadataSources SourceType, string Id) where T : class { // get T type as string string type = typeof(T).Name; diff --git a/gaseous-server/Classes/Metadata/MultiplayerModes.cs b/gaseous-server/Classes/Metadata/MultiplayerModes.cs index 66d7598..ab2c30e 100644 --- a/gaseous-server/Classes/Metadata/MultiplayerModes.cs +++ b/gaseous-server/Classes/Metadata/MultiplayerModes.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static MultiplayerMode? GetGame_MultiplayerModes(long? Id) + public static MultiplayerMode? GetGame_MultiplayerModes(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { @@ -20,7 +20,7 @@ namespace gaseous_server.Classes.Metadata } else { - MultiplayerMode? RetVal = Metadata.GetMetadata(Communications.MetadataSource, (long)Id, false); + MultiplayerMode? RetVal = Metadata.GetMetadata(SourceType, (long)Id, false); return RetVal; } } diff --git a/gaseous-server/Classes/Metadata/PlatformLogos.cs b/gaseous-server/Classes/Metadata/PlatformLogos.cs index 07771ef..89d56ad 100644 --- a/gaseous-server/Classes/Metadata/PlatformLogos.cs +++ b/gaseous-server/Classes/Metadata/PlatformLogos.cs @@ -20,7 +20,7 @@ namespace gaseous_server.Classes.Metadata } else { - PlatformLogo? RetVal = Metadata.GetMetadata(Communications.MetadataSource, (long)Id, false); + PlatformLogo? RetVal = Metadata.GetMetadata(HasheousClient.Models.MetadataSources.IGDB, (long)Id, false); return RetVal; } } diff --git a/gaseous-server/Classes/Metadata/PlatformVersions.cs b/gaseous-server/Classes/Metadata/PlatformVersions.cs index 1e26d3f..9ea43fe 100644 --- a/gaseous-server/Classes/Metadata/PlatformVersions.cs +++ b/gaseous-server/Classes/Metadata/PlatformVersions.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static PlatformVersion? GetPlatformVersion(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long Id) + public static PlatformVersion? GetPlatformVersion(HasheousClient.Models.MetadataSources SourceType, long Id) { if (Id == 0) { diff --git a/gaseous-server/Classes/Metadata/Platforms.cs b/gaseous-server/Classes/Metadata/Platforms.cs index 9a76f16..1992b7f 100644 --- a/gaseous-server/Classes/Metadata/Platforms.cs +++ b/gaseous-server/Classes/Metadata/Platforms.cs @@ -22,7 +22,7 @@ namespace gaseous_server.Classes.Metadata } else { - Platform? RetVal = Metadata.GetMetadata(Communications.MetadataSource, (long)Id, false); + Platform? RetVal = Metadata.GetMetadata(HasheousClient.Models.MetadataSources.IGDB, (long)Id, false); return RetVal; } } @@ -32,7 +32,7 @@ namespace gaseous_server.Classes.Metadata // get platform id from slug - query Platform table Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); string query = "SELECT Id FROM Platform WHERE slug = @slug AND SourceId = @sourceid;"; - DataTable result = db.ExecuteCMD(query, new Dictionary { { "@slug", Slug }, { "@sourceid", Communications.MetadataSource } }); + DataTable result = db.ExecuteCMD(query, new Dictionary { { "@slug", Slug }, { "@sourceid", HasheousClient.Models.MetadataSources.IGDB } }); if (result.Rows.Count == 0) { throw new Metadata.InvalidMetadataId(Slug); diff --git a/gaseous-server/Classes/Metadata/PlayerPerspectives.cs b/gaseous-server/Classes/Metadata/PlayerPerspectives.cs index 74a076e..6b222eb 100644 --- a/gaseous-server/Classes/Metadata/PlayerPerspectives.cs +++ b/gaseous-server/Classes/Metadata/PlayerPerspectives.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static PlayerPerspective? GetGame_PlayerPerspectives(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static PlayerPerspective? GetGame_PlayerPerspectives(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/ReleaseDates.cs b/gaseous-server/Classes/Metadata/ReleaseDates.cs index d08f9c9..1f51bae 100644 --- a/gaseous-server/Classes/Metadata/ReleaseDates.cs +++ b/gaseous-server/Classes/Metadata/ReleaseDates.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static ReleaseDate? GetReleaseDates(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static ReleaseDate? GetReleaseDates(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/Screenshots.cs b/gaseous-server/Classes/Metadata/Screenshots.cs index f8f57c4..114adf9 100644 --- a/gaseous-server/Classes/Metadata/Screenshots.cs +++ b/gaseous-server/Classes/Metadata/Screenshots.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static Screenshot? GetScreenshot(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static Screenshot? GetScreenshot(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/Metadata/Storage.cs b/gaseous-server/Classes/Metadata/Storage.cs index cc8ecc9..16647ef 100644 --- a/gaseous-server/Classes/Metadata/Storage.cs +++ b/gaseous-server/Classes/Metadata/Storage.cs @@ -45,7 +45,7 @@ namespace gaseous_server.Classes.Metadata /// /// The cache status of the record /// - public static CacheStatus GetCacheStatus(HasheousClient.Models.MetadataModel.MetadataSources SourceType, string Endpoint, string Slug) + public static CacheStatus GetCacheStatus(HasheousClient.Models.MetadataSources SourceType, string Endpoint, string Slug) { return _GetCacheStatus(SourceType, Endpoint, "slug", Slug); } @@ -65,7 +65,7 @@ namespace gaseous_server.Classes.Metadata /// /// The cache status of the record /// - public static CacheStatus GetCacheStatus(HasheousClient.Models.MetadataModel.MetadataSources SourceType, string Endpoint, long Id) + public static CacheStatus GetCacheStatus(HasheousClient.Models.MetadataSources SourceType, string Endpoint, long Id) { return _GetCacheStatus(SourceType, Endpoint, "id", Id); } @@ -102,7 +102,7 @@ namespace gaseous_server.Classes.Metadata } } - private static CacheStatus _GetCacheStatus(HasheousClient.Models.MetadataModel.MetadataSources SourceType, string Endpoint, string SearchField, object SearchValue) + private static CacheStatus _GetCacheStatus(HasheousClient.Models.MetadataSources SourceType, string Endpoint, string SearchField, object SearchValue) { Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); @@ -145,7 +145,7 @@ namespace gaseous_server.Classes.Metadata /// /// Whether to update the record if it already exists /// - public static void NewCacheValue(HasheousClient.Models.MetadataModel.MetadataSources SourceType, T ObjectToCache, bool UpdateRecord = false) + public static void NewCacheValue(HasheousClient.Models.MetadataSources SourceType, T ObjectToCache, bool UpdateRecord = false) { // get the object type name string ObjectTypeName = ObjectToCache.GetType().Name; @@ -182,7 +182,7 @@ namespace gaseous_server.Classes.Metadata } fieldList = fieldList + key.Key; valueList = valueList + "@" + key.Key; - if ((key.Key != "id") && (key.Key != "dateAdded")) + if ((key.Key != "id") && (key.Key != "dateAdded") && (key.Key != "SourceId")) { if (updateFieldValueList.Length > 0) { @@ -239,11 +239,11 @@ namespace gaseous_server.Classes.Metadata string sql = ""; if (UpdateRecord == false) { - sql = "INSERT INTO " + ObjectTypeName + " (" + fieldList + ") VALUES (" + valueList + ")"; + sql = "INSERT INTO " + ObjectTypeName + " (" + fieldList + ") VALUES (" + valueList + ");"; } else { - sql = "UPDATE " + ObjectTypeName + " SET " + updateFieldValueList + " WHERE Id = @Id"; + sql = "UPDATE " + ObjectTypeName + " SET " + updateFieldValueList + " WHERE Id = @Id AND SourceId = @SourceId;"; } // execute sql @@ -275,7 +275,7 @@ namespace gaseous_server.Classes.Metadata /// /// Thrown when no record is found that matches the search criteria /// - public static T GetCacheValue(HasheousClient.Models.MetadataModel.MetadataSources SourceType, T? EndpointType, string SearchField, object SearchValue) + public static T GetCacheValue(HasheousClient.Models.MetadataSources SourceType, T? EndpointType, string SearchField, object SearchValue) { string Endpoint = EndpointType.GetType().Name; @@ -311,55 +311,58 @@ namespace gaseous_server.Classes.Metadata if (property.GetCustomAttribute() == null) { // get the value from the DataRow with the same name as the property - object? value = dataRow[property.Name]; - - if (value != null && value != DBNull.Value) + if (dataRow.Table.Columns.Contains(property.Name) == true) { - // check the property type - if it's a list or array, deserialize it. Otherwise, just set the value - Type objectType = EndpointType.GetType(); - if (objectType != null) + object? value = dataRow[property.Name]; + + if (value != null && value != DBNull.Value) { - // fullname = System.Nullable`1[[System.DateTimeOffset, - string propertyTypeName = property.PropertyType.FullName.Split(",")[0]; - bool isNullable = false; - if (propertyTypeName.StartsWith("System.Nullable")) + // check the property type - if it's a list or array, deserialize it. Otherwise, just set the value + Type objectType = EndpointType.GetType(); + if (objectType != null) { - isNullable = true; - propertyTypeName = propertyTypeName.Split("[[")[1]; - } - propertyTypeName = propertyTypeName.Split("`")[0]; + // fullname = System.Nullable`1[[System.DateTimeOffset, + string propertyTypeName = property.PropertyType.FullName.Split(",")[0]; + bool isNullable = false; + if (propertyTypeName.StartsWith("System.Nullable")) + { + isNullable = true; + propertyTypeName = propertyTypeName.Split("[[")[1]; + } + propertyTypeName = propertyTypeName.Split("`")[0]; - switch (propertyTypeName.ToLower()) - { - case "system.collections.generic.list": - var listArray = Newtonsoft.Json.JsonConvert.DeserializeObject>(value.ToString()); - property.SetValue(EndpointType, listArray); - break; + switch (propertyTypeName.ToLower()) + { + case "system.collections.generic.list": + var listArray = Newtonsoft.Json.JsonConvert.DeserializeObject>(value.ToString()); + property.SetValue(EndpointType, listArray); + break; - case "system.int32[]": - var int32array = Newtonsoft.Json.JsonConvert.DeserializeObject(value.ToString()); - property.SetValue(EndpointType, int32array); - break; + case "system.int32[]": + var int32array = Newtonsoft.Json.JsonConvert.DeserializeObject(value.ToString()); + property.SetValue(EndpointType, int32array); + break; - case "system.datetimeoffset": - property.SetValue(EndpointType, (DateTimeOffset)(DateTime?)value); - break; + case "system.datetimeoffset": + property.SetValue(EndpointType, (DateTimeOffset)(DateTime?)value); + break; - default: - // check if property is an enum - if (property.PropertyType.IsEnum) - { - property.SetValue(EndpointType, Enum.Parse(property.PropertyType, value.ToString())); - } - else if (Common.IsNullableEnum(property.PropertyType)) - { - property.SetValue(EndpointType, Enum.Parse(Nullable.GetUnderlyingType(property.PropertyType), value.ToString())); - } - else - { - property.SetValue(EndpointType, value); - } - break; + default: + // check if property is an enum + if (property.PropertyType.IsEnum) + { + property.SetValue(EndpointType, Enum.Parse(property.PropertyType, value.ToString())); + } + else if (Common.IsNullableEnum(property.PropertyType)) + { + property.SetValue(EndpointType, Enum.Parse(Nullable.GetUnderlyingType(property.PropertyType), value.ToString())); + } + else + { + property.SetValue(EndpointType, value); + } + break; + } } } } diff --git a/gaseous-server/Classes/Metadata/Themes.cs b/gaseous-server/Classes/Metadata/Themes.cs index 1cf881e..359969d 100644 --- a/gaseous-server/Classes/Metadata/Themes.cs +++ b/gaseous-server/Classes/Metadata/Themes.cs @@ -12,7 +12,7 @@ namespace gaseous_server.Classes.Metadata { } - public static Theme? GetGame_Themes(HasheousClient.Models.MetadataModel.MetadataSources SourceType, long? Id) + public static Theme? GetGame_Themes(HasheousClient.Models.MetadataSources SourceType, long? Id) { if ((Id == 0) || (Id == null)) { diff --git a/gaseous-server/Classes/MetadataManagement.cs b/gaseous-server/Classes/MetadataManagement.cs index bdd4ae2..f9278ff 100644 --- a/gaseous-server/Classes/MetadataManagement.cs +++ b/gaseous-server/Classes/MetadataManagement.cs @@ -2,11 +2,202 @@ using System.Data; using gaseous_server.Classes.Metadata; using gaseous_server.Models; +using HasheousClient.Models; +using HasheousClient.Models.Metadata.IGDB; namespace gaseous_server.Classes { public class MetadataManagement : QueueItemStatus { + /// + /// Creates a new metadata map, if one with the same platformId and name does not already exist. + /// + /// + /// The ID of the platform to which the metadata map belongs. + /// + /// + /// The name of the metadata map. + /// + /// + /// The ID of the new metadata map, or the ID of the existing metadata map if one already exists. + /// + public static MetadataMap? NewMetadataMap(long platformId, string name) + { + Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); + string sql = ""; + Dictionary dbDict = new Dictionary() + { + { "@platformId", platformId }, + { "@name", name } + }; + DataTable dt = new DataTable(); + + // check if the metadata map already exists + MetadataMap? existingMetadataMap = GetMetadataMap(platformId, name); + if (existingMetadataMap != null) + { + return existingMetadataMap; + } + + // create the metadata map + sql = "INSERT INTO MetadataMap (PlatformId, SignatureGameName) VALUES (@platformId, @name); SELECT CAST(LAST_INSERT_ID() AS SIGNED);"; + dt = db.ExecuteCMD(sql, dbDict); + + long metadataMapId = (long)dt.Rows[0][0]; + + // create dummy game metadata item and capture id + sql = "INSERT INTO Game (SourceId, Name) VALUES (@sourceid, @name); SELECT CAST(LAST_INSERT_ID() AS SIGNED);"; + dbDict = new Dictionary() + { + { "@sourceid", HasheousClient.Models.MetadataSources.None }, + { "@name", name } + }; + dt = db.ExecuteCMD(sql, dbDict); + + long gameId = (long)dt.Rows[0][0]; + + // add default metadata sources + AddMetadataMapItem(metadataMapId, HasheousClient.Models.MetadataSources.None, gameId, true); + + // return the new metadata map + return GetMetadataMap(metadataMapId); + } + + /// + /// Adds a metadata map item to the database. + /// + /// + /// The ID of the metadata map to which the item belongs. + /// + /// + /// The type of the metadata source. + /// + /// + /// The ID of the metadata source. + /// + /// + /// Whether the metadata source is preferred. + /// + /// + /// If the metadata source is preferred, all other metadata sources for the same metadata map will be set to not preferred. + /// + public static void AddMetadataMapItem(long metadataMapId, HasheousClient.Models.MetadataSources sourceType, long sourceId, bool preferred) + { + Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); + string sql = ""; + Dictionary dbDict = new Dictionary() + { + { "@metadataMapId", metadataMapId }, + { "@sourceType", sourceType }, + { "@sourceId", sourceId }, + { "@preferred", preferred }, + { "@processedatimport", false } + }; + + if (preferred == true) + { + // set all other items to not preferred + sql = "UPDATE MetadataMapBridge SET Preferred = 0 WHERE ParentMapId = @metadataMapId;"; + db.ExecuteCMD(sql, dbDict); + } + + sql = "INSERT INTO MetadataMapBridge (ParentMapId, MetadataSourceType, MetadataSourceId, Preferred, ProcessedAtImport) VALUES (@metadataMapId, @sourceType, @sourceId, @preferred, @processedatimport);"; + db.ExecuteCMD(sql, dbDict); + } + + /// + /// Gets a metadata map from the database. + /// + /// + /// The ID of the platform to which the metadata map belongs. + /// + /// + /// The name of the metadata map. + /// + /// + /// The metadata map, or null if it does not exist. + /// + /// + /// This method will return the first metadata map found with the given platformId and name. + /// + public static MetadataMap? GetMetadataMap(long platformId, string name) + { + Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); + string sql = ""; + Dictionary dbDict = new Dictionary() + { + { "@platformId", platformId }, + { "@name", name } + }; + DataTable dt = new DataTable(); + + sql = "SELECT Id FROM MetadataMap WHERE PlatformId = @platformId AND SignatureGameName = @name;"; + dt = db.ExecuteCMD(sql, dbDict); + + if (dt.Rows.Count > 0) + { + return GetMetadataMap((long)dt.Rows[0]["Id"]); + } + + return null; + } + + /// + /// Gets a metadata map from the database. + /// + /// + /// The ID of the metadata map. + /// + /// + /// The metadata map, or null if it does not exist. + /// + /// + /// This method will return the metadata map with the given ID. + /// + public static MetadataMap? GetMetadataMap(long metadataMapId) + { + Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); + string sql = ""; + Dictionary dbDict = new Dictionary() + { + { "@metadataMapId", metadataMapId } + }; + DataTable dt = new DataTable(); + + sql = "SELECT * FROM MetadataMap WHERE Id = @metadataMapId;"; + dt = db.ExecuteCMD(sql, dbDict); + + if (dt.Rows.Count > 0) + { + MetadataMap metadataMap = new MetadataMap() + { + Id = (long)dt.Rows[0]["Id"], + PlatformId = (long)dt.Rows[0]["PlatformId"], + SignatureGameName = dt.Rows[0]["SignatureGameName"].ToString(), + MetadataMapItems = new List() + }; + + sql = "SELECT * FROM MetadataMapBridge WHERE ParentMapId = @metadataMapId;"; + dt = db.ExecuteCMD(sql, dbDict); + + foreach (DataRow dr in dt.Rows) + { + MetadataMap.MetadataMapItem metadataMapItem = new MetadataMap.MetadataMapItem() + { + SourceType = (HasheousClient.Models.MetadataSources)dr["MetadataSourceType"], + SourceId = (long)dr["MetadataSourceId"], + Preferred = (bool)dr["Preferred"] + }; + + metadataMap.MetadataMapItems.Add(metadataMapItem); + } + + return metadataMap; + } + + return null; + } + public void RefreshMetadata(bool forceRefresh = false) { Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); @@ -59,8 +250,102 @@ namespace gaseous_server.Classes try { + MetadataSources metadataSource = MetadataSources.IGDB; Logging.Log(Logging.LogType.Information, "Metadata Refresh", "(" + StatusCounter + "/" + dt.Rows.Count + "): Refreshing metadata for game " + dr["name"] + " (" + dr["id"] + ")"); - Metadata.Games.GetGame(Communications.MetadataSource, (long)dr["id"]); + HasheousClient.Models.Metadata.IGDB.Game game = Metadata.Games.GetGame(metadataSource, (long)dr["id"]); + + // get supporting metadata + if (game != null) + { + if (game.AgeRatings != null) + { + foreach (long ageRatingId in game.AgeRatings) + { + AgeRating ageRating = Metadata.AgeRatings.GetAgeRating(metadataSource, ageRatingId); + if (ageRating.ContentDescriptions != null) + { + foreach (long ageRatingContentDescriptionId in ageRating.ContentDescriptions) + { + Metadata.AgeRatingContentDescriptions.GetAgeRatingContentDescriptions(metadataSource, ageRatingContentDescriptionId); + } + } + } + } + if (game.AlternativeNames != null) + { + foreach (long alternateNameId in game.AlternativeNames) + { + Metadata.AlternativeNames.GetAlternativeNames(metadataSource, alternateNameId); + } + } + if (game.Artworks != null) + { + foreach (long artworkId in game.Artworks) + { + Metadata.Artworks.GetArtwork(metadataSource, artworkId); + } + } + if (game.Cover != null) + { + Metadata.Covers.GetCover(metadataSource, (long?)game.Cover); + } + if (game.GameModes != null) + { + foreach (long gameModeId in game.GameModes) + { + Metadata.GameModes.GetGame_Modes(metadataSource, gameModeId); + } + } + if (game.Genres != null) + { + foreach (long genreId in game.Genres) + { + Metadata.Genres.GetGenres(metadataSource, genreId); + } + } + if (game.Videos != null) + { + foreach (long gameVideoId in game.Videos) + { + Metadata.GamesVideos.GetGame_Videos(metadataSource, gameVideoId); + } + } + if (game.MultiplayerModes != null) + { + foreach (long multiplayerModeId in game.MultiplayerModes) + { + Metadata.MultiplayerModes.GetGame_MultiplayerModes(metadataSource, multiplayerModeId); + } + } + if (game.PlayerPerspectives != null) + { + foreach (long playerPerspectiveId in game.PlayerPerspectives) + { + Metadata.PlayerPerspectives.GetGame_PlayerPerspectives(metadataSource, playerPerspectiveId); + } + } + if (game.ReleaseDates != null) + { + foreach (long releaseDateId in game.ReleaseDates) + { + Metadata.ReleaseDates.GetReleaseDates(metadataSource, releaseDateId); + } + } + if (game.Screenshots != null) + { + foreach (long screenshotId in game.Screenshots) + { + Metadata.Screenshots.GetScreenshot(metadataSource, screenshotId); + } + } + if (game.Themes != null) + { + foreach (long themeId in game.Themes) + { + Metadata.Themes.GetGame_Themes(metadataSource, themeId); + } + } + } } catch (Exception ex) { diff --git a/gaseous-server/Classes/RomMediaGroup.cs b/gaseous-server/Classes/RomMediaGroup.cs index 7c9f3b0..5763442 100644 --- a/gaseous-server/Classes/RomMediaGroup.cs +++ b/gaseous-server/Classes/RomMediaGroup.cs @@ -296,7 +296,7 @@ namespace gaseous_server.Classes GameRomMediaGroupItem mediaGroupItem = GetMediaGroup(Id); if (mediaGroupItem.Status == GameRomMediaGroupItem.GroupBuildStatus.WaitingForBuild) { - Models.Game GameObject = Games.GetGame(Communications.MetadataSource, mediaGroupItem.GameId); + Models.Game GameObject = Games.GetGame(HasheousClient.Models.MetadataSources.IGDB, mediaGroupItem.GameId); Platform PlatformObject = Platforms.GetPlatform(mediaGroupItem.PlatformId); PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(mediaGroupItem.PlatformId); diff --git a/gaseous-server/Classes/Roms.cs b/gaseous-server/Classes/Roms.cs index 94b3494..0a193d5 100644 --- a/gaseous-server/Classes/Roms.cs +++ b/gaseous-server/Classes/Roms.cs @@ -113,7 +113,7 @@ namespace gaseous_server.Classes public static GameRomItem GetRom(long RomId) { Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); - string sql = "SELECT view_Games_Roms.*, Platform.`Name` AS platformname, Game.`Name` AS gamename FROM view_Games_Roms LEFT JOIN Platform ON view_Games_Roms.PlatformId = Platform.Id LEFT JOIN Game ON view_Games_Roms.GameId = Game.Id WHERE view_Games_Roms.Id = @id"; + string sql = "SELECT DISTINCT view_Games_Roms.*, Platform.`Name` AS platformname, view_GamesWithRoms.`Name` AS gamename FROM view_Games_Roms LEFT JOIN Platform ON view_Games_Roms.PlatformId = Platform.Id LEFT JOIN view_GamesWithRoms ON view_Games_Roms.GameId = view_GamesWithRoms.Id WHERE view_Games_Roms.Id = @id"; Dictionary dbDict = new Dictionary(); dbDict.Add("id", RomId); DataTable romDT = db.ExecuteCMD(sql, dbDict); @@ -133,7 +133,7 @@ namespace gaseous_server.Classes public static GameRomItem GetRom(string MD5) { Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); - string sql = "SELECT view_Games_Roms.*, Platform.`Name` AS platformname, Game.`Name` AS gamename FROM view_Games_Roms LEFT JOIN Platform ON view_Games_Roms.PlatformId = Platform.Id LEFT JOIN Game ON view_Games_Roms.GameId = Game.Id WHERE view_Games_Roms.MD5 = @id"; + string sql = "SELECT DISTINCT view_Games_Roms.*, Platform.`Name` AS platformname, view_GamesWithRoms.`Name` AS gamename FROM view_Games_Roms LEFT JOIN Platform ON view_Games_Roms.PlatformId = Platform.Id LEFT JOIN view_GamesWithRoms ON view_Games_Roms.GameId = view_GamesWithRoms.Id WHERE view_Games_Roms.MD5 = @id"; Dictionary dbDict = new Dictionary(); dbDict.Add("id", MD5); DataTable romDT = db.ExecuteCMD(sql, dbDict); @@ -156,7 +156,7 @@ namespace gaseous_server.Classes HasheousClient.Models.Metadata.IGDB.Platform platform = Classes.Metadata.Platforms.GetPlatform(PlatformId); // ensure metadata for gameid is present - Models.Game game = Classes.Metadata.Games.GetGame(Communications.MetadataSource, GameId); + Models.Game game = Classes.Metadata.Games.GetGame(HasheousClient.Models.MetadataSources.IGDB, GameId); Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); string sql = "UPDATE Games_Roms SET PlatformId=@platformid, GameId=@gameid WHERE Id = @id"; diff --git a/gaseous-server/Classes/UserProfile.cs b/gaseous-server/Classes/UserProfile.cs index bdc78c6..dd4acb0 100644 --- a/gaseous-server/Classes/UserProfile.cs +++ b/gaseous-server/Classes/UserProfile.cs @@ -61,7 +61,7 @@ namespace gaseous_server.Classes { NowPlaying = new Models.UserProfile.NowPlayingItem { - Game = Games.GetGame(Communications.MetadataSource, (long)nowPlayingData.Rows[0]["GameId"]), + Game = Games.GetGame(HasheousClient.Models.MetadataSources.IGDB, (long)nowPlayingData.Rows[0]["GameId"]), Platform = Platforms.GetPlatform((long)nowPlayingData.Rows[0]["PlatformId"]), Duration = Convert.ToInt64(nowPlayingData.Rows[0]["SessionLength"]) }; diff --git a/gaseous-server/Controllers/V1.0/GamesController.cs b/gaseous-server/Controllers/V1.0/GamesController.cs index 3f0a313..52a9b30 100644 --- a/gaseous-server/Controllers/V1.0/GamesController.cs +++ b/gaseous-server/Controllers/V1.0/GamesController.cs @@ -1562,7 +1562,7 @@ namespace gaseous_server.Controllers Common.hashObject hash = new Common.hashObject(romItem.Path); FileSignature fileSignature = new FileSignature(); gaseous_server.Models.Signatures_Games romSig = fileSignature.GetFileSignature(romItem.Library, hash, new FileInfo(romItem.Path), romItem.Path); - List searchResults = Classes.ImportGame.SearchForGame_GetAll(romSig.Game.Name, romSig.Flags.IGDBPlatformId); + List searchResults = Classes.ImportGame.SearchForGame_GetAll(romSig.Game.Name, romSig.Flags.PlatformId); return Ok(searchResults); } diff --git a/gaseous-server/Controllers/V1.0/RomsController.cs b/gaseous-server/Controllers/V1.0/RomsController.cs index d7da89b..52bbf73 100644 --- a/gaseous-server/Controllers/V1.0/RomsController.cs +++ b/gaseous-server/Controllers/V1.0/RomsController.cs @@ -77,9 +77,9 @@ namespace gaseous_server.Controllers if (RetVal["status"] == "imported") { gaseous_server.Models.Game? game = (gaseous_server.Models.Game)RetVal["game"]; - if (game.Id == null) + if (game == null || game.Id == null) { - RetVal["game"] = Games.GetGame(Communications.MetadataSource, 0); + RetVal["game"] = Games.GetGame(HasheousClient.Models.MetadataSources.IGDB, 0); } } break; diff --git a/gaseous-server/Controllers/V1.0/SearchController.cs b/gaseous-server/Controllers/V1.0/SearchController.cs index 4650591..dc8f418 100644 --- a/gaseous-server/Controllers/V1.0/SearchController.cs +++ b/gaseous-server/Controllers/V1.0/SearchController.cs @@ -64,77 +64,81 @@ namespace gaseous_server.Controllers private static async Task> _SearchForGame(long PlatformId, string SearchString) { - switch (Communications.MetadataSource) + switch (Config.MetadataConfiguration.DefaultMetadataSource) { - case HasheousClient.Models.MetadataModel.MetadataSources.IGDB: - string searchBody = ""; - string searchFields = "fields *; "; - searchBody += "search \"" + SearchString + "\";"; - searchBody += "where platforms = (" + PlatformId + ");"; - searchBody += "limit 100;"; - - List? searchCache = Communications.GetSearchCache>(searchFields, searchBody); - - if (searchCache == null) + case HasheousClient.Models.MetadataSources.IGDB: + if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false) { - // cache miss - // get Game metadata from data source - Communications comms = new Communications(); - var results = await comms.APIComm("Game", searchFields, searchBody); + string searchBody = ""; + string searchFields = "fields *; "; + searchBody += "search \"" + SearchString + "\";"; + searchBody += "where platforms = (" + PlatformId + ");"; + searchBody += "limit 100;"; - List games = new List(); - foreach (gaseous_server.Models.Game game in results.ToList()) + List? searchCache = Communications.GetSearchCache>(searchFields, searchBody); + + if (searchCache == null) { - Storage.CacheStatus cacheStatus = Storage.GetCacheStatus(Communications.MetadataSource, "Game", (long)game.Id); - switch (cacheStatus) + // cache miss + // get Game metadata from data source + Communications comms = new Communications(); + var results = await comms.APIComm("Game", searchFields, searchBody); + + List games = new List(); + foreach (gaseous_server.Models.Game game in results.ToList()) { - case Storage.CacheStatus.NotPresent: - Storage.NewCacheValue(Communications.MetadataSource, game, false); - break; + Storage.CacheStatus cacheStatus = Storage.GetCacheStatus(HasheousClient.Models.MetadataSources.IGDB, "Game", (long)game.Id); + switch (cacheStatus) + { + case Storage.CacheStatus.NotPresent: + Storage.NewCacheValue(HasheousClient.Models.MetadataSources.IGDB, game, false); + break; - case Storage.CacheStatus.Expired: - Storage.NewCacheValue(Communications.MetadataSource, game, true); - break; + case Storage.CacheStatus.Expired: + Storage.NewCacheValue(HasheousClient.Models.MetadataSources.IGDB, game, true); + break; + } + + games.Add(game); } - games.Add(game); + Communications.SetSearchCache>(searchFields, searchBody, games); + + return games; } + else + { + // get full version of results from database + // this is a hacky workaround due to the readonly nature of IGDB.Model.Game IdentityOrValue fields + List gamesToReturn = new List(); + foreach (gaseous_server.Models.Game game in searchCache) + { + gaseous_server.Models.Game? tempGame = Games.GetGame(Communications.MetadataSource, (long)game.Id); + if (tempGame != null) + { + gamesToReturn.Add(tempGame); + } + } - Communications.SetSearchCache>(searchFields, searchBody, games); - - return games; + return gamesToReturn; + } } else { - // get full version of results from database - // this is a hacky workaround due to the readonly nature of IGDB.Model.Game IdentityOrValue fields - List gamesToReturn = new List(); - foreach (gaseous_server.Models.Game game in searchCache) + HasheousClient.Hasheous hasheous = new HasheousClient.Hasheous(); + Communications.ConfigureHasheousClient(ref hasheous); + List hSearch = hasheous.GetMetadataProxy_SearchGame(HasheousClient.Hasheous.MetadataProvider.IGDB, PlatformId.ToString(), SearchString).ToList(); + + List hGamesToReturn = new List(); + foreach (gaseous_server.Models.Game game in hSearch) { - gaseous_server.Models.Game? tempGame = Games.GetGame(Communications.MetadataSource, (long)game.Id); - if (tempGame != null) - { - gamesToReturn.Add(tempGame); - } + hGamesToReturn.Add(game); } - return gamesToReturn; + return hGamesToReturn; } - case HasheousClient.Models.MetadataModel.MetadataSources.Hasheous: - HasheousClient.Hasheous hasheous = new HasheousClient.Hasheous(); - Communications.ConfigureHasheousClient(ref hasheous); - List hSearch = hasheous.GetMetadataProxy_SearchGame(HasheousClient.Hasheous.MetadataProvider.IGDB, PlatformId.ToString(), SearchString).ToList(); - - List hGamesToReturn = new List(); - foreach (gaseous_server.Models.Game game in hSearch) - { - hGamesToReturn.Add(game); - } - - return hGamesToReturn; - default: return new List(); } diff --git a/gaseous-server/Controllers/V1.0/SystemController.cs b/gaseous-server/Controllers/V1.0/SystemController.cs index 80b2393..fef5adb 100644 --- a/gaseous-server/Controllers/V1.0/SystemController.cs +++ b/gaseous-server/Controllers/V1.0/SystemController.cs @@ -314,7 +314,8 @@ namespace gaseous_server.Controllers }, MetadataSource = new SystemSettingsModel.MetadataSourceItem() { - Source = Config.MetadataConfiguration.MetadataSource, + Source = Config.MetadataConfiguration.DefaultMetadataSource, + UseHasheousProxy = Config.MetadataConfiguration.MetadataUseHasheousProxy, IGDBClientId = Config.IGDB.ClientId, IGDBClientSecret = Config.IGDB.Secret } @@ -340,7 +341,8 @@ namespace gaseous_server.Controllers Config.MetadataConfiguration.HasheousHost = model.SignatureSource.HasheousHost; Config.MetadataConfiguration.HasheousAPIKey = model.SignatureSource.HasheousAPIKey; Config.MetadataConfiguration.HasheousSubmitFixes = model.SignatureSource.HasheousSubmitFixes; - Config.MetadataConfiguration.MetadataSource = model.MetadataSource.Source; + Config.MetadataConfiguration.DefaultMetadataSource = model.MetadataSource.Source; + Config.MetadataConfiguration.MetadataUseHasheousProxy = model.MetadataSource.UseHasheousProxy; Config.IGDB.ClientId = model.MetadataSource.IGDBClientId; Config.IGDB.Secret = model.MetadataSource.IGDBClientSecret; Config.UpdateConfig(); @@ -797,7 +799,8 @@ namespace gaseous_server.Controllers public class MetadataSourceItem { - public HasheousClient.Models.MetadataModel.MetadataSources Source { get; set; } + public HasheousClient.Models.MetadataSources Source { get; set; } + public bool UseHasheousProxy { get; set; } public string IGDBClientId { get; set; } public string IGDBClientSecret { get; set; } } diff --git a/gaseous-server/Controllers/V1.1/GamesController.cs b/gaseous-server/Controllers/V1.1/GamesController.cs index 9f7edf5..1ca8244 100644 --- a/gaseous-server/Controllers/V1.1/GamesController.cs +++ b/gaseous-server/Controllers/V1.1/GamesController.cs @@ -483,6 +483,8 @@ namespace gaseous_server.Controllers.v1_1 SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')); SELECT DISTINCT Game.Id, + Game.MetadataMapId, + Game.GameIdType, Game.`Name`, Game.NameThe, Game.Slug, @@ -507,15 +509,11 @@ SELECT DISTINCT FROM (SELECT DISTINCT Game.*, - CASE - WHEN Game.`Name` LIKE 'The %' THEN CONCAT(TRIM(SUBSTR(Game.`Name` FROM 4)), ', The') - ELSE Game.`Name` - END AS NameThe, view_Games_Roms.PlatformId, AgeGroup.AgeGroupId, COUNT(view_Games_Roms.Id) AS RomCount FROM - Game + view_GamesWithRoms AS Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN view_Games_Roms ON Game.Id = view_Games_Roms.GameId" + platformWhereClause + @" LEFT JOIN AlternativeName ON Game.Id = AlternativeName.Game " + nameWhereClause + @" @@ -553,7 +551,6 @@ FROM Favourites ON Game.Id = Favourites.GameId AND Favourites.UserId = @userid " + whereClause + " " + havingClause + " " + orderByClause; List RetVal = new List(); - Console.WriteLine(sql); DataTable dbResponse = db.ExecuteCMD(sql, whereParams, new Database.DatabaseMemoryCacheOptions(CacheEnabled: true, ExpirationSeconds: 60)); // get count @@ -572,6 +569,9 @@ FROM } Models.Game retGame = Storage.BuildCacheObject(new Models.Game(), dbResponse.Rows[i]); + retGame.MetadataMapId = (long)dbResponse.Rows[i]["MetadataMapId"]; + retGame.MetadataSource = (HasheousClient.Models.MetadataSources)dbResponse.Rows[i]["GameIdType"]; + Games.MinimalGameItem retMinGame = new Games.MinimalGameItem(retGame); retMinGame.Index = i; if (dbResponse.Rows[i]["RomSaveCount"] != DBNull.Value || dbResponse.Rows[i]["MediaGroupSaveCount"] != DBNull.Value) diff --git a/gaseous-server/Models/GaseousGame.cs b/gaseous-server/Models/GaseousGame.cs index 0a4ff99..445c016 100644 --- a/gaseous-server/Models/GaseousGame.cs +++ b/gaseous-server/Models/GaseousGame.cs @@ -14,7 +14,10 @@ namespace gaseous_server.Models public bool HasSavedGame { get; set; } = false; [NoDatabase] - public HasheousClient.Models.MetadataModel.MetadataSources MetadataSource { get; set; } + public long MetadataMapId { get; set; } + + [NoDatabase] + public HasheousClient.Models.MetadataSources MetadataSource { get; set; } } internal class NoDatabaseAttribute : Attribute diff --git a/gaseous-server/Models/MetadataMap.cs b/gaseous-server/Models/MetadataMap.cs new file mode 100644 index 0000000..b4ea862 --- /dev/null +++ b/gaseous-server/Models/MetadataMap.cs @@ -0,0 +1,19 @@ +using HasheousClient.Models; + +namespace gaseous_server.Models +{ + public class MetadataMap + { + public long Id { get; set; } + public long PlatformId { get; set; } + public string SignatureGameName { get; set; } + public List MetadataMapItems { get; set; } + + public class MetadataMapItem + { + public HasheousClient.Models.MetadataSources SourceType { get; set; } + public long SourceId { get; set; } + public bool Preferred { get; set; } + } + } +} \ No newline at end of file diff --git a/gaseous-server/Models/PlatformMapping.cs b/gaseous-server/Models/PlatformMapping.cs index 9ba579a..422610a 100644 --- a/gaseous-server/Models/PlatformMapping.cs +++ b/gaseous-server/Models/PlatformMapping.cs @@ -446,8 +446,8 @@ namespace gaseous_server.Models { if (Signature.Game != null) { Signature.Game.System = PlatformMapping.IGDBName; } } - Signature.Flags.IGDBPlatformId = PlatformMapping.IGDBId; - Signature.Flags.IGDBPlatformName = PlatformMapping.IGDBName; + Signature.Flags.PlatformId = PlatformMapping.IGDBId; + Signature.Flags.PlatformName = PlatformMapping.IGDBName; PlatformFound = true; @@ -470,8 +470,8 @@ namespace gaseous_server.Models { if (Signature.Game != null) { Signature.Game.System = PlatformMapping.IGDBName; } } - Signature.Flags.IGDBPlatformId = PlatformMapping.IGDBId; - Signature.Flags.IGDBPlatformName = PlatformMapping.IGDBName; + Signature.Flags.PlatformId = PlatformMapping.IGDBId; + Signature.Flags.PlatformName = PlatformMapping.IGDBName; PlatformFound = true; diff --git a/gaseous-server/Models/Signatures_Games.cs b/gaseous-server/Models/Signatures_Games.cs index cc389cc..157e78f 100644 --- a/gaseous-server/Models/Signatures_Games.cs +++ b/gaseous-server/Models/Signatures_Games.cs @@ -1,14 +1,17 @@ using System; using System.Text.Json.Serialization; +using gaseous_server.Classes; +using gaseous_server.Classes.Metadata; using gaseous_signature_parser.models.RomSignatureObject; +using HasheousClient.Models; namespace gaseous_server.Models { - public class Signatures_Games : HasheousClient.Models.SignatureModel - { - public Signatures_Games() - { - } + public class Signatures_Games : HasheousClient.Models.SignatureModel + { + public Signatures_Games() + { + } [JsonIgnore] public int Score @@ -34,13 +37,97 @@ namespace gaseous_server.Models public GameItem Game = new GameItem(); public RomItem Rom = new RomItem(); - public SignatureFlags Flags = new SignatureFlags(); + public SignatureFlags Flags + { + get + { + SignatureFlags _flags = new SignatureFlags(); + + foreach (SourceValues.SourceValueItem source in MetadataSources.Platforms) + { + if (source.Source == Config.MetadataConfiguration.DefaultMetadataSource) + { + _flags.PlatformId = source.Id; + _flags.PlatformName = source.Name; + _flags.PlatformMetadataSource = source.Source; + break; + } + } + + foreach (SourceValues.SourceValueItem source in MetadataSources.Games) + { + if (source.Source == Config.MetadataConfiguration.DefaultMetadataSource) + { + _flags.GameId = source.Id; + _flags.GameName = source.Name; + _flags.GameMetadataSource = source.Source; + break; + } + } + + return _flags; + } + } + + public SourceValues MetadataSources = new SourceValues(); + + public class SourceValues + { + public List Platforms = new List(); + public List Games = new List(); + + public class SourceValueItem + { + public long Id { get; set; } + public string Name { get; set; } + public HasheousClient.Models.MetadataSources Source { get; set; } + } + + public void AddPlatform(long Id, string Name, HasheousClient.Models.MetadataSources Source) + { + // check that the platform doesn't already exist + foreach (SourceValueItem item in Platforms) + { + if (item.Id == Id) + { + return; + } + } + + SourceValueItem newItem = new SourceValueItem(); + newItem.Id = Id; + newItem.Name = Name; + newItem.Source = Source; + Platforms.Add(newItem); + } + + public void AddGame(long Id, string Name, HasheousClient.Models.MetadataSources Source) + { + // check that the game doesn't already exist + foreach (SourceValueItem item in Games) + { + if (item.Id == Id) + { + return; + } + } + + SourceValueItem newItem = new SourceValueItem(); + newItem.Id = Id; + newItem.Name = Name; + newItem.Source = Source; + Games.Add(newItem); + } + } public class SignatureFlags { - public long IGDBPlatformId { get; set; } - public string IGDBPlatformName { get; set; } - public long IGDBGameId { get; set; } + public long PlatformId { get; set; } + public string PlatformName { get; set; } + public long GameId { get; set; } + public string GameName { get; set; } + public HasheousClient.Models.MetadataSources PlatformMetadataSource { get; set; } + public HasheousClient.Models.MetadataSources GameMetadataSource { get; set; } } public class GameItem : HasheousClient.Models.SignatureModel.GameItem @@ -211,7 +298,8 @@ namespace gaseous_server.Models break; } } - else { + else + { switch (inType.ToLower()) { case "disk": diff --git a/gaseous-server/Program.cs b/gaseous-server/Program.cs index 168d48b..fc32f86 100644 --- a/gaseous-server/Program.cs +++ b/gaseous-server/Program.cs @@ -52,7 +52,7 @@ Config.UpdateConfig(); GameLibrary.UpdateDefaultLibraryPath(); // set api metadata source from config -Communications.MetadataSource = Config.MetadataConfiguration.MetadataSource; +Communications.MetadataSource = Config.MetadataConfiguration.DefaultMetadataSource; // set up hasheous client HasheousClient.WebApp.HttpHelper.BaseUri = Config.MetadataConfiguration.HasheousHost; diff --git a/gaseous-server/Support/Database/MySQL/gaseous-1024.sql b/gaseous-server/Support/Database/MySQL/gaseous-1024.sql index 0e75bd8..69bf54f 100644 --- a/gaseous-server/Support/Database/MySQL/gaseous-1024.sql +++ b/gaseous-server/Support/Database/MySQL/gaseous-1024.sql @@ -115,13 +115,16 @@ CREATE INDEX idx_favourites_userid_gameid ON Favourites (UserId, GameId); CREATE TABLE `MetadataMap` ( `Id` bigint(20) NOT NULL AUTO_INCREMENT, `PlatformId` bigint(20) NOT NULL, - PRIMARY KEY (`id`) + `SignatureGameName` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + INDEX `idx_gamename` ( + `SignatureGameName`, + `PlatformId` + ) ); CREATE TABLE `MetadataMapBridge` ( `ParentMapId` bigint(20) NOT NULL, - `SignatureGameName` varchar(255) NOT NULL, - `SignaturePlatformId` bigint(20) NOT NULL, `MetadataSourceType` int(11) NOT NULL DEFAULT 0, `MetadataSourceId` bigint(20) NOT NULL, `Preferred` BOOLEAN NOT NULL DEFAULT 0, @@ -131,14 +134,20 @@ CREATE TABLE `MetadataMapBridge` ( `MetadataSourceType`, `MetadataSourceId` ), - INDEX `idx_gamename` ( - `SignatureGameName`, - `SignaturePlatformId` - ) + CONSTRAINT `MetadataMapBridge_MetadataMap` FOREIGN KEY (`ParentMapId`) REFERENCES `MetadataMap` (`Id`) ON DELETE CASCADE ); +CREATE OR REPLACE VIEW `view_MetadataMap` AS +SELECT `MetadataMap`.*, `MetadataMapBridge`.`MetadataSourceType`, `MetadataMapBridge`.`MetadataSourceId` +FROM + `MetadataMap` + LEFT JOIN `MetadataMapBridge` ON ( + `MetadataMap`.`Id` = `MetadataMapBridge`.`ParentMapId` + AND `MetadataMapBridge`.`Preferred` = 1 + ); + ALTER TABLE `Games_Roms` -ADD CONSTRAINT metadataMapId FOREIGN KEY (`MetadataMapId`) REFERENCES `MetadataMapBridge` (`ParentMapId`) ON DELETE CASCADE; +ADD CONSTRAINT metadataMapId FOREIGN KEY (`MetadataMapId`) REFERENCES `MetadataMap` (`Id`) ON DELETE CASCADE; ALTER TABLE `Games_Roms` ADD COLUMN `MetadataMapId` BIGINT NOT NULL DEFAULT 0; @@ -199,6 +208,7 @@ DROP PRIMARY KEY, ADD PRIMARY KEY (`Id`, `SourceId`); ALTER TABLE `Game` +CHANGE `Id` `Id` bigint(20) NOT NULL AUTO_INCREMENT, ADD COLUMN `SourceId` INT NOT NULL DEFAULT 1 AFTER `Id`, DROP INDEX IF EXISTS `Id_UNIQUE`, DROP INDEX IF EXISTS `PRIMARY`, @@ -263,4 +273,142 @@ ADD PRIMARY KEY (`Id`, `SourceId`); ALTER TABLE `Theme` ADD COLUMN `SourceId` INT NOT NULL DEFAULT 1 AFTER `Id`, DROP PRIMARY KEY, -ADD PRIMARY KEY (`Id`, `SourceId`); \ No newline at end of file +ADD PRIMARY KEY (`Id`, `SourceId`); + +ALTER TABLE `ReleaseDate` +CHANGE `m` `Month` int(11) DEFAULT NULL, +CHANGE `y` `Year` int(11) DEFAULT NULL; + +CREATE OR REPLACE VIEW `view_Games_Roms` AS +SELECT + `Games_Roms`.`Id` AS `Id`, + `Games_Roms`.`PlatformId` AS `PlatformId`, + `view_MetadataMap`.`Id` AS `MetadataMapId`, + `view_MetadataMap`.`MetadataSourceType` AS `GameIdType`, + `view_MetadataMap`.`MetadataSourceId` AS `GameId`, + `Games_Roms`.`Name` AS `Name`, + `Games_Roms`.`Size` AS `Size`, + `Games_Roms`.`CRC` AS `CRC`, + `Games_Roms`.`MD5` AS `MD5`, + `Games_Roms`.`SHA1` AS `SHA1`, + `Games_Roms`.`DevelopmentStatus` AS `DevelopmentStatus`, + `Games_Roms`.`Flags` AS `Flags`, + `Games_Roms`.`Attributes` AS `Attributes`, + `Games_Roms`.`RomType` AS `RomType`, + `Games_Roms`.`RomTypeMedia` AS `RomTypeMedia`, + `Games_Roms`.`MediaLabel` AS `MediaLabel`, + `Games_Roms`.`RelativePath` AS `RelativePath`, + `Games_Roms`.`MetadataSource` AS `MetadataSource`, + `Games_Roms`.`MetadataGameName` AS `MetadataGameName`, + `Games_Roms`.`MetadataVersion` AS `MetadataVersion`, + `Games_Roms`.`LibraryId` AS `LibraryId`, + `Games_Roms`.`LastMatchAttemptDate` AS `LastMatchAttemptDate`, + `Games_Roms`.`RomDataVersion` AS `RomDataVersion`, + CONCAT( + `GameLibraries`.`Path`, + '/', + `Games_Roms`.`RelativePath` + ) AS `Path`, + `GameLibraries`.`Name` AS `LibraryName` +FROM ( + `Games_Roms` + JOIN `GameLibraries` ON ( + `Games_Roms`.`LibraryId` = `GameLibraries`.`Id` + ) + LEFT JOIN `view_MetadataMap` ON ( + `Games_Roms`.`MetadataMapId` = `view_MetadataMap`.`Id` + ) + ); + +CREATE OR REPLACE VIEW `view_GamesWithRoms` AS +SELECT DISTINCT + `Games_Roms`.`GameId` AS `ROMGameId`, + `view_MetadataMap`.`Id` AS `MetadataMapId`, + `view_MetadataMap`.`MetadataSourceType` AS `GameIdType`, + CASE + WHEN `Game`.`Id` IS NULL THEN 0 + ELSE `Game`.`Id` + END AS `Id`, + `Game`.`AgeRatings` AS `AgeRatings`, + `Game`.`AggregatedRating` AS `AggregatedRating`, + `Game`.`AggregatedRatingCount` AS `AggregatedRatingCount`, + `Game`.`AlternativeNames` AS `AlternativeNames`, + `Game`.`Artworks` AS `Artworks`, + `Game`.`Bundles` AS `Bundles`, + `Game`.`Category` AS `Category`, + `Game`.`Checksum` AS `Checksum`, + `Game`.`Collection` AS `Collection`, + `Game`.`Cover` AS `Cover`, + `Game`.`CreatedAt` AS `CreatedAt`, + `Game`.`Dlcs` AS `Dlcs`, + `Game`.`Expansions` AS `Expansions`, + `Game`.`ExternalGames` AS `ExternalGames`, + `Game`.`FirstReleaseDate` AS `FirstReleaseDate`, + `Game`.`Follows` AS `Follows`, + `Game`.`Franchise` AS `Franchise`, + `Game`.`Franchises` AS `Franchises`, + `Game`.`GameEngines` AS `GameEngines`, + `Game`.`GameModes` AS `GameModes`, + `Game`.`Genres` AS `Genres`, + `Game`.`Hypes` AS `Hypes`, + `Game`.`InvolvedCompanies` AS `InvolvedCompanies`, + `Game`.`Keywords` AS `Keywords`, + `Game`.`MultiplayerModes` AS `MultiplayerModes`, + CASE + WHEN `Game`.`Name` IS NULL THEN `view_MetadataMap`.`SignatureGameName` + ELSE `Game`.`Name` + END AS `Name`, + CASE + WHEN `Game`.`Name` IS NULL THEN CASE + WHEN `view_MetadataMap`.`SignatureGameName` LIKE 'The %' THEN CONCAT( + TRIM( + SUBSTR( + `view_MetadataMap`.`SignatureGameName`, + 4 + ) + ), + ', The' + ) + ELSE `view_MetadataMap`.`SignatureGameName` + END + WHEN `Game`.`Name` LIKE 'The %' THEN CONCAT( + TRIM(SUBSTR(`Game`.`Name`, 4)), + ', The' + ) + ELSE `Game`.`Name` + END AS `NameThe`, + `Game`.`ParentGame` AS `ParentGame`, + `Game`.`Platforms` AS `Platforms`, + `Game`.`PlayerPerspectives` AS `PlayerPerspectives`, + `Game`.`Rating` AS `Rating`, + `Game`.`RatingCount` AS `RatingCount`, + `Game`.`ReleaseDates` AS `ReleaseDates`, + `Game`.`Screenshots` AS `Screenshots`, + `Game`.`SimilarGames` AS `SimilarGames`, + `Game`.`Slug` AS `Slug`, + `Game`.`StandaloneExpansions` AS `StandaloneExpansions`, + `Game`.`Status` AS `Status`, + `Game`.`StoryLine` AS `StoryLine`, + `Game`.`Summary` AS `Summary`, + `Game`.`Tags` AS `Tags`, + `Game`.`Themes` AS `Themes`, + `Game`.`TotalRating` AS `TotalRating`, + `Game`.`TotalRatingCount` AS `TotalRatingCount`, + `Game`.`UpdatedAt` AS `UpdatedAt`, + `Game`.`Url` AS `Url`, + `Game`.`VersionParent` AS `VersionParent`, + `Game`.`VersionTitle` AS `VersionTitle`, + `Game`.`Videos` AS `Videos`, + `Game`.`Websites` AS `Websites`, + `Game`.`dateAdded` AS `dateAdded`, + `Game`.`lastUpdated` AS `lastUpdated` +FROM ( + `Games_Roms` + JOIN `view_MetadataMap` ON ( + `view_MetadataMap`.`Id` = `Games_Roms`.`MetadataMapId` + ) + LEFT JOIN `Game` ON ( + `Game`.`SourceId` = `view_MetadataMap`.`MetadataSourceType` + AND `Game`.`Id` = `view_MetadataMap`.`MetadataSourceId` + ) + ); \ No newline at end of file diff --git a/gaseous-server/gaseous-server.csproj b/gaseous-server/gaseous-server.csproj index 99eef6e..25e5b06 100644 --- a/gaseous-server/gaseous-server.csproj +++ b/gaseous-server/gaseous-server.csproj @@ -18,9 +18,9 @@ - + - + diff --git a/gaseous-server/wwwroot/pages/game.js b/gaseous-server/wwwroot/pages/game.js index 08e4110..9d92ab3 100644 --- a/gaseous-server/wwwroot/pages/game.js +++ b/gaseous-server/wwwroot/pages/game.js @@ -13,6 +13,7 @@ function SetupPage() { document.head.appendChild(mappingScript); ajaxCall('/api/v1.1/Games/' + gameId, 'GET', function (result) { + console.log(result); // populate games page gameData = result; @@ -21,19 +22,19 @@ function SetupPage() { gameTitleLabel.innerHTML = result.name; // get critic rating - if (gameData.totalRating) { + if (gameData.total_rating) { var criticscoreval = document.getElementById('gametitle_criticrating_value'); - criticscoreval.innerHTML = Math.floor(gameData.totalRating) + '%'; + criticscoreval.innerHTML = Math.floor(gameData.total_rating) + '%'; - if (gameData.totalRatingCount) { + if (gameData.total_rating_count) { var criticscorelabel = document.getElementById('gametitle_criticrating_label'); - criticscorelabel.innerHTML = ' User Rating
' + "based on " + gameData.totalRatingCount + " votes
" + criticscorelabel.innerHTML = ' User Rating
' + "based on " + gameData.total_rating_count + " votes
" } } // get alt name var gameTitleAltLabel = document.getElementById('gametitle_alts'); - if (result.alternativeNames) { + if (result.alternative_names) { ajaxCall('/api/v1.1/Games/' + gameId + '/alternativename', 'GET', function (result) { var altNames = ''; for (var i = 0; i < result.length; i++) { @@ -103,7 +104,7 @@ function SetupPage() { var gamePublisherContent = document.getElementById('gamesummary_publishers_content'); var gameDeveloperLoaded = false; var gamePublisherLoaded = false; - if (result.involvedCompanies) { + if (result.involved_companies) { ajaxCall('/api/v1.1/Games/' + gameId + '/companies', 'GET', function (result) { var lstDevelopers = []; var lstPublishers = []; @@ -199,9 +200,9 @@ function SetupPage() { // load release date var gameSummaryRelease = document.getElementById('gamesummary_firstrelease'); var gameSummaryReleaseContent = document.getElementById('gamesummary_firstrelease_content'); - if (result.firstReleaseDate) { + if (result.first_release_date) { var firstRelease = document.createElement('span'); - firstRelease.innerHTML = moment(result.firstReleaseDate).format('LL') + ' (' + moment(result.firstReleaseDate).fromNow() + ')'; + firstRelease.innerHTML = moment(result.first_release_date).format('LL') + ' (' + moment(result.first_release_date).fromNow() + ')'; gameSummaryReleaseContent.appendChild(firstRelease); } else { gameSummaryRelease.setAttribute('style', 'display: none;'); @@ -210,7 +211,7 @@ function SetupPage() { // load ratings let gameSummaryRatings = document.getElementById('gamesummary_ratings'); let gameSummaryRatingsContent = document.getElementById('gamesummary_ratings_content'); - if (result.ageRatings) { + if (result.age_ratings) { ajaxCall('/api/v1.1/Games/' + gameId + '/agerating', 'GET', function (result) { let classTable = document.createElement('table'); @@ -305,7 +306,7 @@ function SetupPage() { var gameScreenshots_Gallery = document.getElementById('gamescreenshots_gallery_panel'); var imageIndex = 0; if (result.videos) { - imageIndex = result.videos.ids.length; + imageIndex = result.videos.length; } if (result.screenshots) { ajaxCall('/api/v1.1/Games/' + gameId + '/screenshots', 'GET', function (screenshotsItem) { @@ -335,10 +336,10 @@ function SetupPage() { var vScreenshotItem = document.createElement('li'); vScreenshotItem.id = 'gamescreenshots_gallery_' + i; vScreenshotItem.setAttribute('name', 'gamescreenshots_gallery_item'); - vScreenshotItem.setAttribute('style', 'background-image: url("https://i.ytimg.com/vi/' + result[i].videoId + '/hqdefault.jpg"); background-position: center; background-repeat: no-repeat; background-size: contain;)'); + vScreenshotItem.setAttribute('style', 'background-image: url("https://i.ytimg.com/vi/' + result[i].video_id + '/hqdefault.jpg"); background-position: center; background-repeat: no-repeat; background-size: contain;)'); vScreenshotItem.setAttribute('imageid', i); vScreenshotItem.setAttribute('imagetype', 1); - vScreenshotItem.setAttribute('imageref', result[i].videoId); + vScreenshotItem.setAttribute('imageref', result[i].video_id); vScreenshotItem.className = 'gamescreenshots_gallery_item'; vScreenshotItem.setAttribute('onclick', 'selectScreenshot(' + i + ');'); @@ -1448,7 +1449,7 @@ class RomManagement { id: data[i].id, text: data[i].name, cover: data[i].cover, - releaseDate: data[i].firstReleaseDate + releaseDate: data[i].first_release_date }); } @@ -1466,8 +1467,8 @@ function loadArtwork(game, cover) { // default background should be the artworks if (game.artworks) { - for (let i = 0; i < game.artworks.ids.length; i++) { - URLList.push("/api/v1.1/Games/" + gameId + "/artwork/" + game.artworks.ids[i] + "/image/original/" + game.artworks.ids[i] + ".jpg"); + for (let i = 0; i < game.artworks.length; i++) { + URLList.push("/api/v1.1/Games/" + gameId + "/artwork/" + game.artworks[i] + "/image/original/" + game.artworks[i] + ".jpg"); } } else if (game.cover) { // backup background is the cover artwork diff --git a/gaseous-server/wwwroot/scripts/gamesformating.js b/gaseous-server/wwwroot/scripts/gamesformating.js index e1363f5..60f5429 100644 --- a/gaseous-server/wwwroot/scripts/gamesformating.js +++ b/gaseous-server/wwwroot/scripts/gamesformating.js @@ -60,6 +60,7 @@ var pageReloadInterval; var firstLoad = true; function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScrollTop) { + console.log(result); // set page mode buttons let pageViewButton = document.getElementById('games_library_button_pagedview'); let infiniteViewButton = document.getElementById('games_library_button_infiniteview'); @@ -434,7 +435,7 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification, } // gameImage.src = '/images/unknowngame.png'; if (gameObject.cover) { - gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameObject.id + '/cover/' + gameObject.cover.id + '/image/cover_big/' + gameObject.cover.id + '.jpg'); + gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameObject.id + '/cover/' + gameObject.cover + '/image/cover_big/' + gameObject.cover + '.jpg'); } else { gameImage.classList.add(...classes['game_tile_image unknown']); gameImage.setAttribute('data-src', '/images/unknowngame.png');