Compare commits

...

5 Commits

Author SHA1 Message Date
Michael Green
ea0a5a6a71 Add missing indexes (#238)
* Add missing index

* Check of indexes
2023-12-21 20:39:37 +11:00
Michael Green
d014a176ce Many performance updates (#237) 2023-12-21 16:59:17 +11:00
Michael Green
b9d9b0ea16 Filter ROMs by platform (#236)
* Added paging to the ROM display on game pages

* Added basic ROM filtering
2023-12-20 13:31:45 +11:00
Michael Green
7e3e4991dc Now pre-compiles age group metadata instead of generating it on every query (#235)
* Server will now quit on start up if schema updates fail (closes Abort start up if an error occurs during database upgrade #221)

* Moved AgeGroups to it's own class

* Improved query performance by defining the AgeGroupId as a metadata item. A metadata refresh is required to generate this data
2023-12-19 23:03:02 +11:00
Michael Green
57248cd467 Overhaul of SQL queries to (hopefully) improve performance with large libraries (#233)
* Latest round of performance updates

* Improved first set up logging

* Updated logging display
2023-12-17 00:51:46 +11:00
29 changed files with 1045 additions and 351 deletions

View File

@@ -1,6 +1,6 @@
# Gaseous Server # Gaseous Server
This is the server for the Gaseous system. It offers ROM and title management, as well as some basic in browser emulation of those ROM's. This is the server for the Gaseous system. It offers ROM and title management, as well as some basic in browser emulation of those ROMs.
## Warning ## Warning

View File

@@ -5,13 +5,13 @@ namespace Authentication
public class SecurityProfileViewModel public class SecurityProfileViewModel
{ {
public AgeRestrictionItem AgeRestrictionPolicy { get; set; } = new AgeRestrictionItem{ public AgeRestrictionItem AgeRestrictionPolicy { get; set; } = new AgeRestrictionItem{
MaximumAgeRestriction = gaseous_server.Classes.Metadata.AgeRatings.AgeGroups.AgeRestrictionGroupings.Adult, MaximumAgeRestriction = gaseous_server.Classes.Metadata.AgeGroups.AgeRestrictionGroupings.Adult,
IncludeUnrated = true IncludeUnrated = true
}; };
public class AgeRestrictionItem public class AgeRestrictionItem
{ {
public gaseous_server.Classes.Metadata.AgeRatings.AgeGroups.AgeRestrictionGroupings MaximumAgeRestriction { get; set; } public gaseous_server.Classes.Metadata.AgeGroups.AgeRestrictionGroupings MaximumAgeRestriction { get; set; }
public bool IncludeUnrated { get; set; } public bool IncludeUnrated { get; set; }
} }
} }

View File

@@ -220,7 +220,7 @@ namespace gaseous_server.Classes
} }
} else { } else {
// get all platforms to pull from // get all platforms to pull from
Dictionary<string, object> FilterDict = Filters.Filter(AgeRatings.AgeGroups.AgeRestrictionGroupings.Adult, true); Dictionary<string, List<Filters.FilterItem>> FilterDict = Filters.Filter(AgeGroups.AgeRestrictionGroupings.Adult, true);
List<Classes.Filters.FilterItem> filteredPlatforms = (List<Classes.Filters.FilterItem>)FilterDict["platforms"]; List<Classes.Filters.FilterItem> filteredPlatforms = (List<Classes.Filters.FilterItem>)FilterDict["platforms"];
foreach (Filters.FilterItem filterItem in filteredPlatforms) { foreach (Filters.FilterItem filterItem in filteredPlatforms) {
platforms.Add(Platforms.GetPlatform(filterItem.Id)); platforms.Add(Platforms.GetPlatform(filterItem.Id));
@@ -499,7 +499,7 @@ namespace gaseous_server.Classes
if (File.Exists(gameRomItem.Path)) if (File.Exists(gameRomItem.Path))
{ {
Logging.Log(Logging.LogType.Information, "Collections", "Copying ROM: " + gameRomItem.Name); Logging.Log(Logging.LogType.Information, "Collections", "Copying ROM: " + gameRomItem.Name);
File.Copy(gameRomItem.Path, Path.Combine(ZipGamePath, gameRomItem.Name)); File.Copy(gameRomItem.Path, Path.Combine(ZipGamePath, gameRomItem.Name), true);
} }
} }
} }

View File

@@ -107,20 +107,28 @@ namespace gaseous_server.Classes
Logging.Log(Logging.LogType.Information, "Database", "Schema version is " + SchemaVer); Logging.Log(Logging.LogType.Information, "Database", "Schema version is " + SchemaVer);
if (SchemaVer < i) if (SchemaVer < i)
{ {
// run pre-upgrade code try
DatabaseMigration.PreUpgradeScript(i, _ConnectorType); {
// run pre-upgrade code
DatabaseMigration.PreUpgradeScript(i, _ConnectorType);
// apply schema! // apply schema!
Logging.Log(Logging.LogType.Information, "Database", "Updating schema to version " + i); Logging.Log(Logging.LogType.Information, "Database", "Updating schema to version " + i);
ExecuteCMD(dbScript, dbDict); ExecuteCMD(dbScript, dbDict, 180);
sql = "UPDATE schema_version SET schema_version=@schemaver"; sql = "UPDATE schema_version SET schema_version=@schemaver";
dbDict = new Dictionary<string, object>(); dbDict = new Dictionary<string, object>();
dbDict.Add("schemaver", i); dbDict.Add("schemaver", i);
ExecuteCMD(sql, dbDict); ExecuteCMD(sql, dbDict);
// run post-upgrade code // run post-upgrade code
DatabaseMigration.PostUpgradeScript(i, _ConnectorType); DatabaseMigration.PostUpgradeScript(i, _ConnectorType);
}
catch (Exception ex)
{
Logging.Log(Logging.LogType.Critical, "Database", "Schema upgrade failed! Unable to continue.", ex);
System.Environment.Exit(1);
}
} }
} }
} }

View File

