Implement API rate limit handling support (#227)

* Merged all IGDB API communications into one class

* Added code to handle IGDB's rate limiter

* Revised IGDB rate limit avoidance and recovery times
This commit is contained in:
Michael Green
2023-12-12 12:00:24 +11:00
committed by GitHub
parent 7b241ee13e
commit 32051493a8
28 changed files with 334 additions and 173 deletions

View File

@@ -2,6 +2,7 @@
using System.Data;
using Newtonsoft.Json;
using IGDB.Models;
using gaseous_server.Classes.Metadata;
namespace gaseous_server.Classes
{
@@ -57,6 +58,14 @@ namespace gaseous_server.Classes
}
}
public static ConfigFile.MetadataAPI MetadataConfiguration
{
get
{
return _config.MetadataConfiguration;
}
}
public static ConfigFile.IGDB IGDB
{
get
@@ -247,6 +256,8 @@ namespace gaseous_server.Classes
[JsonIgnore]
public Library LibraryConfiguration = new Library();
public MetadataAPI MetadataConfiguration = new MetadataAPI();
public IGDB IGDBConfiguration = new IGDB();
public Logging LoggingConfiguration = new Logging();
@@ -460,6 +471,26 @@ namespace gaseous_server.Classes
}
}
public class MetadataAPI
{
private static Communications.MetadataSources _Source
{
get
{
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("metadatasource")))
{
return (Communications.MetadataSources)Enum.Parse(typeof(Communications.MetadataSources), Environment.GetEnvironmentVariable("metadatasource"));
}
else
{
return Communications.MetadataSources.IGDB;
}
}
}
public Communications.MetadataSources Source = _Source;
}
public class IGDB
{
private static string _DefaultIGDBClientId

View File

@@ -15,12 +15,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static AgeRating? GetAgeRatings(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -117,7 +111,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<AgeRating> GetObjectFromServer(string WhereClause)
{
// get AgeRatings metadata
var results = await igdb.QueryAsync<AgeRating>(IGDBClient.Endpoints.AgeRating, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<AgeRating>(IGDBClient.Endpoints.AgeRating, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static AgeRatingContentDescription? GetAgeRatingContentDescriptions(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -103,7 +97,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<AgeRatingContentDescription> GetObjectFromServer(string WhereClause)
{
// get AgeRatingContentDescriptionContentDescriptions metadata
var results = await igdb.QueryAsync<AgeRatingContentDescription>(IGDBClient.Endpoints.AgeRatingContentDescriptions, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<AgeRatingContentDescription>(IGDBClient.Endpoints.AgeRatingContentDescriptions, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static AlternativeName? GetAlternativeNames(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -103,7 +97,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<AlternativeName> GetObjectFromServer(string WhereClause)
{
// get AlternativeNames metadata
var results = await igdb.QueryAsync<AlternativeName>(IGDBClient.Endpoints.AlternativeNames, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<AlternativeName>(IGDBClient.Endpoints.AlternativeNames, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Artwork? GetArtwork(long? Id, string LogoPath)
{
if ((Id == 0) || (Id == null))
@@ -113,7 +107,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Artwork> GetObjectFromServer(string WhereClause, string LogoPath)
{
// get Artwork metadata
var results = await igdb.QueryAsync<Artwork>(IGDBClient.Endpoints.Artworks, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Artwork>(IGDBClient.Endpoints.Artworks, fieldList, WhereClause);
var result = results.First();
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb, result.ImageId);

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Collection? GetCollections(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -103,7 +97,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Collection> GetObjectFromServer(string WhereClause)
{
// get Collections metadata
var results = await igdb.QueryAsync<Collection>(IGDBClient.Endpoints.Collections, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Collection>(IGDBClient.Endpoints.Collections, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -0,0 +1,238 @@
using System.Net;
using IGDB;
using RestEase;
namespace gaseous_server.Classes.Metadata
{
/// <summary>
/// Handles all metadata API communications
/// </summary>
public class Communications
{
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
/// <summary>
/// Configure metadata API communications
/// </summary>
public static MetadataSources MetadataSource
{
get
{
return _MetadataSource;
}
set
{
_MetadataSource = value;
switch (value)
{
case MetadataSources.IGDB:
// set rate limiter avoidance values
RateLimitAvoidanceWait = 1500;
RateLimitAvoidanceThreshold = 3;
RateLimitAvoidancePeriod = 1;
// set rate limiter recovery values
RateLimitRecoveryWaitTime = 10000;
break;
default:
// leave all values at default
break;
}
}
}
private static MetadataSources _MetadataSource = MetadataSources.None;
// rate limit avoidance - what can we do to ensure that rate limiting is avoided?
// these values affect all communications
/// <summary>
/// How long to wait to avoid hitting an API rate limiter
/// </summary>
private static int RateLimitAvoidanceWait = 2000;
/// <summary>
/// How many API calls in the period are allowed before we start introducing a wait
/// </summary>
private static int RateLimitAvoidanceThreshold = 80;
/// <summary>
/// A counter of API calls since the beginning of the period
/// </summary>
private static int RateLimitAvoidanceCallCount = 0;
/// <summary>
/// How large the period (in seconds) to measure API call counts against
/// </summary>
private static int RateLimitAvoidancePeriod = 60;
/// <summary>
/// The start of the rate limit avoidance period
/// </summary>
private static DateTime RateLimitAvoidanceStartTime = DateTime.UtcNow;
/// <summary>
/// Used to determine if we're already in rate limit avoidance mode - always query "InRateLimitAvoidanceMode"
/// for up to date mode status.
/// This bool is used to track status changes and should not be relied upon for current status.
/// </summary>
private static bool InRateLimitAvoidanceModeStatus = false;
/// <summary>
/// Determine if we're in rate limit avoidance mode.
/// </summary>
private static bool InRateLimitAvoidanceMode
{
get
{
if (RateLimitAvoidanceStartTime.AddSeconds(RateLimitAvoidancePeriod) <= DateTime.UtcNow)
{
// avoidance period has expired - reset
RateLimitAvoidanceCallCount = 0;
RateLimitAvoidanceStartTime = DateTime.UtcNow;
return false;
}
else
{
// we're in the avoidance period
if (RateLimitAvoidanceCallCount > RateLimitAvoidanceThreshold)
{
// the number of call counts indicates we should throttle things a bit
if (InRateLimitAvoidanceModeStatus == false)
{
Logging.Log(Logging.LogType.Information, "API Connection", "Entered rate limit avoidance period, API calls will be throttled by " + RateLimitAvoidanceWait + " milliseconds.");
InRateLimitAvoidanceModeStatus = true;
}
return true;
}
else
{
// still in full speed mode - no throttle required
if (InRateLimitAvoidanceModeStatus == true)
{
Logging.Log(Logging.LogType.Information, "API Connection", "Exited rate limit avoidance period, API call rate is returned to full speed.");
InRateLimitAvoidanceModeStatus = false;
}
return false;
}
}
}
}
// rate limit handling - how long to wait to allow the server to recover and try again
// these values affect ALL communications if a 429 response code is received
/// <summary>
/// How long to wait (in milliseconds) if a 429 status code is received before trying again
/// </summary>
private static int RateLimitRecoveryWaitTime = 10000;
/// <summary>
/// The time when normal communications can attempt to be resumed
/// </summary>
private static DateTime RateLimitResumeTime = DateTime.UtcNow.AddMinutes(5 * -1);
// rate limit retry - how many times to retry before aborting
private int RetryAttempts = 0;
private int RetryAttemptsMax = 3;
/// <summary>
/// Supported metadata sources
/// </summary>
public enum MetadataSources
{
/// <summary>
/// None - always returns null for metadata requests - should not really be using this source
/// </summary>
None,
/// <summary>
/// IGDB - queries the IGDB service for metadata
/// </summary>
IGDB
}
/// <summary>
/// Request data from the metadata API
/// </summary>
/// <typeparam name="T">Type of object to return</typeparam>
/// <param name="Endpoint">API endpoint segment to use</param>
/// <param name="Fields">Fields to request from the API</param>
/// <param name="Query">Selection criteria for data to request</param>
/// <returns></returns>
public async Task<T[]?> APIComm<T>(string Endpoint, string Fields, string Query)
{
switch (_MetadataSource)
{
case MetadataSources.None:
return null;
case MetadataSources.IGDB:
return await IGDBAPI<T>(Endpoint, Fields, Query);
default:
return null;
}
}
private async Task<T[]> IGDBAPI<T>(string Endpoint, string Fields, string Query)
{
Logging.Log(Logging.LogType.Debug, "API Connection", "Accessing API for endpoint: " + Endpoint);
if (RateLimitResumeTime > DateTime.UtcNow)
{
Logging.Log(Logging.LogType.Information, "API Connection", "IGDB rate limit hit. Pausing API communications until " + RateLimitResumeTime.ToString() + ". Attempt " + RetryAttempts + " of " + RetryAttemptsMax + " retries.");
Thread.Sleep(RateLimitRecoveryWaitTime);
}
try
{
if (InRateLimitAvoidanceMode == true)
{
// sleep for a moment to help avoid hitting the rate limiter
Thread.Sleep(RateLimitAvoidanceWait);
}
// perform the actual API call
var results = await igdb.QueryAsync<T>(Endpoint, query: Fields + " " + Query + ";");
// increment rate limiter avoidance call count
RateLimitAvoidanceCallCount += 1;
return results;
}
catch (ApiException apiEx)
{
switch (apiEx.StatusCode)
{
case HttpStatusCode.TooManyRequests:
if (RetryAttempts >= RetryAttemptsMax)
{
Logging.Log(Logging.LogType.Warning, "API Connection", "IGDB rate limiter attempts expired. Aborting.", apiEx);
throw;
}
else
{
Logging.Log(Logging.LogType.Information, "API Connection", "IGDB API rate limit hit while accessing endpoint " + Endpoint, apiEx);
RetryAttempts += 1;
return await IGDBAPI<T>(Endpoint, Fields, Query);
}
default:
Logging.Log(Logging.LogType.Warning, "API Connection", "Exception when accessing endpoint " + Endpoint, apiEx);
throw;
}
}
catch(Exception ex)
{
Logging.Log(Logging.LogType.Warning, "API Connection", "Exception when accessing endpoint " + Endpoint, ex);
throw;
}
}
}
}

View File

@@ -12,12 +12,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Company? GetCompanies(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -111,7 +105,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Company> GetObjectFromServer(string WhereClause)
{
// get Companies metadata
var results = await igdb.QueryAsync<Company>(IGDBClient.Endpoints.Companies, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Company>(IGDBClient.Endpoints.Companies, fieldList, WhereClause);
if (results.Length > 0)
{
var result = results.First();

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static CompanyLogo? GetCompanyLogo(long? Id, string LogoPath)
{
if ((Id == 0) || (Id == null))
@@ -118,7 +112,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<CompanyLogo?> GetObjectFromServer(string WhereClause, string LogoPath)
{
// get CompanyLogo metadata
var results = await igdb.QueryAsync<CompanyLogo>(IGDBClient.Endpoints.CompanyLogos, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<CompanyLogo>(IGDBClient.Endpoints.CompanyLogos, fieldList, WhereClause);
if (results.Length > 0)
{
var result = results.First();

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Cover? GetCover(long? Id, string LogoPath)
{
if ((Id == 0) || (Id == null))
@@ -113,7 +107,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Cover> GetObjectFromServer(string WhereClause, string LogoPath)
{
// get Cover metadata
var results = await igdb.QueryAsync<Cover>(IGDBClient.Endpoints.Covers, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Cover>(IGDBClient.Endpoints.Covers, fieldList, WhereClause);
var result = results.First();
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb, result.ImageId);

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static ExternalGame? GetExternalGames(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -106,7 +100,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<ExternalGame?> GetObjectFromServer(string WhereClause)
{
// get ExternalGames metadata
var results = await igdb.QueryAsync<ExternalGame>(IGDBClient.Endpoints.ExternalGames, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<ExternalGame>(IGDBClient.Endpoints.ExternalGames, fieldList, WhereClause);
if (results.Length > 0)
{
var result = results.First();

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Franchise? GetFranchises(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -103,7 +97,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Franchise> GetObjectFromServer(string WhereClause)
{
// get FranchiseContentDescriptions metadata
var results = await igdb.QueryAsync<Franchise>(IGDBClient.Endpoints.Franchies, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Franchise>(IGDBClient.Endpoints.Franchies, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static GameMode? GetGame_Modes(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -103,7 +97,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<GameMode> GetObjectFromServer(string WhereClause)
{
// get Game_Modes metadata
var results = await igdb.QueryAsync<GameMode>(IGDBClient.Endpoints.GameModes, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<GameMode>(IGDBClient.Endpoints.GameModes, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static GameVideo? GetGame_Videos(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -103,7 +97,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<GameVideo> GetObjectFromServer(string WhereClause)
{
// get Game_Videos metadata
var results = await igdb.QueryAsync<GameVideo>(IGDBClient.Endpoints.GameVideos, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<GameVideo>(IGDBClient.Endpoints.GameVideos, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -20,12 +20,6 @@ namespace gaseous_server.Classes.Metadata
{}
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Game? GetGame(long Id, bool getAllMetadata, bool followSubGames, bool forceRefresh)
{
if (Id == 0)
@@ -295,7 +289,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Game> GetObjectFromServer(string WhereClause)
{
// get Game metadata
var results = await igdb.QueryAsync<Game>(IGDBClient.Endpoints.Games, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, fieldList, WhereClause);
var result = results.First();
return result;
@@ -310,7 +305,7 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Game[]> _SearchForGame(string SearchString, long PlatformId, SearchType searchType)
{
string searchBody = "";
searchBody += "fields id,name,slug,platforms,summary; ";
string searchFields = "fields id,name,slug,platforms,summary; ";
switch (searchType)
{
case SearchType.searchNoPlatform:
@@ -330,7 +325,8 @@ namespace gaseous_server.Classes.Metadata
// get Game metadata
var results = await igdb.QueryAsync<Game>(IGDBClient.Endpoints.Games, query: searchBody);
Communications comms = new Communications();
var results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody);
return results;
}

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Genre? GetGenres(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -103,7 +97,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Genre> GetObjectFromServer(string WhereClause)
{
// get Genres metadata
var results = await igdb.QueryAsync<Genre>(IGDBClient.Endpoints.Genres, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Genre>(IGDBClient.Endpoints.Genres, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -12,12 +12,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static InvolvedCompany? GetInvolvedCompanies(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -113,7 +107,8 @@ namespace gaseous_server.Classes.Metadata
// get InvolvedCompanies metadata
try
{
var results = await igdb.QueryAsync<InvolvedCompany>(IGDBClient.Endpoints.InvolvedCompanies, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<InvolvedCompany>(IGDBClient.Endpoints.InvolvedCompanies, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static MultiplayerMode? GetGame_MultiplayerModes(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -103,7 +97,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<MultiplayerMode> GetObjectFromServer(string WhereClause)
{
// get Game_MultiplayerModes metadata
var results = await igdb.QueryAsync<MultiplayerMode>(IGDBClient.Endpoints.MultiplayerModes, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<MultiplayerMode>(IGDBClient.Endpoints.MultiplayerModes, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static PlatformLogo? GetPlatformLogo(long? Id, string LogoPath)
{
if ((Id == 0) || (Id == null))
@@ -118,7 +112,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<PlatformLogo?> GetObjectFromServer(string WhereClause, string LogoPath)
{
// get PlatformLogo metadata
var results = await igdb.QueryAsync<PlatformLogo>(IGDBClient.Endpoints.PlatformLogos, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<PlatformLogo>(IGDBClient.Endpoints.PlatformLogos, fieldList, WhereClause);
if (results.Length > 0)
{
var result = results.First();

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static PlatformVersion? GetPlatformVersion(long Id, Platform ParentPlatform)
{
if (Id == 0)
@@ -113,7 +107,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<PlatformVersion?> GetObjectFromServer(string WhereClause)
{
// get PlatformVersion metadata
var results = await igdb.QueryAsync<PlatformVersion>(IGDBClient.Endpoints.PlatformVersions, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<PlatformVersion>(IGDBClient.Endpoints.PlatformVersions, fieldList, WhereClause);
if (results.Length > 0)
{
var result = results.First();

View File

@@ -15,12 +15,6 @@ namespace gaseous_server.Classes.Metadata
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Platform? GetPlatform(long Id, bool forceRefresh = false)
{
if (Id == 0)
@@ -168,7 +162,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Platform> GetObjectFromServer(string WhereClause)
{
// get platform metadata
var results = await igdb.QueryAsync<Platform>(IGDBClient.Endpoints.Platforms, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Platform>(IGDBClient.Endpoints.Platforms, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static PlayerPerspective? GetGame_PlayerPerspectives(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -105,7 +99,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<PlayerPerspective> GetObjectFromServer(string WhereClause)
{
// get Game_PlayerPerspectives metadata
var results = await igdb.QueryAsync<PlayerPerspective>(IGDBClient.Endpoints.PlayerPerspectives, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<PlayerPerspective>(IGDBClient.Endpoints.PlayerPerspectives, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static ReleaseDate? GetReleaseDates(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -103,7 +97,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<ReleaseDate> GetObjectFromServer(string WhereClause)
{
// get ReleaseDates metadata
var results = await igdb.QueryAsync<ReleaseDate>(IGDBClient.Endpoints.ReleaseDates, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<ReleaseDate>(IGDBClient.Endpoints.ReleaseDates, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Screenshot? GetScreenshot(long? Id, string LogoPath)
{
if ((Id == 0) || (Id == null))
@@ -114,7 +108,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Screenshot> GetObjectFromServer(string WhereClause, string LogoPath)
{
// get Screenshot metadata
var results = await igdb.QueryAsync<Screenshot>(IGDBClient.Endpoints.Screenshots, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Screenshot>(IGDBClient.Endpoints.Screenshots, fieldList, WhereClause);
var result = results.First();
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb, result.ImageId);

View File

@@ -414,6 +414,12 @@ namespace gaseous_server.Classes.Metadata
case "[igdb.models.startdatecategory":
property.SetValue(EndpointType, (StartDateCategory)dataRow[property.Name]);
break;
case "[igdb.models.releasedateregion":
property.SetValue(EndpointType, (ReleaseDateRegion)dataRow[property.Name]);
break;
case "[igdb.models.releasedatecategory":
property.SetValue(EndpointType, (ReleaseDateCategory)dataRow[property.Name]);
break;
default:
property.SetValue(EndpointType, dataRow[property.Name]);
break;

View File

@@ -13,12 +13,6 @@ namespace gaseous_server.Classes.Metadata
{
}
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
public static Theme? GetGame_Themes(long? Id)
{
if ((Id == 0) || (Id == null))
@@ -105,7 +99,8 @@ namespace gaseous_server.Classes.Metadata
private static async Task<Theme> GetObjectFromServer(string WhereClause)
{
// get Game_Themes metadata
var results = await igdb.QueryAsync<Theme>(IGDBClient.Endpoints.Themes, query: fieldList + " " + WhereClause + ";");
Communications comms = new Communications();
var results = await comms.APIComm<Theme>(IGDBClient.Endpoints.Themes, fieldList, WhereClause);
var result = results.First();
return result;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using gaseous_server.Classes;
using gaseous_server.Classes.Metadata;
using IGDB;
using IGDB.Models;
using Microsoft.AspNetCore.Authorization;
@@ -19,12 +20,6 @@ namespace gaseous_server.Controllers
[Authorize]
public class SearchController : Controller
{
private static IGDBClient igdb = new IGDBClient(
// Found in Twitch Developer portal for your app
Config.IGDB.ClientId,
Config.IGDB.Secret
);
[MapToApiVersion("1.0")]
[MapToApiVersion("1.1")]
[HttpGet]
@@ -39,11 +34,12 @@ namespace gaseous_server.Controllers
private static async Task<List<Platform>> _SearchForPlatform(string SearchString)
{
string searchBody = "";
searchBody += "fields abbreviation,alternative_name,category,checksum,created_at,generation,name,platform_family,platform_logo,slug,summary,updated_at,url,versions,websites; ";
string searchFields = "fields abbreviation,alternative_name,category,checksum,created_at,generation,name,platform_family,platform_logo,slug,summary,updated_at,url,versions,websites; ";
searchBody += "where name ~ *\"" + SearchString + "\"*;";
// get Platform metadata
var results = await igdb.QueryAsync<Platform>(IGDBClient.Endpoints.Platforms, query: searchBody);
Communications comms = new Communications();
var results = await comms.APIComm<Platform>(IGDBClient.Endpoints.Platforms, searchFields, searchBody);
return results.ToList();
}
@@ -62,12 +58,13 @@ namespace gaseous_server.Controllers
private static async Task<List<Game>> _SearchForGame(long PlatformId, string SearchString)
{
string searchBody = "";
searchBody += "fields cover.*,first_release_date,name,platforms,slug; ";
string searchFields = "fields cover.*,first_release_date,name,platforms,slug; ";
searchBody += "search \"" + SearchString + "\";";
searchBody += "where platforms = (" + PlatformId + ");";
// get Platform metadata
var results = await igdb.QueryAsync<Game>(IGDBClient.Endpoints.Games, query: searchBody);
Communications comms = new Communications();
var results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody);
return results.ToList();
}

View File

@@ -49,6 +49,9 @@ Config.InitSettings();
// write updated settings back to the config file
Config.UpdateConfig();
// set api metadata source from config
Communications.MetadataSource = Config.MetadataConfiguration.Source;
// set initial values
Guid APIKey = Guid.NewGuid();
if (Config.ReadSetting("API Key", "Test API Key") == "Test API Key")