using System.Data; namespace gaseous_server.Classes.Metadata { public class Metadata { #region Exception Handling public class InvalidMetadataId : Exception { public InvalidMetadataId(long Id) : base("Invalid Metadata id: " + Id + " from source: " + HasheousClient.Models.MetadataSources.IGDB + " (default)") { } 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: " + HasheousClient.Models.MetadataSources.IGDB + " (default)") { } public InvalidMetadataId(HasheousClient.Models.MetadataSources SourceType, string Id) : base("Invalid Metadata id: " + Id + " from source: " + SourceType) { } } #endregion #region Get Metadata /// /// Get metadata from the default source /// /// /// The type of metadata to get /// /// /// The id of the metadata to get /// /// /// The metadata object /// /// /// Thrown when the id is invalid /// public static T? GetMetadata(long Id, Boolean ForceRefresh = false) where T : class { if (Id < 0) { throw new InvalidMetadataId(Id); } return _GetMetadata(HasheousClient.Models.MetadataSources.IGDB, Id, ForceRefresh); } /// /// Get metadata from the specified source /// /// /// The type of metadata to get /// /// /// The source of the metadata /// /// /// The id of the metadata to get /// /// /// The metadata object /// /// /// Thrown when the id is invalid /// public static T? GetMetadata(HasheousClient.Models.MetadataSources SourceType, long Id, Boolean ForceRefresh = false) where T : class { if (Id < 0) { throw new InvalidMetadataId(SourceType, Id); } return _GetMetadata(SourceType, Id, ForceRefresh); } 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.MetadataSources SourceType, object Id, Boolean ForceRefresh) where T : class { // get T type as string string type = typeof(T).Name; // get type of Id as string IdType idType = Id.GetType() == typeof(long) ? IdType.Long : IdType.String; // check cached metadata status // if metadata is not cached or expired, get it from the source. Otherwise, return the cached metadata Storage.CacheStatus? cacheStatus; if (idType == IdType.Long) { cacheStatus = Storage.GetCacheStatus(SourceType, type, (long)Id); } else { cacheStatus = Storage.GetCacheStatus(SourceType, type, (string)Id); } // if ForceRefresh is true, set cache status to expired if it is current if (ForceRefresh == true) { if (cacheStatus == Storage.CacheStatus.Current) { cacheStatus = Storage.CacheStatus.Expired; } } // if the source is "none", cache status should be "current" or "not present" if (SourceType == HasheousClient.Models.MetadataSources.None) { if (cacheStatus == Storage.CacheStatus.Expired) { cacheStatus = Storage.CacheStatus.Current; } } T? metadata = (T)Activator.CreateInstance(typeof(T)); switch (cacheStatus) { case Storage.CacheStatus.Current: if (idType == IdType.Long) { metadata = Storage.GetCacheValue(SourceType, metadata, "Id", (long)Id); } else { metadata = Storage.GetCacheValue(SourceType, metadata, "Slug", (string)Id); } break; case Storage.CacheStatus.Expired: if (idType == IdType.Long) { metadata = GetMetadataFromServer(SourceType, (long)Id).Result; } else { metadata = GetMetadataFromServer(SourceType, (string)Id).Result; } Storage.NewCacheValue(SourceType, metadata, true); break; case Storage.CacheStatus.NotPresent: if (idType == IdType.Long) { metadata = GetMetadataFromServer(SourceType, (long)Id).Result; } else { metadata = GetMetadataFromServer(SourceType, (string)Id).Result; } Storage.NewCacheValue(SourceType, metadata, false); break; } return metadata; } private enum IdType { Long, String } private static async Task GetMetadataFromServer(HasheousClient.Models.MetadataSources SourceType, long Id) where T : class { // get T type as string string type = typeof(T).Name; if (SourceType == HasheousClient.Models.MetadataSources.None) { // generate a dummy object var returnObject = (T)Activator.CreateInstance(typeof(T)); returnObject.GetType().GetProperty("Id").SetValue(returnObject, Id); // if returnObject has a property called "name", query the metadatamap view for the name if (returnObject.GetType().GetProperty("Name") != null) { Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); string sql = "SELECT SignatureGameName FROM view_MetadataMap WHERE `Id` = @id;"; DataTable dataTable = db.ExecuteCMD(sql, new Dictionary { { "@id", Id } }); if (dataTable.Rows.Count > 0) { returnObject.GetType().GetProperty("Name").SetValue(returnObject, dataTable.Rows[0]["SignatureGameName"].ToString()); } } return returnObject; } else { // get metadata from the server Communications comms = new Communications(); var results = await comms.APIComm(SourceType, (Communications.MetadataEndpoint)Enum.Parse(typeof(Communications.MetadataEndpoint), type, true), Id); // check for errors if (results == null) { throw new InvalidMetadataId(SourceType, Id); } return results.FirstOrDefault(); } } private static async Task GetMetadataFromServer(HasheousClient.Models.MetadataSources SourceType, string Id) where T : class { // get T type as string string type = typeof(T).Name; if (SourceType == HasheousClient.Models.MetadataSources.None) { // generate a dummy object return (T)Activator.CreateInstance(typeof(T)); } else { // get metadata from the server Communications comms = new Communications(); var results = await comms.APIComm(SourceType, (Communications.MetadataEndpoint)Enum.Parse(typeof(Communications.MetadataEndpoint), type, true), Id); // check for errors if (results == null) { throw new InvalidMetadataId(SourceType, Id); } return results.FirstOrDefault(); } } #endregion } }