@@ -7,24 +7,24 @@ namespace gaseous_server.Classes
{ {
public class Filters public class Filters
{ {
public static Dictionary<string, object> Filter(Metadata.AgeRatings.AgeGroups.AgeRestrictionGroupings MaximumAgeRestriction, bool IncludeUnrated) public static Dictionary<string, List<FilterItem>> Filter(Metadata.AgeGroups.AgeRestrictionGroupings MaximumAgeRestriction, bool IncludeUnrated)
{ {
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
Dictionary<string, object> FilterSet = new Dictionary<string, object>(); Dictionary<string, List<FilterItem>> FilterSet = new Dictionary<string, List<FilterItem>>();
// platforms // platforms
List<FilterItem> platforms = new List<FilterItem>(); List<FilterItem> platforms = new List<FilterItem>();
string ageRestriction_Platform = "Game.AgeGroupId <= " + (int)MaximumAgeRestriction; string ageRestriction_Platform = "AgeGroup.AgeGroupId <= " + (int)MaximumAgeRestriction;
string ageRestriction_Generic = "view_Games.AgeGroupId <= " + (int)MaximumAgeRestriction; string ageRestriction_Generic = "view_Games.AgeGroupId <= " + (int)MaximumAgeRestriction;
if (IncludeUnrated == true) if (IncludeUnrated == true)
{ {
ageRestriction_Platform += " OR Game.AgeGroupId IS NULL"; ageRestriction_Platform += " OR AgeGroup.AgeGroupId IS NULL";
ageRestriction_Generic += " OR view_Games.AgeGroupId IS NULL"; ageRestriction_Generic += " OR view_Games.AgeGroupId IS NULL";
} }
string sql = "SELECT Platform.Id, Platform.`Name`, COUNT(view_Games.Id) AS GameCount FROM view_Games JOIN Relation_Game_Platforms ON Relation_Game_Platforms.GameId = view_Games.Id AND (Relation_Game_Platforms.PlatformsId IN (SELECT DISTINCT PlatformId FROM Games_Roms WHERE Games_Roms.GameId = view_Games.Id)) JOIN Platform ON Platform.Id = Relation_Game_Platforms.PlatformsId WHERE (" + ageRestriction_Generic + ") GROUP BY Platform.`Name` ORDER BY Platform.`Name`;"; string sql = "SELECT Platform.Id, Platform.`Name`, COUNT(Game.Id) AS GameCount FROM (SELECT DISTINCT Game.Id, Games_Roms.PlatformId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId WHERE (" + ageRestriction_Platform + ") GROUP BY Game.Id , Games_Roms.PlatformId HAVING RomCount > 0) Game JOIN Platform ON Game.PlatformId = Platform.Id GROUP BY Platform.`Name`;";
DataTable dbResponse = db.ExecuteCMD(sql); DataTable dbResponse = db.ExecuteCMD(sql);
@@ -38,7 +38,7 @@ namespace gaseous_server.Classes
// genres // genres
List<FilterItem> genres = new List<FilterItem>(); List<FilterItem> genres = new List<FilterItem>();
dbResponse = GetGenericFilterItem(db, "Genre", ageRestriction_Generic); dbResponse = GetGenericFilterItem(db, "Genre", ageRestriction_Platform);
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
@@ -49,7 +49,7 @@ namespace gaseous_server.Classes
// game modes // game modes
List<FilterItem> gameModes = new List<FilterItem>(); List<FilterItem> gameModes = new List<FilterItem>();
dbResponse = GetGenericFilterItem(db, "GameMode", ageRestriction_Generic); dbResponse = GetGenericFilterItem(db, "GameMode", ageRestriction_Platform);
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
@@ -60,7 +60,7 @@ namespace gaseous_server.Classes
// player perspectives // player perspectives
List<FilterItem> playerPerspectives = new List<FilterItem>(); List<FilterItem> playerPerspectives = new List<FilterItem>();
dbResponse = GetGenericFilterItem(db, "PlayerPerspective", ageRestriction_Generic); dbResponse = GetGenericFilterItem(db, "PlayerPerspective", ageRestriction_Platform);
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
@@ -71,7 +71,7 @@ namespace gaseous_server.Classes
// themes // themes
List<FilterItem> themes = new List<FilterItem>(); List<FilterItem> themes = new List<FilterItem>();
dbResponse = GetGenericFilterItem(db, "Theme", ageRestriction_Generic); dbResponse = GetGenericFilterItem(db, "Theme", ageRestriction_Platform);
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
@@ -81,22 +81,24 @@ namespace gaseous_server.Classes
FilterSet.Add("themes", themes); FilterSet.Add("themes", themes);
// age groups // age groups
List<FilterAgeGrouping> agegroupings = new List<FilterAgeGrouping>(); List<FilterItem> agegroupings = new List<FilterItem>();
sql = "SELECT view_Games.Id, view_Games.AgeGroupId, COUNT(view_Games.Id) AS GameCount FROM view_Games WHERE (" + ageRestriction_Generic + ") GROUP BY view_Games.AgeGroupId ORDER BY view_Games.AgeGroupId DESC;"; sql = "SELECT Game.AgeGroupId, COUNT(Game.Id) AS GameCount FROM (SELECT DISTINCT Game.Id, AgeGroup.AgeGroupId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId WHERE (" + ageRestriction_Platform + ") GROUP BY Game.Id HAVING RomCount > 0) Game GROUP BY Game.AgeGroupId ORDER BY Game.AgeGroupId DESC";
dbResponse = db.ExecuteCMD(sql); dbResponse = db.ExecuteCMD(sql);
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
FilterAgeGrouping filterAgeGrouping = new FilterAgeGrouping(); FilterItem filterAgeGrouping = new FilterItem();
if (dr["AgeGroupId"] == DBNull.Value) if (dr["AgeGroupId"] == DBNull.Value)
{ {
filterAgeGrouping.Id = (long)AgeRatings.AgeGroups.AgeRestrictionGroupings.Unclassified; filterAgeGrouping.Id = (int)(long)AgeGroups.AgeRestrictionGroupings.Unclassified;
filterAgeGrouping.AgeGroup = AgeRatings.AgeGroups.AgeRestrictionGroupings.Unclassified; filterAgeGrouping.Name = AgeGroups.AgeRestrictionGroupings.Unclassified.ToString();
} }
else else
{ {
filterAgeGrouping.Id = (long)(AgeRatings.AgeGroups.AgeRestrictionGroupings)dr["AgeGroupId"]; int ageGroupLong = (int)dr["AgeGroupId"];
filterAgeGrouping.AgeGroup = (AgeRatings.AgeGroups.AgeRestrictionGroupings)dr["AgeGroupId"]; AgeGroups.AgeRestrictionGroupings ageGroup = (AgeGroups.AgeRestrictionGroupings)ageGroupLong;
filterAgeGrouping.Id = ageGroupLong;
filterAgeGrouping.Name = ageGroup.ToString();
} }
filterAgeGrouping.GameCount = (int)(long)dr["GameCount"]; filterAgeGrouping.GameCount = (int)(long)dr["GameCount"];
agegroupings.Add(filterAgeGrouping); agegroupings.Add(filterAgeGrouping);
@@ -106,9 +108,11 @@ namespace gaseous_server.Classes
return FilterSet; return FilterSet;
} }
private static DataTable GetGenericFilterItem(Database db, string Name, string AgeRestriction_Generic) private static DataTable GetGenericFilterItem(Database db, string Name, string AgeRestriction)
{ {
string sql = "SELECT DISTINCT <ITEMNAME>.Id, <ITEMNAME>.`Name`, COUNT(view_Games.Id) AS GameCount FROM <ITEMNAME> LEFT JOIN Relation_Game_<ITEMNAME>s ON Relation_Game_<ITEMNAME>s.<ITEMNAME>sId = <ITEMNAME>.Id LEFT JOIN view_Games ON view_Games.Id = Relation_Game_<ITEMNAME>s.GameId WHERE (" + AgeRestriction_Generic + ") GROUP BY <ITEMNAME>.Id HAVING GameCount > 0 ORDER BY <ITEMNAME>.`Name`;"; //string sql = "SELECT DISTINCT <ITEMNAME>.Id, <ITEMNAME>.`Name`, COUNT(view_Games.Id) AS GameCount FROM <ITEMNAME> LEFT JOIN Relation_Game_<ITEMNAME>s ON Relation_Game_<ITEMNAME>s.<ITEMNAME>sId = <ITEMNAME>.Id LEFT JOIN view_Games ON view_Games.Id = Relation_Game_<ITEMNAME>s.GameId WHERE (" + AgeRestriction_Generic + ") GROUP BY <ITEMNAME>.Id HAVING GameCount > 0 ORDER BY <ITEMNAME>.`Name`;";
string sql = "SELECT <ITEMNAME>.Id, <ITEMNAME>.`Name`, COUNT(Game.Id) AS GameCount FROM (SELECT DISTINCT Game.Id, AgeGroup.AgeGroupId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId WHERE (" + AgeRestriction + ") GROUP BY Game.Id HAVING RomCount > 0) Game JOIN Relation_Game_<ITEMNAME>s ON Game.Id = Relation_Game_<ITEMNAME>s.GameId JOIN <ITEMNAME> ON Relation_Game_<ITEMNAME>s.<ITEMNAME>sId = <ITEMNAME>.Id GROUP BY <ITEMNAME>.`Name` ORDER BY <ITEMNAME>.`Name`;";
sql = sql.Replace("<ITEMNAME>", Name); sql = sql.Replace("<ITEMNAME>", Name);
DataTable dbResponse = db.ExecuteCMD(sql); DataTable dbResponse = db.ExecuteCMD(sql);
@@ -117,6 +121,11 @@ namespace gaseous_server.Classes
public class FilterItem public class FilterItem
{ {
public FilterItem()
{
}
public FilterItem(DataRow dr) public FilterItem(DataRow dr)
{ {
this.Id = (long)dr["Id"]; this.Id = (long)dr["Id"];
@@ -130,22 +139,5 @@ namespace gaseous_server.Classes
public int GameCount { get; set; } public int GameCount { get; set; }
} }
public class FilterAgeGrouping
{
public long Id { get; set; }
public AgeRatings.AgeGroups.AgeRestrictionGroupings AgeGroup { get ; set; }
public string Name
{
get
{
return this.AgeGroup.ToString();
}
}
public int GameCount { get; set; }
}
} }
} }

View File

@@ -690,25 +690,32 @@ namespace gaseous_server.Classes
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId); IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
IGDB.Models.Game determinedGame = new Game(); IGDB.Models.Game determinedGame = new Game();
if (determinedPlatform == null) try
{ {
if (library.DefaultPlatformId == 0) if (determinedPlatform == null)
{ {
determinedPlatform = new IGDB.Models.Platform(); if (library.DefaultPlatformId == 0)
determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId); {
determinedPlatform = new IGDB.Models.Platform();
determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
}
else
{
determinedPlatform = Platforms.GetPlatform(library.DefaultPlatformId);
determinedGame = SearchForGame(sig.Game.Name, library.DefaultPlatformId);
}
} }
else else
{ {
determinedPlatform = Platforms.GetPlatform(library.DefaultPlatformId); determinedGame = SearchForGame(sig.Game.Name, (long)determinedPlatform.Id);
determinedGame = SearchForGame(sig.Game.Name, library.DefaultPlatformId);
} }
}
else
{
determinedGame = SearchForGame(sig.Game.Name, (long)determinedPlatform.Id);
}
StoreROM(library, hash, determinedGame, determinedPlatform, sig, LibraryFile); StoreROM(library, hash, determinedGame, determinedPlatform, sig, LibraryFile);
}
catch (Exception ex)
{
Logging.Log(Logging.LogType.Warning, "Library Scan", " An error occurred while matching orphaned file: " + LibraryFile + ". Skipping.", ex);
}
} }
} }
StatusCount += 1; StatusCount += 1;
@@ -720,6 +727,7 @@ namespace gaseous_server.Classes
// check all roms to see if their local file still exists // check all roms to see if their local file still exists
Logging.Log(Logging.LogType.Information, "Library Scan", "Checking library files exist on disk"); Logging.Log(Logging.LogType.Information, "Library Scan", "Checking library files exist on disk");
StatusCount = 0;
if (dtRoms.Rows.Count > 0) if (dtRoms.Rows.Count > 0)
{ {
for (var i = 0; i < dtRoms.Rows.Count; i++) for (var i = 0; i < dtRoms.Rows.Count; i++)
@@ -728,6 +736,7 @@ namespace gaseous_server.Classes
string romPath = (string)dtRoms.Rows[i]["Path"]; string romPath = (string)dtRoms.Rows[i]["Path"];
gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType romMetadataSource = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(int)dtRoms.Rows[i]["MetadataSource"]; gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType romMetadataSource = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(int)dtRoms.Rows[i]["MetadataSource"];
SetStatus(StatusCount, dtRoms.Rows.Count, "Processing file " + romPath);
Logging.Log(Logging.LogType.Information, "Library Scan", " Processing ROM at path " + romPath); Logging.Log(Logging.LogType.Information, "Library Scan", " Processing ROM at path " + romPath);
if (File.Exists(romPath)) if (File.Exists(romPath))
@@ -751,6 +760,8 @@ namespace gaseous_server.Classes
deleteDict.Add("libraryid", library.Id); deleteDict.Add("libraryid", library.Id);
db.ExecuteCMD(deleteSql, deleteDict); db.ExecuteCMD(deleteSql, deleteDict);
} }
StatusCount += 1;
} }
} }

View File

@@ -109,8 +109,25 @@ namespace gaseous_server.Classes
callingProcess = ""; callingProcess = "";
} }
string callingUser;
try
{
if (CallContext.GetData("CallingUser").ToString() == null)
{
callingUser = "";
}
else
{
callingUser = CallContext.GetData("CallingUser").ToString();
}
}
catch
{
callingUser = "";
}
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRententionDate; INSERT INTO ServerLogs (EventTime, EventType, Process, Message, Exception, CorrelationId, CallingProcess) VALUES (@EventTime, @EventType, @Process, @Message, @Exception, @correlationid, @callingprocess);"; string sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRententionDate; INSERT INTO ServerLogs (EventTime, EventType, Process, Message, Exception, CorrelationId, CallingProcess, CallingUser) VALUES (@EventTime, @EventType, @Process, @Message, @Exception, @correlationid, @callingprocess, @callinguser);";
Dictionary<string, object> dbDict = new Dictionary<string, object>(); Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("EventRententionDate", DateTime.UtcNow.AddDays(Config.LoggingConfiguration.LogRetention * -1)); dbDict.Add("EventRententionDate", DateTime.UtcNow.AddDays(Config.LoggingConfiguration.LogRetention * -1));
dbDict.Add("EventTime", logItem.EventTime); dbDict.Add("EventTime", logItem.EventTime);
@@ -120,6 +137,7 @@ namespace gaseous_server.Classes
dbDict.Add("Exception", Common.ReturnValueIfNull(logItem.ExceptionValue, "").ToString()); dbDict.Add("Exception", Common.ReturnValueIfNull(logItem.ExceptionValue, "").ToString());
dbDict.Add("correlationid", correlationId); dbDict.Add("correlationid", correlationId);
dbDict.Add("callingprocess", callingProcess); dbDict.Add("callingprocess", callingProcess);
dbDict.Add("callinguser", callingUser);
try try
{ {
@@ -238,6 +256,15 @@ namespace gaseous_server.Classes
} }
} }
if (model.CallingUser != null)
{
if (model.CallingUser.Length > 0)
{
dbDict.Add("callingUser", model.CallingUser);
whereClauses.Add("CallingUser = @callingUser");
}
}
// compile WHERE clause // compile WHERE clause
string whereClause = ""; string whereClause = "";
if (whereClauses.Count > 0) if (whereClauses.Count > 0)
@@ -252,7 +279,8 @@ namespace gaseous_server.Classes
{ {
whereClause = "WHERE " + whereClause; whereClause = "WHERE " + whereClause;
} }
sql = "SELECT * FROM ServerLogs " + whereClause + " ORDER BY Id DESC LIMIT @PageSize OFFSET @PageNumber;";
sql = "SELECT ServerLogs.Id, ServerLogs.EventTime, ServerLogs.EventType, ServerLogs.`Process`, ServerLogs.Message, ServerLogs.Exception, ServerLogs.CorrelationId, ServerLogs.CallingProcess, Users.Email FROM ServerLogs LEFT JOIN Users ON ServerLogs.CallingUser = Users.Id " + whereClause + " ORDER BY ServerLogs.Id DESC LIMIT @PageSize OFFSET @PageNumber;";
} }
else else
{ {
@@ -260,7 +288,8 @@ namespace gaseous_server.Classes
{ {
whereClause = "AND " + whereClause; whereClause = "AND " + whereClause;
} }
sql = "SELECT * FROM ServerLogs WHERE Id < @StartIndex " + whereClause + " ORDER BY Id DESC LIMIT @PageSize OFFSET @PageNumber;";
sql = "SELECT ServerLogs.Id, ServerLogs.EventTime, ServerLogs.EventType, ServerLogs.`Process`, ServerLogs.Message, ServerLogs.Exception, ServerLogs.CorrelationId, ServerLogs.CallingProcess, Users.Email FROM ServerLogs LEFT JOIN Users ON ServerLogs.CallingUser = Users.Id WHERE ServerLogs.Id < @StartIndex " + whereClause + " ORDER BY ServerLogs.Id DESC LIMIT @PageSize OFFSET @PageNumber;";
} }
DataTable dataTable = db.ExecuteCMD(sql, dbDict); DataTable dataTable = db.ExecuteCMD(sql, dbDict);
@@ -276,7 +305,8 @@ namespace gaseous_server.Classes
Message = (string)row["Message"], Message = (string)row["Message"],
ExceptionValue = (string)row["Exception"], ExceptionValue = (string)row["Exception"],
CorrelationId = (string)Common.ReturnValueIfNull(row["CorrelationId"], ""), CorrelationId = (string)Common.ReturnValueIfNull(row["CorrelationId"], ""),
CallingProcess = (string)Common.ReturnValueIfNull(row["CallingProcess"], "") CallingProcess = (string)Common.ReturnValueIfNull(row["CallingProcess"], ""),
CallingUser = (string)Common.ReturnValueIfNull(row["Email"], "")
}; };
logs.Add(log); logs.Add(log);
@@ -301,6 +331,7 @@ namespace gaseous_server.Classes
public string Process { get; set; } = ""; public string Process { get; set; } = "";
public string CorrelationId { get; set; } = ""; public string CorrelationId { get; set; } = "";
public string? CallingProcess { get; set; } = ""; public string? CallingProcess { get; set; } = "";
public string? CallingUser { get; set; } = "";
private string _Message = ""; private string _Message = "";
public string Message public string Message
{ {
@@ -327,6 +358,7 @@ namespace gaseous_server.Classes
public string? SearchText { get; set; } public string? SearchText { get; set; }
public string? CorrelationId { get; set; } public string? CorrelationId { get; set; }
public string? CallingProcess { get; set; } public string? CallingProcess { get; set; }
public string? CallingUser { get; set; }
} }
} }
} }

View File

@@ -0,0 +1,304 @@
using System;
using System.Reflection;
using System.Text.Json.Serialization;
using IGDB;
using IGDB.Models;
using Microsoft.CodeAnalysis.Classification;
namespace gaseous_server.Classes.Metadata
{
public class AgeGroups
{
public AgeGroups()
{
}
public static AgeGroup? GetAgeGroup(Game? game)
{
if (game == null)
{
return null;
}
else
{
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
cacheStatus = Storage.GetCacheStatus("AgeGroup", (long)game.Id);
AgeGroup? RetVal = new AgeGroup();
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
RetVal = _GetAgeGroup(game);
Storage.NewCacheValue(RetVal, false);
break;
case Storage.CacheStatus.Expired:
RetVal = _GetAgeGroup(game);
Storage.NewCacheValue(RetVal, true);
break;
case Storage.CacheStatus.Current:
RetVal = Storage.GetCacheValue<AgeGroup>(RetVal, "Id", game.Id);
break;
default:
throw new Exception("How did you get here?");
}
return RetVal;
}
}
public static AgeGroup? _GetAgeGroup(Game game)
{
// compile the maximum age group for the given game
if (game != null)
{
if (game.AgeRatings != null)
{
if (game.AgeRatings.Ids != null)
{
// collect ratings values from metadata
List<AgeRating> ageRatings = new List<AgeRating>();
foreach (long ratingId in game.AgeRatings.Ids)
{
AgeRating? rating = AgeRatings.GetAgeRatings(ratingId);
if (rating != null)
{
ageRatings.Add(rating);
}
}
// compile the ratings values into the ratings groups
AgeRestrictionGroupings highestAgeGroup = AgeRestrictionGroupings.Unclassified;
foreach (AgeRating ageRating in ageRatings)
{
foreach (KeyValuePair<AgeRestrictionGroupings, AgeGroupItem> ageGroupItem in AgeGroupingsFlat)
{
PropertyInfo[] groupProps = typeof(AgeGroupItem).GetProperties();
foreach (PropertyInfo property in groupProps)
{
if (RatingsBoards.Contains(property.Name))
{
List<AgeRatingTitle> ratingBoard = (List<AgeRatingTitle>)property.GetValue(ageGroupItem.Value);
foreach (AgeRatingTitle ratingTitle in ratingBoard)
{
if (ageRating.Rating == ratingTitle)
{
if (highestAgeGroup < ageGroupItem.Key)
{
highestAgeGroup = ageGroupItem.Key;
}
}
}
}
}
}
}
// return the compiled ratings group
AgeGroup ageGroup = new AgeGroup();
ageGroup.Id = game.Id;
ageGroup.GameId = game.Id;
if (highestAgeGroup == 0)
{
ageGroup.AgeGroupId = null;
}
else
{
ageGroup.AgeGroupId = highestAgeGroup;
}
return ageGroup;
}
else
{
AgeGroup ageGroup = new AgeGroup();
ageGroup.Id = game.Id;
ageGroup.GameId = game.Id;
ageGroup.AgeGroupId = null;
return ageGroup;
}
}
else
{
AgeGroup ageGroup = new AgeGroup();
ageGroup.Id = game.Id;
ageGroup.GameId = game.Id;
ageGroup.AgeGroupId = null;
return ageGroup;
}
}
return null;
}
public class AgeGroup
{
public long? Id { get; set; }
public long? GameId { get; set; }
public AgeRestrictionGroupings? AgeGroupId { get; set; }
}
public static Dictionary<AgeRestrictionGroupings, List<AgeGroupItem>> AgeGroupings
{
get
{
return new Dictionary<AgeRestrictionGroupings, List<AgeGroupItem>>{
{
AgeRestrictionGroupings.Adult, new List<AgeGroupItem>{ Adult_Item, Mature_Item, Teen_Item, Child_Item }
},
{
AgeRestrictionGroupings.Mature, new List<AgeGroupItem>{ Mature_Item, Teen_Item, Child_Item }
},
{
AgeRestrictionGroupings.Teen, new List<AgeGroupItem>{ Teen_Item, Child_Item }
},
{
AgeRestrictionGroupings.Child, new List<AgeGroupItem>{ Child_Item }
}
};
}
}
public static Dictionary<AgeRestrictionGroupings, AgeGroupItem> AgeGroupingsFlat
{
get
{
return new Dictionary<AgeRestrictionGroupings, AgeGroupItem>{
{
AgeRestrictionGroupings.Adult, Adult_Item
},
{
AgeRestrictionGroupings.Mature, Mature_Item
},
{
AgeRestrictionGroupings.Teen, Teen_Item
},
{
AgeRestrictionGroupings.Child, Child_Item
}
};
}
}
public enum AgeRestrictionGroupings
{
Adult = 4,
Mature = 3,
Teen = 2,
Child = 1,
Unclassified = 0
}
public static List<string> RatingsBoards
{
get
{
List<string> boards = new List<string>{
"ACB", "CERO", "CLASS_IND", "ESRB", "GRAC", "PEGI", "USK"
};
return boards;
}
}
readonly static AgeGroupItem Adult_Item = new AgeGroupItem{
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_R18, AgeRatingTitle.ACB_RC },
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_Z },
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_Eighteen },
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.RP, AgeRatingTitle.AO },
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_Eighteen },
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Eighteen},
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_18}
};
readonly static AgeGroupItem Mature_Item = new AgeGroupItem{
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_M, AgeRatingTitle.ACB_MA15 },
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_C, AgeRatingTitle.CERO_D },
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_Sixteen },
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.M },
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_Fifteen },
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Sixteen},
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_16}
};
readonly static AgeGroupItem Teen_Item = new AgeGroupItem{
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_PG },
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_B },
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_Twelve, AgeRatingTitle.CLASS_IND_Fourteen },
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.T },
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_Twelve },
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Twelve},
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_12}
};
readonly static AgeGroupItem Child_Item = new AgeGroupItem{
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_G },
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_A },
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_L, AgeRatingTitle.CLASS_IND_Ten },
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.E, AgeRatingTitle.E10 },
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_All },
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Three, AgeRatingTitle.Seven},
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_0, AgeRatingTitle.USK_6}
};
public class AgeGroupItem
{
public List<IGDB.Models.AgeRatingTitle> ACB { get; set; }
public List<IGDB.Models.AgeRatingTitle> CERO { get; set; }
public List<IGDB.Models.AgeRatingTitle> CLASS_IND { get; set; }
public List<IGDB.Models.AgeRatingTitle> ESRB { get; set; }
public List<IGDB.Models.AgeRatingTitle> GRAC { get; set; }
public List<IGDB.Models.AgeRatingTitle> PEGI { get; set; }
public List<IGDB.Models.AgeRatingTitle> USK { get; set; }
[JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
public List<long> AgeGroupItemValues
{
get
{
List<long> values = new List<long>();
{
foreach (AgeRatingTitle ageRatingTitle in ACB)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in CERO)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in CLASS_IND)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in ESRB)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in GRAC)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in PEGI)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in USK)
{
values.Add((long)ageRatingTitle);
}
}
return values;
}
}
}
}
}

View File

@@ -186,158 +186,6 @@ namespace gaseous_server.Classes.Metadata
} }
} }
} }
public class AgeGroups
{
public AgeGroups()
{
}
public static Dictionary<AgeRestrictionGroupings, List<AgeGroupItem>> AgeGroupings
{
get
{
return new Dictionary<AgeRestrictionGroupings, List<AgeGroupItem>>{
{
AgeRestrictionGroupings.Adult, new List<AgeGroupItem>{ Adult_Item, Mature_Item, Teen_Item, Child_Item }
},
{
AgeRestrictionGroupings.Mature, new List<AgeGroupItem>{ Mature_Item, Teen_Item, Child_Item }
},
{
AgeRestrictionGroupings.Teen, new List<AgeGroupItem>{ Teen_Item, Child_Item }
},
{
AgeRestrictionGroupings.Child, new List<AgeGroupItem>{ Child_Item }
}
};
}
}
public static Dictionary<AgeRestrictionGroupings, AgeGroupItem> AgeGroupingsFlat
{
get
{
return new Dictionary<AgeRestrictionGroupings, AgeGroupItem>{
{
AgeRestrictionGroupings.Adult, Adult_Item
},
{
AgeRestrictionGroupings.Mature, Mature_Item
},
{
AgeRestrictionGroupings.Teen, Teen_Item
},
{
AgeRestrictionGroupings.Child, Child_Item
}
};
}
}
public enum AgeRestrictionGroupings
{
Adult = 4,
Mature = 3,
Teen = 2,
Child = 1,
Unclassified = 0
}
readonly static AgeGroupItem Adult_Item = new AgeGroupItem{
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_R18, AgeRatingTitle.ACB_RC },
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_Z },
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_Eighteen },
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.RP, AgeRatingTitle.AO },
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_Eighteen },
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Eighteen},
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_18}
};
readonly static AgeGroupItem Mature_Item = new AgeGroupItem{
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_M, AgeRatingTitle.ACB_MA15 },
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_C, AgeRatingTitle.CERO_D },
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_Sixteen },
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.M },
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_Fifteen },
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Sixteen},
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_16}
};
readonly static AgeGroupItem Teen_Item = new AgeGroupItem{
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_PG },
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_B },
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_Twelve, AgeRatingTitle.CLASS_IND_Fourteen },
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.T },
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_Twelve },
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Twelve},
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_12}
};
readonly static AgeGroupItem Child_Item = new AgeGroupItem{
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_G },
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_A },
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_L, AgeRatingTitle.CLASS_IND_Ten },
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.E, AgeRatingTitle.E10 },
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_All },
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Three, AgeRatingTitle.Seven},
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_0, AgeRatingTitle.USK_6}
};
public class AgeGroupItem
{
public List<IGDB.Models.AgeRatingTitle> ACB { get; set; }
public List<IGDB.Models.AgeRatingTitle> CERO { get; set; }
public List<IGDB.Models.AgeRatingTitle> CLASS_IND { get; set; }
public List<IGDB.Models.AgeRatingTitle> ESRB { get; set; }
public List<IGDB.Models.AgeRatingTitle> GRAC { get; set; }
public List<IGDB.Models.AgeRatingTitle> PEGI { get; set; }
public List<IGDB.Models.AgeRatingTitle> USK { get; set; }
[JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
public List<long> AgeGroupItemValues
{
get
{
List<long> values = new List<long>();
{
foreach (AgeRatingTitle ageRatingTitle in ACB)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in CERO)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in CLASS_IND)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in ESRB)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in GRAC)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in PEGI)
{
values.Add((long)ageRatingTitle);
}
foreach (AgeRatingTitle ageRatingTitle in USK)
{
values.Add((long)ageRatingTitle);
}
}
return values;
}
}
}
}
} }
} }

View File

@@ -114,7 +114,9 @@ namespace gaseous_server.Classes.Metadata
} }
return returnValue; return returnValue;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
return Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);
UpdateSubClasses(returnValue, false, false);
return returnValue;
default: default:
throw new Exception("How did you get here?"); throw new Exception("How did you get here?");
} }
@@ -125,7 +127,14 @@ namespace gaseous_server.Classes.Metadata
// required metadata // required metadata
if (Game.Cover != null) if (Game.Cover != null)
{ {
Cover GameCover = Covers.GetCover(Game.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game)); try
{
Cover GameCover = Covers.GetCover(Game.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
}
catch (Exception ex)
{
Logging.Log(Logging.LogType.Critical, "Game Metadata", "Unable to fetch cover artwork.", ex);
}
} }
if (Game.Genres != null) if (Game.Genres != null)
@@ -175,6 +184,7 @@ namespace gaseous_server.Classes.Metadata
AgeRating GameAgeRating = AgeRatings.GetAgeRatings(AgeRatingId); AgeRating GameAgeRating = AgeRatings.GetAgeRatings(AgeRatingId);
} }
} }
AgeGroups.GetAgeGroup(Game);
if (Game.ReleaseDates != null) if (Game.ReleaseDates != null)
{ {
@@ -199,7 +209,14 @@ namespace gaseous_server.Classes.Metadata
{ {
foreach (long ArtworkId in Game.Artworks.Ids) foreach (long ArtworkId in Game.Artworks.Ids)
{ {
Artwork GameArtwork = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game)); try
{
Artwork GameArtwork = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
}
catch (Exception ex)
{
Logging.Log(Logging.LogType.Critical, "Game Metadata", "Unable to fetch artwork id: " + ArtworkId, ex);
}
} }
} }
@@ -266,7 +283,14 @@ namespace gaseous_server.Classes.Metadata
{ {
foreach (long ScreenshotId in Game.Screenshots.Ids) foreach (long ScreenshotId in Game.Screenshots.Ids)
{ {
try
{
Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game)); Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
}
catch (Exception ex)
{
Logging.Log(Logging.LogType.Critical, "Game Metadata", "Unable to fetch screenshot id: " + ScreenshotId, ex);
}
} }
} }
@@ -307,6 +331,37 @@ namespace gaseous_server.Classes.Metadata
ids: platformIds.ToArray<long>() ids: platformIds.ToArray<long>()
); );
// get cover art from parent if this has no cover
if (result.Cover == null)
{
if (result.ParentGame != null)
{
if (result.ParentGame.Id != null)
{
Logging.Log(Logging.LogType.Information, "Game Metadata", "Game has no cover art, fetching cover art from parent game");
Game parentGame = GetGame((long)result.ParentGame.Id, false, false, false);
result.Cover = parentGame.Cover;
}
}
}
// get missing metadata from parent if this is a port
if (result.Category == Category.Port)
{
if (result.Summary == null)
{
if (result.ParentGame != null)
{
if (result.ParentGame.Id != null)
{
Logging.Log(Logging.LogType.Information, "Game Metadata", "Game has no summary, fetching summary from parent game");
Game parentGame = GetGame((long)result.ParentGame.Id, false, false, false);
result.Summary = parentGame.Summary;
}
}
}
}
return result; return result;
} }
@@ -324,37 +379,112 @@ namespace gaseous_server.Classes.Metadata
} }
} }
private static bool AllowNoPlatformSearch = false;
public static Game[] SearchForGame(string SearchString, long PlatformId, SearchType searchType) public static Game[] SearchForGame(string SearchString, long PlatformId, SearchType searchType)
{ {
Task<Game[]> games = _SearchForGame(SearchString, PlatformId, searchType); // search local first
Logging.Log(Logging.LogType.Information, "Game Search", "Attempting local search of type '" + searchType.ToString() + "' for " + SearchString);
Task<Game[]> games = _SearchForGameDatabase(SearchString, PlatformId, searchType);
if (games.Result.Length == 0)
{
// fall back to online search
Logging.Log(Logging.LogType.Information, "Game Search", "Falling back to remote search of type '" + searchType.ToString() + "' for " + SearchString);
games = _SearchForGameRemote(SearchString, PlatformId, searchType);
}
return games.Result; return games.Result;
} }
private static async Task<Game[]> _SearchForGame(string SearchString, long PlatformId, SearchType searchType) private static async Task<Game[]> _SearchForGameDatabase(string SearchString, long PlatformId, SearchType searchType)
{ {
string searchBody = ""; string whereClause = "";
string searchFields = "fields id,name,slug,platforms,summary; "; Dictionary<string, object> dbDict = new Dictionary<string, object>();
bool allowSearch = true;
switch (searchType) switch (searchType)
{ {
case SearchType.searchNoPlatform: case SearchType.searchNoPlatform:
searchBody += "search \"" + SearchString + "\"; "; whereClause = "MATCH(`Name`) AGAINST (@gamename)";
dbDict.Add("platformid", PlatformId);
dbDict.Add("gamename", SearchString);
allowSearch = AllowNoPlatformSearch;
break; break;
case SearchType.search: case SearchType.search:
searchBody += "search \"" + SearchString + "\"; "; whereClause = "PlatformsId = @platformid AND MATCH(`Name`) AGAINST (@gamename)";
searchBody += "where platforms = (" + PlatformId + ");"; dbDict.Add("platformid", PlatformId);
dbDict.Add("gamename", SearchString);
break; break;
case SearchType.wherefuzzy: case SearchType.wherefuzzy:
searchBody += "where platforms = (" + PlatformId + ") & name ~ *\"" + SearchString + "\"*;"; whereClause = "PlatformsId = @platformid AND `Name` LIKE @gamename";
dbDict.Add("platformid", PlatformId);
dbDict.Add("gamename", "%" + SearchString + "%");
break; break;
case SearchType.where: case SearchType.where:
searchBody += "where platforms = (" + PlatformId + ") & name ~ \"" + SearchString + "\";"; whereClause = "PlatformsId = @platformid AND `Name` = @gamename";
dbDict.Add("platformid", PlatformId);
dbDict.Add("gamename", SearchString);
break;
}
string sql = "SELECT Game.Id, Game.`Name`, Game.Slug, Relation_Game_Platforms.PlatformsId AS PlatformsId, Game.Summary FROM gaseous.Game JOIN Relation_Game_Platforms ON Game.Id = Relation_Game_Platforms.GameId WHERE " + whereClause + ";";
// get Game metadata
Game[]? results = new Game[0];
if (allowSearch == true)
{
List<Game> searchResults = new List<Game>();
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
DataTable data = db.ExecuteCMD(sql, dbDict);
foreach (DataRow row in data.Rows)
{
Game game = new Game{
Id = (long)row["Id"],
Name = (string)row["Name"],
Slug = (string)row["Slug"],
Summary = (string)row["Summary"]
};
searchResults.Add(game);
}
results = searchResults.ToArray();
}
return results;
}
private static async Task<Game[]> _SearchForGameRemote(string SearchString, long PlatformId, SearchType searchType)
{
string searchBody = "";
string searchFields = "fields id,name,slug,platforms,summary; ";
bool allowSearch = true;
switch (searchType)
{
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; break;
} }
// get Game metadata // get Game metadata
Communications comms = new Communications(); Communications comms = new Communications();
var results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody); Game[]? results = new Game[0];
if (allowSearch == true)
{
results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody);
}
return results; return results;
} }
@@ -377,6 +507,7 @@ namespace gaseous_server.Classes.Metadata
this.TotalRatingCount = gameObject.TotalRatingCount; this.TotalRatingCount = gameObject.TotalRatingCount;
this.Cover = gameObject.Cover; this.Cover = gameObject.Cover;
this.Artworks = gameObject.Artworks; this.Artworks = gameObject.Artworks;
this.FirstReleaseDate = gameObject.FirstReleaseDate;
// compile age ratings // compile age ratings
this.AgeRatings = new List<AgeRating>(); this.AgeRatings = new List<AgeRating>();
@@ -397,6 +528,7 @@ namespace gaseous_server.Classes.Metadata
public string Name { get; set; } public string Name { get; set; }
public double? TotalRating { get; set; } public double? TotalRating { get; set; }
public int? TotalRatingCount { get; set; } public int? TotalRatingCount { get; set; }
public DateTimeOffset? FirstReleaseDate { get; set; }
public IGDB.IdentityOrValue<IGDB.Models.Cover> Cover { get; set; } public IGDB.IdentityOrValue<IGDB.Models.Cover> Cover { get; set; }
public IGDB.IdentitiesOrValues<IGDB.Models.Artwork> Artworks { get; set; } public IGDB.IdentitiesOrValues<IGDB.Models.Artwork> Artworks { get; set; }
public List<IGDB.Models.AgeRating> AgeRatings { get; set; } public List<IGDB.Models.AgeRating> AgeRatings { get; set; }

View File

@@ -372,9 +372,12 @@ namespace gaseous_server.Classes.Metadata
case "[igdb.models.releasedateregion": case "[igdb.models.releasedateregion":
property.SetValue(EndpointType, (ReleaseDateRegion)dataRow[property.Name]); property.SetValue(EndpointType, (ReleaseDateRegion)dataRow[property.Name]);
break; break;
case "[igdb.models.releasedatecategory": case "[igdb.models.releasedatecategory":
property.SetValue(EndpointType, (ReleaseDateCategory)dataRow[property.Name]); property.SetValue(EndpointType, (ReleaseDateCategory)dataRow[property.Name]);
break; break;
case "[gaseous_server.classes.metadata.agegroups+agerestrictiongroupings":
property.SetValue(EndpointType, (AgeGroups.AgeRestrictionGroupings)dataRow[property.Name]);
break;
default: default:
property.SetValue(EndpointType, dataRow[property.Name]); property.SetValue(EndpointType, dataRow[property.Name]);
break; break;

View File

@@ -3,6 +3,7 @@ using System.Data;
using gaseous_signature_parser.models.RomSignatureObject; using gaseous_signature_parser.models.RomSignatureObject;
using static gaseous_server.Classes.RomMediaGroup; using static gaseous_server.Classes.RomMediaGroup;
using gaseous_server.Classes.Metadata; using gaseous_server.Classes.Metadata;
using IGDB.Models;
namespace gaseous_server.Classes namespace gaseous_server.Classes
{ {
@@ -14,7 +15,7 @@ namespace gaseous_server.Classes
{} {}
} }
public static GameRomObject GetRoms(long GameId, long PlatformId = -1) public static GameRomObject GetRoms(long GameId, long PlatformId = -1, int pageNumber = 0, int pageSize = 0)
{ {
GameRomObject GameRoms = new GameRomObject(); GameRomObject GameRoms = new GameRomObject();
@@ -24,23 +25,43 @@ namespace gaseous_server.Classes
dbDict.Add("id", GameId); dbDict.Add("id", GameId);
if (PlatformId == -1) { if (PlatformId == -1) {
sql = "SELECT * FROM Games_Roms WHERE GameId = @id ORDER BY `Name`"; sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id ORDER BY Platform.`Name`, Games_Roms.`Name`";
} else { } else {
sql = "SELECT * FROM Games_Roms WHERE GameId = @id AND PlatformId = @platformid ORDER BY `Name`"; sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid ORDER BY Platform.`Name`, Games_Roms.`Name`";
dbDict.Add("platformid", PlatformId); dbDict.Add("platformid", PlatformId);
} }
DataTable romDT = db.ExecuteCMD(sql, dbDict); DataTable romDT = db.ExecuteCMD(sql, dbDict);
if (romDT.Rows.Count > 0) if (romDT.Rows.Count > 0)
{ {
foreach (DataRow romDR in romDT.Rows) // set count of roms
GameRoms.Count = romDT.Rows.Count;
// setup platforms list
Dictionary<long, string> platformDict = new Dictionary<long, string>();
int pageOffset = pageSize * (pageNumber - 1);
for (int i = 0; i < romDT.Rows.Count; i++)
{ {
GameRoms.GameRomItems.Add(BuildRom(romDR)); GameRomItem gameRomItem = BuildRom(romDT.Rows[i]);
if ((i >= pageOffset && i < pageOffset + pageSize) || pageSize == 0)
{
GameRoms.GameRomItems.Add(gameRomItem);
}
if (!platformDict.ContainsKey(gameRomItem.PlatformId))
{
platformDict.Add(gameRomItem.PlatformId, gameRomItem.Platform);
}
} }
// get rom media groups // get rom media groups
GameRoms.MediaGroups = Classes.RomMediaGroup.GetMediaGroupsFromGameId(GameId); GameRoms.MediaGroups = Classes.RomMediaGroup.GetMediaGroupsFromGameId(GameId);
// sort the platforms
GameRoms.Platforms = platformDict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value).ToList<KeyValuePair<long, string>>();
return GameRoms; return GameRoms;
} }
else else
@@ -52,7 +73,7 @@ namespace gaseous_server.Classes
public static GameRomItem GetRom(long RomId) public static GameRomItem GetRom(long RomId)
{ {
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT * FROM Games_Roms WHERE Id = @id"; string sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.Id = @id";
Dictionary<string, object> dbDict = new Dictionary<string, object>(); Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", RomId); dbDict.Add("id", RomId);
DataTable romDT = db.ExecuteCMD(sql, dbDict); DataTable romDT = db.ExecuteCMD(sql, dbDict);
@@ -114,7 +135,7 @@ namespace gaseous_server.Classes
{ {
Id = (long)romDR["id"], Id = (long)romDR["id"],
PlatformId = (long)romDR["platformid"], PlatformId = (long)romDR["platformid"],
Platform = Classes.Metadata.Platforms.GetPlatform((long)romDR["platformid"]), Platform = (string)romDR["platformname"],
GameId = (long)romDR["gameid"], GameId = (long)romDR["gameid"],
Name = (string)romDR["name"], Name = (string)romDR["name"],
Size = (long)romDR["size"], Size = (long)romDR["size"],
@@ -151,13 +172,15 @@ namespace gaseous_server.Classes
{ {
public List<GameRomMediaGroupItem> MediaGroups { get; set; } = new List<GameRomMediaGroupItem>(); public List<GameRomMediaGroupItem> MediaGroups { get; set; } = new List<GameRomMediaGroupItem>();
public List<GameRomItem> GameRomItems { get; set; } = new List<GameRomItem>(); public List<GameRomItem> GameRomItems { get; set; } = new List<GameRomItem>();
public int Count { get; set; }
public List<KeyValuePair<long, string>> Platforms { get; set; }
} }
public class GameRomItem public class GameRomItem
{ {
public long Id { get; set; } public long Id { get; set; }
public long PlatformId { get; set; } public long PlatformId { get; set; }
public IGDB.Models.Platform Platform { get; set; } public string Platform { get; set; }
//public Dictionary<string, object>? Emulator { get; set; } //public Dictionary<string, object>? Emulator { get; set; }
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; } public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
public long GameId { get; set; } public long GameId { get; set; }

View File

@@ -870,13 +870,13 @@ namespace gaseous_server.Controllers
[ProducesResponseType(typeof(Classes.Roms.GameRomObject), StatusCodes.Status200OK)] [ProducesResponseType(typeof(Classes.Roms.GameRomObject), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
//[ResponseCache(CacheProfileName = "5Minute")] //[ResponseCache(CacheProfileName = "5Minute")]
public ActionResult GameRom(long GameId) public ActionResult GameRom(long GameId, int pageNumber = 0, int pageSize = 0, long PlatformId = -1)
{ {
try try
{ {
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false); Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
return Ok(Classes.Roms.GetRoms(GameId)); return Ok(Classes.Roms.GetRoms(GameId, PlatformId, pageNumber, pageSize));
} }
catch catch
{ {

View File

@@ -103,7 +103,7 @@ namespace gaseous_server.Controllers
"var AgeRatingStrings = " + JsonSerializer.Serialize(AgeRatingsStrings, new JsonSerializerOptions{ "var AgeRatingStrings = " + JsonSerializer.Serialize(AgeRatingsStrings, new JsonSerializerOptions{
WriteIndented = true WriteIndented = true
}) + ";" + Environment.NewLine + }) + ";" + Environment.NewLine +
"var AgeRatingGroups = " + JsonSerializer.Serialize(AgeRatings.AgeGroups.AgeGroupingsFlat, new JsonSerializerOptions{ "var AgeRatingGroups = " + JsonSerializer.Serialize(AgeGroups.AgeGroupingsFlat, new JsonSerializerOptions{
WriteIndented = true WriteIndented = true
}) + ";"; }) + ";";
byte[] bytes = Encoding.UTF8.GetBytes(ver); byte[] bytes = Encoding.UTF8.GetBytes(ver);

View File

@@ -52,15 +52,22 @@ namespace gaseous_server.Controllers
NormalizedEmail = model.Email.ToUpper(), NormalizedEmail = model.Email.ToUpper(),
SecurityProfile = new SecurityProfileViewModel() SecurityProfile = new SecurityProfileViewModel()
}; };
Logging.Log(Logging.LogType.Information, "First Run", "Creating new account " + model.Email);
var result = await _userManager.CreateAsync(user, model.Password); var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded) if (result.Succeeded)
{ {
Logging.Log(Logging.LogType.Information, "First Run", "Creation of " + model.Email + " successful.");
Logging.Log(Logging.LogType.Information, "First Run", "Adding Player role to " + model.Email);
await _userManager.AddToRoleAsync(user, "Player"); await _userManager.AddToRoleAsync(user, "Player");
Logging.Log(Logging.LogType.Information, "First Run", "Adding Gamer role to " + model.Email);
await _userManager.AddToRoleAsync(user, "Gamer"); await _userManager.AddToRoleAsync(user, "Gamer");
Logging.Log(Logging.LogType.Information, "First Run", "Adding Admin role to " + model.Email);
await _userManager.AddToRoleAsync(user, "Admin"); await _userManager.AddToRoleAsync(user, "Admin");
Logging.Log(Logging.LogType.Information, "First Run", "Signing in as " + model.Email);
await _signInManager.SignInAsync(user, isPersistent: true); await _signInManager.SignInAsync(user, isPersistent: true);
Logging.Log(Logging.LogType.Information, "First Run", "Setting first run state to 1");
Config.SetSetting("FirstRunStatus", "1"); Config.SetSetting("FirstRunStatus", "1");
return Ok(result); return Ok(result);

View File

@@ -192,11 +192,14 @@ namespace gaseous_server.Controllers.v1_1
string tempVal = ""; string tempVal = "";
string nameWhereClause = "";
if (model.Name.Length > 0) if (model.Name.Length > 0)
{ {
tempVal = "`Name` LIKE @Name"; // tempVal = "`Name` LIKE @Name";
whereParams.Add("@Name", "%" + model.Name + "%"); // whereParams.Add("@Name", "%" + model.Name + "%");
havingClauses.Add(tempVal); // havingClauses.Add(tempVal);
nameWhereClause = "WHERE (MATCH(Game.`Name`) AGAINST (@Name IN BOOLEAN MODE) OR MATCH(AlternativeName.`Name`) AGAINST (@Name IN BOOLEAN MODE))";
whereParams.Add("@Name", "(*" + model.Name + "*) (" + model.Name + ") ");
} }
if (model.GameRating != null) if (model.GameRating != null)
@@ -263,9 +266,10 @@ namespace gaseous_server.Controllers.v1_1
} }
} }
string platformWhereClause = "";
if (model.Platform.Count > 0) if (model.Platform.Count > 0)
{ {
tempVal = "Relation_Game_Platforms.PlatformsId IN ("; tempVal = " AND Games_Roms.PlatformId IN (";
for (int i = 0; i < model.Platform.Count; i++) for (int i = 0; i < model.Platform.Count; i++)
{ {
if (i > 0) if (i > 0)
@@ -277,7 +281,8 @@ namespace gaseous_server.Controllers.v1_1
whereParams.Add(platformLabel, model.Platform[i]); whereParams.Add(platformLabel, model.Platform[i]);
} }
tempVal += ")"; tempVal += ")";
whereClauses.Add(tempVal); //whereClauses.Add(tempVal);
platformWhereClause = tempVal;
} }
if (model.Genre.Count > 0) if (model.Genre.Count > 0)
@@ -352,7 +357,7 @@ namespace gaseous_server.Controllers.v1_1
{ {
if (model.GameAgeRating.AgeGroupings.Count > 0) if (model.GameAgeRating.AgeGroupings.Count > 0)
{ {
tempVal = "(AgeGroupId IN ("; tempVal = "(Game.AgeGroupId IN (";
for (int i = 0; i < model.GameAgeRating.AgeGroupings.Count; i++) for (int i = 0; i < model.GameAgeRating.AgeGroupings.Count; i++)
{ {
if (i > 0) if (i > 0)
@@ -367,7 +372,7 @@ namespace gaseous_server.Controllers.v1_1
if (model.GameAgeRating.IncludeUnrated == true) if (model.GameAgeRating.IncludeUnrated == true)
{ {
tempVal += " OR AgeGroupId IS NULL"; tempVal += " OR Game.AgeGroupId IS NULL";
} }
tempVal += ")"; tempVal += ")";
@@ -439,7 +444,9 @@ namespace gaseous_server.Controllers.v1_1
string orderByClause = "ORDER BY `" + orderByField + "` " + orderByOrder; string orderByClause = "ORDER BY `" + orderByField + "` " + orderByOrder;
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT DISTINCT view_Games.* FROM view_Games LEFT JOIN Relation_Game_Platforms ON view_Games.Id = Relation_Game_Platforms.GameId AND (Relation_Game_Platforms.PlatformsId IN (SELECT DISTINCT PlatformId FROM Games_Roms WHERE Games_Roms.GameId = view_Games.Id)) LEFT JOIN Relation_Game_Genres ON view_Games.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON view_Games.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON view_Games.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON view_Games.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause; //string sql = "SELECT DISTINCT view_Games.* FROM view_Games LEFT JOIN Relation_Game_Platforms ON view_Games.Id = Relation_Game_Platforms.GameId AND (Relation_Game_Platforms.PlatformsId IN (SELECT DISTINCT PlatformId FROM Games_Roms WHERE Games_Roms.GameId = view_Games.Id)) LEFT JOIN Relation_Game_Genres ON view_Games.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON view_Games.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON view_Games.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON view_Games.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
string sql = "SELECT DISTINCT Game.Id, Game.`Name`, Game.NameThe, Game.PlatformId, Game.TotalRating, Game.TotalRatingCount, Game.Cover, Game.Artworks, Game.FirstReleaseDate, Game.Category, Game.ParentGame, Game.AgeRatings, Game.AgeGroupId, Game.RomCount 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, Games_Roms.PlatformId, AgeGroup.AgeGroupId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId" + platformWhereClause + " LEFT JOIN AlternativeName ON Game.Id = AlternativeName.Game " + nameWhereClause + " GROUP BY Game.Id HAVING RomCount > 0) Game LEFT JOIN Relation_Game_Genres ON Game.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON Game.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON Game.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON Game.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>(); List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>();
@@ -457,7 +464,8 @@ namespace gaseous_server.Controllers.v1_1
break; break;
} }
RetVal.Add(Classes.Metadata.Games.GetGame(dbResponse.Rows[i])); Game retGame = Storage.BuildCacheObject<Game>(new Game() , dbResponse.Rows[i]);
RetVal.Add(retGame);
} }
GameReturnPackage gameReturn = new GameReturnPackage(RecordCount, RetVal); GameReturnPackage gameReturn = new GameReturnPackage(RecordCount, RetVal);

View File

@@ -113,6 +113,7 @@ namespace gaseous_server
_CorrelationId = correlationId.ToString(); _CorrelationId = correlationId.ToString();
CallContext.SetData("CorrelationId", correlationId); CallContext.SetData("CorrelationId", correlationId);
CallContext.SetData("CallingProcess", _ItemType.ToString()); CallContext.SetData("CallingProcess", _ItemType.ToString());
CallContext.SetData("CallingUser", "System");
// log the start // log the start
Logging.Log(Logging.LogType.Debug, "Timered Event", "Executing " + _ItemType + " with correlation id " + _CorrelationId); Logging.Log(Logging.LogType.Debug, "Timered Event", "Executing " + _ItemType + " with correlation id " + _CorrelationId);
@@ -148,6 +149,7 @@ namespace gaseous_server
CallingQueueItem = this CallingQueueItem = this
}; };
// clean up
Classes.ImportGame.DeleteOrphanedDirectories(Config.LibraryConfiguration.LibraryImportDirectory); Classes.ImportGame.DeleteOrphanedDirectories(Config.LibraryConfiguration.LibraryImportDirectory);
_SaveLastRunTime = true; _SaveLastRunTime = true;

View File

@@ -297,20 +297,6 @@ using (var scope = app.Services.CreateScope())
} }
} }
app.Use(async (context, next) =>
{
// set the correlation id
string correlationId = Guid.NewGuid().ToString();
CallContext.SetData("CorrelationId", correlationId);
CallContext.SetData("CallingProcess", context.Request.Method + ": " + context.Request.Path);
context.Response.Headers.Add("x-correlation-id", correlationId.ToString());
await next();
});
app.UseAuthorization(); app.UseAuthorization();
app.UseDefaultFiles(); app.UseDefaultFiles();
@@ -322,6 +308,28 @@ app.UseStaticFiles(new StaticFileOptions
app.MapControllers(); app.MapControllers();
app.Use(async (context, next) =>
{
// set the correlation id
string correlationId = Guid.NewGuid().ToString();
CallContext.SetData("CorrelationId", correlationId);
CallContext.SetData("CallingProcess", context.Request.Method + ": " + context.Request.Path);
string userIdentity;
try
{
userIdentity = context.User.Claims.Where(x=>x.Type==System.Security.Claims.ClaimTypes.NameIdentifier).FirstOrDefault().Value;
}
catch
{
userIdentity = "";
}
CallContext.SetData("CallingUser", userIdentity);
context.Response.Headers.Add("x-correlation-id", correlationId.ToString());
await next();
});
// emergency password recovery if environment variable is set // emergency password recovery if environment variable is set
// process: // process:
// - set the environment variable "recoveraccount" to the email address of the account to be recovered // - set the environment variable "recoveraccount" to the email address of the account to be recovered

View File

@@ -0,0 +1,23 @@
CREATE OR REPLACE VIEW `view_Games` AS
SELECT
a.*, b.AgeGroupId
FROM
view_GamesWithRoms a
INNER JOIN
(SELECT
view_GamesWithRoms.Id,
MAX((SELECT
AgeGroupId
FROM
ClassificationMap
WHERE
RatingId = AgeRating.Rating)) AgeGroupId
FROM
view_GamesWithRoms
LEFT JOIN Relation_Game_AgeRatings ON view_GamesWithRoms.Id = Relation_Game_AgeRatings.GameId
LEFT JOIN AgeRating ON Relation_Game_AgeRatings.AgeRatingsId = AgeRating.Id
GROUP BY Id) b ON a.Id = b.Id
ORDER BY NameThe;
ALTER TABLE `ServerLogs`
ADD COLUMN `CallingUser` VARCHAR(255) NULL AFTER `CallingProcess`;

View File

@@ -0,0 +1,29 @@
CREATE TABLE `AgeGroup` (
`Id` BIGINT NOT NULL,
`GameId` BIGINT NULL,
`AgeGroupId` INT NULL,
`dateAdded` DATETIME NULL DEFAULT NULL,
`lastUpdated` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`Id`));
ALTER TABLE `AgeGroup`
ADD INDEX `id_GameId` (`GameId` ASC) VISIBLE,
ADD INDEX `id_AgeGroupId` (`AgeGroupId` ASC) VISIBLE;
ALTER TABLE `Game`
CHANGE COLUMN `Slug` `Slug` VARCHAR(255) NULL DEFAULT NULL;
CREATE OR REPLACE VIEW `view_Games` AS
SELECT
a.*, b.AgeGroupId
FROM
view_GamesWithRoms a
LEFT JOIN AgeGroup b ON b.GameId = a.Id
ORDER BY NameThe;
ALTER TABLE `Game`
ADD FULLTEXT INDEX `ft_Name` (`Name`) VISIBLE;
ALTER TABLE `AlternativeName`
ADD FULLTEXT INDEX `ft_Name` (`Name`) VISIBLE,
ADD INDEX `id_GameId` (`Game` ASC) VISIBLE;

View File

@@ -50,6 +50,8 @@
<None Remove="Support\Database\MySQL\gaseous-1007.sql" /> <None Remove="Support\Database\MySQL\gaseous-1007.sql" />
<None Remove="Support\Database\MySQL\gaseous-1008.sql" /> <None Remove="Support\Database\MySQL\gaseous-1008.sql" />
<None Remove="Support\Database\MySQL\gaseous-1009.sql" /> <None Remove="Support\Database\MySQL\gaseous-1009.sql" />
<None Remove="Support\Database\MySQL\gaseous-1010.sql" />
<None Remove="Support\Database\MySQL\gaseous-1011.sql" />
<None Remove="Classes\Metadata\" /> <None Remove="Classes\Metadata\" />
<None Remove="Assets\" /> <None Remove="Assets\" />
<None Remove="Assets\Ratings\" /> <None Remove="Assets\Ratings\" />
@@ -182,5 +184,7 @@
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1007.sql" /> <EmbeddedResource Include="Support\Database\MySQL\gaseous-1007.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1008.sql" /> <EmbeddedResource Include="Support\Database\MySQL\gaseous-1008.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1009.sql" /> <EmbeddedResource Include="Support\Database\MySQL\gaseous-1009.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1010.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1011.sql" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -71,11 +71,11 @@
</td> </td>
<td> <td>
<span id="collection_directorylayout_gaseous_label" name="collection_directorylayout_label"> <span id="collection_directorylayout_gaseous_label" name="collection_directorylayout_label">
<p>Standard layout: /&lt;IGDB Platform Slug&gt;/&lt;IGDB Game Slug&gt;/Game ROM's</p> <p>Standard layout: /&lt;IGDB Platform Slug&gt;/&lt;IGDB Game Slug&gt;/Game ROMs</p>
<p>Example: /genesis-slash-megadrive/sonic-the-hedgehog/Sonic the Hedgehog.smd</p> <p>Example: /genesis-slash-megadrive/sonic-the-hedgehog/Sonic the Hedgehog.smd</p>
</span> </span>
<span id="collection_directorylayout_retropie_label" style="display: none;" name="collection_directorylayout_label"> <span id="collection_directorylayout_retropie_label" style="display: none;" name="collection_directorylayout_label">
<p>RetroPie layout: /roms/&lt;RetroPie Platform Label&gt;/Game ROM's</p> <p>RetroPie layout: /roms/&lt;RetroPie Platform Label&gt;/Game ROMs</p>
<p>Example: /roms/megadrive/Sonic the Hedgehog.smd</p> <p>Example: /roms/megadrive/Sonic the Hedgehog.smd</p>
</span> </span>
</td> </td>

View File

@@ -120,9 +120,10 @@
ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables, 'GET', function (result) { ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables, 'GET', function (result) {
romData = result; romData = result;
console.log(romData);
document.getElementById('modal-heading').innerHTML = result.name; document.getElementById('modal-heading').innerHTML = result.name;
document.getElementById('rominfo_library').innerHTML = result.library.name; document.getElementById('rominfo_library').innerHTML = result.library.name;
document.getElementById('rominfo_platform').innerHTML = result.platform.name; document.getElementById('rominfo_platform').innerHTML = result.platform;
document.getElementById('rominfo_size').innerHTML = formatBytes(result.size, 2); document.getElementById('rominfo_size').innerHTML = formatBytes(result.size, 2);
document.getElementById('rominfo_type').innerHTML = getRomType(result.romType); document.getElementById('rominfo_type').innerHTML = getRomType(result.romType);
document.getElementById('rominfo_mediatype').innerHTML = result.romTypeMedia; document.getElementById('rominfo_mediatype').innerHTML = result.romTypeMedia;
@@ -132,7 +133,7 @@
document.getElementById('rominfo_signaturematch').innerHTML = result.source; document.getElementById('rominfo_signaturematch').innerHTML = result.source;
document.getElementById('rominfo_signaturetitle').innerHTML = result.signatureSourceGameTitle; document.getElementById('rominfo_signaturetitle').innerHTML = result.signatureSourceGameTitle;
document.getElementById('properties_fixplatform').innerHTML = "<option value='" + result.platform.id + "' selected='selected'>" + result.platform.name + "</option>"; document.getElementById('properties_fixplatform').innerHTML = "<option value='" + result.platformId + "' selected='selected'>" + result.platform + "</option>";
document.getElementById('properties_fixgame').innerHTML = "<option value='" + gameData.id + "' selected='selected'>" + gameData.name + "</option>"; document.getElementById('properties_fixgame').innerHTML = "<option value='" + gameData.id + "' selected='selected'>" + gameData.name + "</option>";
if (result.library.isDefaultLibrary == false) { if (result.library.isDefaultLibrary == false) {
@@ -196,40 +197,57 @@
} }
}); });
$('#properties_fixgame').select2({ $('#properties_fixplatform').on('select2:select', function (e) {
minimumInputLength: 3, var platformData = e.params.data;
templateResult: DropDownRenderGameOption, console.log(platformData);
ajax: {
url: '/api/v1.1/Search/Game',
data: function (params) {
fixplatform = $('#properties_fixplatform').select2('data');
var query = { var gameValue = $('#properties_fixgame').select2('data');
PlatformId: fixplatform[0].id, if (gameValue) {
SearchString: params.term console.log(gameValue[0]);
}
// Query parameters will be ?SearchString=[term] setFixGameDropDown();
return query;
},
processResults: function (data) {
var arr = [];
for (var i = 0; i < data.length; i++) {
arr.push({
id: data[i].id,
text: data[i].name,
cover: data[i].cover
});
}
return {
results: arr
};
}
} }
}); });
function setFixGameDropDown() {
$('#properties_fixgame').empty().select2({
minimumInputLength: 3,
placeholder: 'Game',
templateResult: DropDownRenderGameOption,
ajax: {
url: '/api/v1.1/Search/Game',
data: function (params) {
fixplatform = $('#properties_fixplatform').select2('data');
var query = {
PlatformId: fixplatform[0].id,
SearchString: params.term
}
// Query parameters will be ?SearchString=[term]
return query;
},
processResults: function (data) {
var arr = [];
for (var i = 0; i < data.length; i++) {
arr.push({
id: data[i].id,
text: data[i].name,
cover: data[i].cover,
releaseDate: data[i].firstReleaseDate
});
}
return {
results: arr
};
}
}
});
}
setFixGameDropDown();
function SaveFixedGame() { function SaveFixedGame() {
var fixplatform = $('#properties_fixplatform').select2('data'); var fixplatform = $('#properties_fixplatform').select2('data');
var fixgame = $('#properties_fixgame').select2('data'); var fixgame = $('#properties_fixgame').select2('data');

View File

@@ -50,7 +50,7 @@
</th> </th>
</tr> </tr>
<tr> <tr>
<th colspan="4"><h3>Games and ROM's</h3></td> <th colspan="4"><h3>Games and ROMs</h3></td>
</tr> </tr>
<tr class="romrow"> <tr class="romrow">
<td class="romcell">Play games</td> <td class="romcell">Play games</td>

View File

@@ -74,7 +74,7 @@
</div> </div>
<div id="gamesummaryroms"> <div id="gamesummaryroms">
<span id="rom_edit" class="romlink" onclick="DisplayROMCheckboxes(true);">Edit</span> <span id="rom_edit" class="romlink" onclick="DisplayROMCheckboxes(true);">Edit</span>
<h3>ROM's/Images</h3> <h3>ROMs/Images</h3>
<div id="rom_edit_panel" style="display: none;"> <div id="rom_edit_panel" style="display: none;">
<div id="rom_edit_panel_center"> <div id="rom_edit_panel_center">
<button id="rom_edit_delete" class="redbutton" onclick="deleteGameRoms();">Delete</button> <button id="rom_edit_delete" class="redbutton" onclick="deleteGameRoms();">Delete</button>
@@ -86,7 +86,7 @@
</div> </div>
</div> </div>
</div> </div>
<div id="gamesummarysimilar"> <div id="gamesummarysimilar" style="display: none;">
<h3>Similar Games</h3> <h3>Similar Games</h3>
<div id="gamesummarysimilarcontent"></div> <div id="gamesummarysimilarcontent"></div>
</div> </div>
@@ -365,6 +365,8 @@
var gameSummarySimilar = document.getElementById('gamesummarysimilar'); var gameSummarySimilar = document.getElementById('gamesummarysimilar');
ajaxCall('/api/v1.1/Games/' + gameId + '/Related', 'GET', function (result) { ajaxCall('/api/v1.1/Games/' + gameId + '/Related', 'GET', function (result) {
if (result.games.length > 0) { if (result.games.length > 0) {
gameSummarySimilar.removeAttribute('style');
var gameSummarySimilarContent = document.getElementById('gamesummarysimilar'); var gameSummarySimilarContent = document.getElementById('gamesummarysimilar');
for (var i = 0; i < result.games.length; i++) { for (var i = 0; i < result.games.length; i++) {
var similarObject = renderGameIcon(result.games[i], false, false, false, null, true); var similarObject = renderGameIcon(result.games[i], false, false, false, null, true);
@@ -382,28 +384,94 @@
}); });
// load roms // load roms
loadRoms(); loadRoms(false);
}); });
function loadRoms(displayCheckboxes) { function loadRoms(displayCheckboxes, pageNumber, selectedPlatform) {
if (!pageNumber) {
pageNumber = 1;
}
if (selectedPlatform == undefined) {
selectedPlatform = -1;
}
console.log(selectedPlatform);
var filterControlBlock = document.getElementById('games_library_controls');
if (filterControlBlock) {
filterControlBlock.remove();
}
var existingTable = document.getElementById('romtable'); var existingTable = document.getElementById('romtable');
if (existingTable) { if (existingTable) {
existingTable.remove(); existingTable.remove();
} }
var romPager = document.getElementById('romPaginator');
if (romPager) {
romPager.remove();
}
var existingMgTable = document.getElementById('mediagrouptable'); var existingMgTable = document.getElementById('mediagrouptable');
if (existingMgTable) { if (existingMgTable) {
existingMgTable.remove(); existingMgTable.remove();
} }
if (displayCheckboxes == undefined) {
if (document.getElementById('rom_edit_panel').style.display == 'none') {
displayCheckboxes = false;
} else {
displayCheckboxes = true;
}
}
var gameRoms = document.getElementById('gamesummaryroms'); var gameRoms = document.getElementById('gamesummaryroms');
ajaxCall('/api/v1.1/Games/' + gameId + '/roms', 'GET', function (result) { var pageSize = 20;
ajaxCall('/api/v1.1/Games/' + gameId + '/roms?pageNumber=' + pageNumber + '&pageSize=' + pageSize + '&platformId=' + selectedPlatform, 'GET', function (result) {
// display filter tools
var filterControls = document.createElement('div');
filterControls.id = "games_library_controls";
var platformFilterBlock = document.createElement('div');
platformFilterBlock.className = 'games_library_controlblock';
var platformFilterOpt = document.createElement('select');
platformFilterOpt.id = "platform_filter";
platformFilterOpt.setAttribute('onchange', 'loadRoms(' + undefined + ', ' + 1 + ', Number(document.getElementById("platform_filter").value));');
var platformFilterOptDefault = document.createElement('option');
platformFilterOptDefault.value = '-1';
platformFilterOptDefault.innerHTML = 'All Platforms';
if (selectedPlatform == -1) {
platformFilterOptDefault.selected = 'selected';
}
platformFilterOpt.appendChild(platformFilterOptDefault);
for (var i = 0; i < result.platforms.length; i++) {
var platformFilterOptValue = document.createElement('option');
platformFilterOptValue.value = result.platforms[i].key;
platformFilterOptValue.innerHTML = result.platforms[i].value;
if (selectedPlatform == Number(result.platforms[i].key)) {
platformFilterOptValue.selected = 'selected';
}
platformFilterOpt.appendChild(platformFilterOptValue);
}
platformFilterBlock.appendChild(platformFilterOpt);
filterControls.appendChild(platformFilterBlock);
var romCounter = document.createElement('div');
romCounter.className = 'games_library_controlblock';
romCounter.innerHTML = result.count + ' ROMs';
filterControls.appendChild(romCounter);
gameRoms.appendChild(filterControls);
if (result.gameRomItems) { if (result.gameRomItems) {
var gameRomItems = result.gameRomItems; var gameRomItems = result.gameRomItems;
var mediaGroups = result.mediaGroups; var mediaGroups = result.mediaGroups;
gameRomItems.sort((a, b) => a.platform.name.charCodeAt(0) - b.platform.name.charCodeAt(0)); // display roms
var newTable = document.createElement('table'); var newTable = document.createElement('table');
newTable.id = 'romtable'; newTable.id = 'romtable';
newTable.className = 'romtable'; newTable.className = 'romtable';
@@ -412,23 +480,21 @@
var lastPlatform = ''; var lastPlatform = '';
for (var i = 0; i < gameRomItems.length; i++) { for (var i = 0; i < gameRomItems.length; i++) {
if (gameRomItems[i].platform.name != lastPlatform) { if (gameRomItems[i].platform != lastPlatform) {
lastPlatform = gameRomItems[i].platform.name; lastPlatform = gameRomItems[i].platform;
var platformRow = document.createElement('tr'); var platformRow = document.createElement('tr');
var platformHeader = document.createElement('th'); var platformHeader = document.createElement('th');
platformHeader.setAttribute('colspan', 6); platformHeader.setAttribute('colspan', 6);
platformHeader.innerHTML = '<a href="#" onclick="ShowPlatformMappingDialog(' + gameRomItems[i].platform.id + ');" style="float: right; text-decoration: none;" class="romlink"><img src="/images/map.svg" class="banner_button_image banner_button_image_smaller" alt="Edit platform mapping" title="Edit platform mapping" /></a><a href="#" onclick="ShowCollectionDialog(' + gameRomItems[i].platform.id + ');" style="float: right; text-decoration: none;" class="romlink"><img src="/images/collections.svg" class="banner_button_image banner_button_image_smaller" alt="Add to collection" title="Add to collection" /></a>' + gameRomItems[i].platform.name; platformHeader.innerHTML = '<a href="#" onclick="ShowPlatformMappingDialog(' + gameRomItems[i].platformId + ');" style="float: right; text-decoration: none;" class="romlink"><img src="/images/map.svg" class="banner_button_image banner_button_image_smaller" alt="Edit platform mapping" title="Edit platform mapping" /></a><a href="#" onclick="ShowCollectionDialog(' + gameRomItems[i].platformId + ');" style="float: right; text-decoration: none;" class="romlink"><img src="/images/collections.svg" class="banner_button_image banner_button_image_smaller" alt="Add to collection" title="Add to collection" /></a>' + gameRomItems[i].platform;
platformRow.appendChild(platformHeader); platformRow.appendChild(platformHeader);
newTable.appendChild(platformRow); newTable.appendChild(platformRow);
} }
var launchButton = ''; var launchButton = '';
if (result.gameRomItems[i].emulator) { if (result.gameRomItems[i].emulator) {
if (gameRomItems[i].emulator.type) { if (gameRomItems[i].emulator.type) {
if (gameRomItems[i].emulator.type.length > 0) { if (gameRomItems[i].emulator.type.length > 0) {
launchButton = '<a href="/index.html?page=emulator&engine=' + gameRomItems[i].emulator.type + '&core=' + gameRomItems[i].emulator.core + '&platformid=' + gameRomItems[i].platform.id + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1.1/Games/' + gameId + '/roms/' + gameRomItems[i].id + '/' + encodeURIComponent(gameRomItems[i].name)) + '" class="romstart">Launch</a>'; launchButton = '<a href="/index.html?page=emulator&engine=' + gameRomItems[i].emulator.type + '&core=' + gameRomItems[i].emulator.core + '&platformid=' + gameRomItems[i].platformId + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1.1/Games/' + gameId + '/roms/' + gameRomItems[i].id + '/' + encodeURIComponent(gameRomItems[i].name)) + '" class="romstart">Launch</a>';
} }
} }
} }
@@ -451,6 +517,51 @@
DisplayROMCheckboxes(true); DisplayROMCheckboxes(true);
} }
if (result.count > pageSize) {
// draw pagination
var numOfPages = Math.ceil(result.count / pageSize);
var romPaginator = document.createElement('div');
romPaginator.id = 'romPaginator';
romPaginator.className = 'rom_pager';
// draw previous page button
var prevPage = document.createElement('span');
prevPage.className = 'rom_pager_number_disabled';
prevPage.innerHTML = '&lt;';
if (pageNumber != 1) {
prevPage.setAttribute('onclick', 'loadRoms(' + undefined + ', ' + (pageNumber - 1) + ', ' + selectedPlatform + ');');
prevPage.className = 'rom_pager_number';
}
romPaginator.appendChild(prevPage);
// draw page numbers
for (var i = 0; i < numOfPages; i++) {
var romPaginatorPage = document.createElement('span');
romPaginatorPage.className = 'rom_pager_number_disabled';
romPaginatorPage.innerHTML = (i + 1);
if ((i + 1) != pageNumber) {
romPaginatorPage.setAttribute('onclick', 'loadRoms(' + undefined + ', ' + (i + 1) + ', ' + selectedPlatform + ');');
romPaginatorPage.className = 'rom_pager_number';
}
romPaginator.appendChild(romPaginatorPage);
}
// draw next page button
var nextPage = document.createElement('span');
nextPage.className = 'rom_pager_number_disabled';
nextPage.innerHTML = '&gt;';
if (pageNumber != numOfPages) {
nextPage.setAttribute('onclick', 'loadRoms(' + undefined + ', ' + (pageNumber + 1) + ', ' + selectedPlatform + ');');
nextPage.className = 'rom_pager_number';
}
romPaginator.appendChild(nextPage);
gameRoms.appendChild(romPaginator);
}
// display media groups
var mediaGroupDiv = document.getElementById('gamesummarymediagroups'); var mediaGroupDiv = document.getElementById('gamesummarymediagroups');
if (mediaGroups.length == 0) { if (mediaGroups.length == 0) {
mediaGroupDiv.style.display = 'none'; mediaGroupDiv.style.display = 'none';
@@ -741,41 +852,57 @@
} }
}); });
$('#rom_edit_fixgame').select2({ $('#rom_edit_fixplatform').on('select2:select', function (e) {
minimumInputLength: 3, var platformData = e.params.data;
templateResult: DropDownRenderGameOption, console.log(platformData);
placeholder: "Game",
ajax: {
url: '/api/v1.1/Search/Game',
data: function (params) {
fixplatform = $('#rom_edit_fixplatform').select2('data');
var query = { var gameValue = $('#rom_edit_fixgame').select2('data');
PlatformId: fixplatform[0].id, if (gameValue) {
SearchString: params.term console.log(gameValue[0]);
}
// Query parameters will be ?SearchString=[term] setRomFixGameDropDown();
return query;
},
processResults: function (data) {
var arr = [];
for (var i = 0; i < data.length; i++) {
arr.push({
id: data[i].id,
text: data[i].name,
cover: data[i].cover
});
}
return {
results: arr
};
}
} }
}); });
function setRomFixGameDropDown() {
$('#rom_edit_fixgame').empty().select2({
minimumInputLength: 3,
templateResult: DropDownRenderGameOption,
placeholder: "Game",
ajax: {
url: '/api/v1.1/Search/Game',
data: function (params) {
fixplatform = $('#rom_edit_fixplatform').select2('data');
var query = {
PlatformId: fixplatform[0].id,
SearchString: params.term
}
// Query parameters will be ?SearchString=[term]
return query;
},
processResults: function (data) {
var arr = [];
for (var i = 0; i < data.length; i++) {
arr.push({
id: data[i].id,
text: data[i].name,
cover: data[i].cover,
releaseDate: data[i].firstReleaseDate
});
}
return {
results: arr
};
}
}
});
}
setRomFixGameDropDown();
var remapCallCounter = 0; var remapCallCounter = 0;
var remapCallCounterMax = 0; var remapCallCounterMax = 0;

View File

@@ -139,18 +139,25 @@
for (var i = 0; i < result.length; i++) { for (var i = 0; i < result.length; i++) {
lastStartIndex = result[i].id; lastStartIndex = result[i].id;
console.log(result[i]);
var surroundingRow = document.createElement('tbody');
surroundingRow.setAttribute('colspan', 4);
surroundingRow.className = 'logs_table_row_' + result[i].eventType;
var newRow = [ var newRow = [
//result[i].id,
moment(result[i].eventTime).format("YYYY-MM-DD h:mm:ss a"), moment(result[i].eventTime).format("YYYY-MM-DD h:mm:ss a"),
result[i].eventType, result[i].eventType,
result[i].process, result[i].process,
result[i].message result[i].message
]; ];
newTable.appendChild(createTableRow(false, newRow, 'logs_table_row_' + result[i].eventType, 'romcell logs_table_cell')); surroundingRow.appendChild(createTableRow(false, newRow, '', 'romcell logs_table_cell'));
// exception
var exceptionString = '';
if (result[i].exceptionValue) { if (result[i].exceptionValue) {
var exceptionString = "<h3>Exception</h3><pre class='logs_table_exception' style='width: 795px; word-wrap: break-word; overflow-wrap: break-word; overflow-y: scroll;'>" + syntaxHighlight(JSON.stringify(result[i].exceptionValue, null, 2)).replace(/\\n/g, "<br /> ") + "</pre>"; exceptionString = "<strong>Exception</strong><pre class='logs_table_exception' style='width: 795px; word-wrap: break-word; overflow-wrap: break-word; overflow-y: scroll;'>" + syntaxHighlight(JSON.stringify(result[i].exceptionValue, null, 2)).replace(/\\n/g, "<br /> ") + "</pre>";
var exRow = document.createElement('tr'); var exRow = document.createElement('tr');
var leadCell = document.createElement('td'); var leadCell = document.createElement('td');
exRow.appendChild(leadCell); exRow.appendChild(leadCell);
@@ -158,8 +165,59 @@
exCell.colSpan = '3'; exCell.colSpan = '3';
exCell.innerHTML = exceptionString; exCell.innerHTML = exceptionString;
exRow.appendChild(exCell); exRow.appendChild(exCell);
newTable.appendChild(exRow); surroundingRow.appendChild(exRow);
} }
// calling process
var infoRow = document.createElement('tr');
var infoRowEmptyCell = document.createElement('td');
infoRowEmptyCell.className = 'romcell';
var infoRowDataCell = document.createElement('td');
infoRowDataCell.className = 'romcell';
infoRowDataCell.setAttribute('colspan', 3);
infoRowDataCell.innerHTML = '<strong>Calling process:</strong> ' + result[i].callingProcess;
infoRow.appendChild(infoRowEmptyCell);
infoRow.appendChild(infoRowDataCell);
surroundingRow.appendChild(infoRow);
// initiated by user
if (result[i].callingUser) {
if (result[i].callingUser.length > 0) {
var infoRow3 = document.createElement('tr');
var infoRowEmptyCell3 = document.createElement('td');
infoRowEmptyCell3.className = 'romcell';
var infoRowDataCell3 = document.createElement('td');
infoRowDataCell3.className = 'romcell';
infoRowDataCell3.setAttribute('colspan', 3);
infoRowDataCell3.innerHTML = '<strong>User:</strong> ' + result[i].callingUser + "</a>";
infoRow3.appendChild(infoRowEmptyCell3);
infoRow3.appendChild(infoRowDataCell3);
surroundingRow.appendChild(infoRow3);
}
}
// correlation id
var infoRow2 = document.createElement('tr');
var infoRowEmptyCell2 = document.createElement('td');
infoRowEmptyCell2.className = 'romcell';
var infoRowDataCell2 = document.createElement('td');
infoRowDataCell2.className = 'romcell';
infoRowDataCell2.setAttribute('colspan', 3);
infoRowDataCell2.innerHTML = '<strong>Correlation Id:</strong> <a class="romlink" href="/index.html?page=settings&sub=logs&correlationid=' + result[i].correlationId + '">' + result[i].correlationId + "</a>";
infoRow2.appendChild(infoRowEmptyCell2);
infoRow2.appendChild(infoRowDataCell2);
surroundingRow.appendChild(infoRow2);
newTable.appendChild(surroundingRow);
} }
}, },
function (error) { function (error) {

View File

@@ -12,6 +12,8 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize) {
console.log("Displaying page: " + pageNumber); console.log("Displaying page: " + pageNumber);
console.log("Page size: " + pageSize); console.log("Page size: " + pageSize);
window.scrollTo(0, 0);
var pageMode = GetPreference('LibraryPagination', 'paged'); var pageMode = GetPreference('LibraryPagination', 'paged');
if (pageNumber == 1 || pageMode == 'paged') { if (pageNumber == 1 || pageMode == 'paged') {

View File

@@ -253,13 +253,18 @@ function DropDownRenderGameOption(state) {
var response; var response;
var releaseDate;
if (state.releaseDate) {
releaseDate = moment(state.releaseDate).format('yyyy');
}
if (state.cover) { if (state.cover) {
response = $( response = $(
'<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="https://images.igdb.com/igdb/image/upload/t_cover_small/' + state.cover.value.imageId + '.jpg" /></td><td class="dropdown-label"><span>' + state.text + '</span></td></tr></table>' '<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="https://images.igdb.com/igdb/image/upload/t_cover_small/' + state.cover.value.imageId + '.jpg" /></td><td class="dropdown-label"><span class="dropdown-title">' + state.text + '</span><span class="dropdown-releasedate">' + releaseDate + '</span></td></tr></table>'
); );
} else { } else {
response = $( response = $(
'<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="/images/unknowngame.png" /></td><td class="dropdown-label"><span>' + state.text + '</span></td></tr></table>' '<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="/images/unknowngame.png" style="max-width: 90px;" /></td><td class="dropdown-label"><span>' + state.text + '</span><span class="dropdown-releasedate">' + releaseDate + '</span></td></tr></table>'
); );
} }
return response; return response;

View File

@@ -335,6 +335,40 @@ input[id='filter_panel_userrating_max'] {
color: grey; color: grey;
} }
.rom_pager {
position: absolute;
left: 50%;
transform: translate(-50%, 0);
padding-left: 20px;
padding-right: 20px;
padding-top: 15px;
padding-bottom: 15px;
font-size: 16px;
font-family: Commodore64;
text-align: center;
width: 80%;
}
.rom_pager_number {
display: inline-block;
padding: 5px;
width: 40px;
text-align: center;
}
.rom_pager_number:hover {
background-color: blue;
cursor: pointer;
}
.rom_pager_number_disabled {
display: inline-block;
padding: 5px;
width: 40px;
text-align: center;
color: grey;
}
.filter_panel_item { .filter_panel_item {
display: flex; display: flex;
position: relative; position: relative;
@@ -524,6 +558,10 @@ input[id='filter_panel_userrating_max'] {
width: 250px; width: 250px;
} }
#gamesummaryroms {
position: relative;
}
.game_cover_image { .game_cover_image {
display: block; display: block;
max-width: 250px; max-width: 250px;
@@ -857,6 +895,18 @@ div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover
text-align: left; text-align: left;
} }
.dropdown-title {
display: block;
font-weight: bold;
margin-right: 5px;
}
.dropdown-releasedate {
display: block;
font-weight: normal;
color: lightgray;
}
button { button {
background-color: #555; background-color: #555;
color: white; color: white;