Compare commits

..

14 Commits

Author SHA1 Message Date
Michael Green
49784dc325 Removed import block from LibraryScan (#150) 2023-10-10 11:00:13 +11:00
Michael Green
fc09db60ab Updated the about page (#137) 2023-09-27 21:58:43 +10:00
Michael Green
906456782a Logs page now has paging (#136) 2023-09-25 21:22:27 +10:00
Michael Green
d6d6a5d808 Resolved blocked service UI bug (#134) 2023-09-24 13:59:01 +10:00
Michael Green
586f2c69d8 Fixed incorrect docker command (#132) 2023-09-23 17:09:07 -07:00
Michael Green
45e4666c51 EmulatorJS version bump (#131) 2023-09-24 09:57:44 +10:00
Michael Green
d94c921815 Add a list of available cores for each platform to the platform map (#130) 2023-09-23 16:14:04 -07:00
Michael Green
fff22ea8d9 Other processes should now be blocked during database upgrade processes (#128) 2023-09-22 23:42:24 +10:00
Michael Green
9b930b2a51 Fail safe when the IGDB connector experiences an exception (#127)
* Updated readme with database limitations

* Wrapped all IGDB calls (except search) in try catch blocks
2023-09-22 20:24:09 +10:00
Michael Green
a0408a1d1d Added EmulatorJS core selection help link (#124) 2023-09-20 12:07:25 +10:00
Michael Green
f2c58bb172 All uses of hashes should now be lower case (#122) 2023-09-20 09:32:40 +10:00
Michael Green
7eb418d6a2 Signature ingestor database update is now a background task (#121)
* Updated background task code to support options and self clearing

* Moved background safe database upgrade code to a background task
2023-09-20 00:35:24 +10:00
Michael Green
60fab488a2 Add internet exposure warning to the README #118 2023-09-19 11:57:31 +10:00
Michael Green
5a5a2f94fb Remove ‘and’ from end of Game Boy BIOS hash (#116) 2023-09-19 08:53:08 +10:00
50 changed files with 2359 additions and 370 deletions

View File

@@ -2,15 +2,25 @@
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 ROM's.
## Warning
This project is currently not suitable for being exposed to the internet.
1. there is currently no authentication support, meaning anyone could trash your library
2. the server has not been hardened for exposure to the internet - so there maybe unknown vulnerabilities
If you expose the server to the internet, **you do so at your own risk**.
## Screenshots ## Screenshots
![Library](./screenshots/Library.png) ![Library](./screenshots/Library.png)
![Game](./screenshots/Game.png) ![Game](./screenshots/Game.png)
![Emulator](./screenshots/Emulator.png) ![Emulator](./screenshots/Emulator.png)
## Requirements ## Requirements
* MySQL Server 8+ * MySQL Server 8+*
* Internet Game Database API Key. See: https://api-docs.igdb.com/#account-creation * Internet Game Database API Key. See: https://api-docs.igdb.com/#account-creation
***Note**: MariaDB is currently not supported as Gaseous uses features present only in MySQL. This is being tracked in https://github.com/gaseous-project/gaseous-server/issues/93
## Third Party Projects ## Third Party Projects
The following projects are used by Gaseous The following projects are used by Gaseous
* https://dotnet.microsoft.com/en-us/apps/aspnet * https://dotnet.microsoft.com/en-us/apps/aspnet
@@ -76,12 +86,12 @@ Dockerfile and docker-compose-build.yml files have been provided to make deploym
2. Change into the gaseous-server directory 2. Change into the gaseous-server directory
3. Clone the submodules with the command ```git submodule update --init``` 3. Clone the submodules with the command ```git submodule update --init```
4. Open the docker-compose-build.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account 4. Open the docker-compose-build.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
5. Run the command "docker-compose up --file docker-compose-build.yml -d" 5. Run the command ```docker-compose --file docker-compose-build.yml up -d```
6. Connect to the host on port 5198 6. Connect to the host on port 5198
## Source ## Source
### Build and deploy ### Build and deploy
1. Install and configure a MySQL or MariaDB instance 1. Install and configure a MySQL instance
2. Install the dotnet 7.0 packages appropriate for your operating system 2. Install the dotnet 7.0 packages appropriate for your operating system
* See: https://learn.microsoft.com/en-us/dotnet/core/install/linux * See: https://learn.microsoft.com/en-us/dotnet/core/install/linux
3. Create a database user with permission to create a databse. Gaseous will create the new database and apply the database schema on it's first startup. 3. Create a database user with permission to create a databse. Gaseous will create the new database and apply the database schema on it's first startup.

View File

@@ -79,7 +79,7 @@ namespace gaseous_server.Classes
platformname = platform.Name, platformname = platform.Name,
description = emulatorBios.description, description = emulatorBios.description,
filename = emulatorBios.filename, filename = emulatorBios.filename,
hash = emulatorBios.hash hash = emulatorBios.hash.ToLower()
}; };
biosItems.Add(biosItem); biosItems.Add(biosItem);
} }

View File

@@ -171,13 +171,10 @@ namespace gaseous_server.Classes
db.ExecuteCMD(sql, dbDict); db.ExecuteCMD(sql, dbDict);
// start background task // start background task
foreach (ProcessQueue.QueueItem qi in ProcessQueue.QueueItems) ProcessQueue.QueueItem queueItem = new ProcessQueue.QueueItem(ProcessQueue.QueueItemType.CollectionCompiler, 1, false, true);
{ queueItem.Options = Id;
if (qi.ItemType == ProcessQueue.QueueItemType.CollectionCompiler) { queueItem.ForceExecute();
qi.ForceExecute(); ProcessQueue.QueueItems.Add(queueItem);
break;
}
}
} }
} }
@@ -364,176 +361,173 @@ namespace gaseous_server.Classes
return collectionContents; return collectionContents;
} }
public static void CompileCollections() public static void CompileCollections(long CollectionId)
{ {
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
List<CollectionItem> collectionItems = GetCollections(); CollectionItem collectionItem = GetCollection(CollectionId);
foreach (CollectionItem collectionItem in collectionItems) if (collectionItem.BuildStatus == CollectionItem.CollectionBuildStatus.WaitingForBuild)
{ {
if (collectionItem.BuildStatus == CollectionItem.CollectionBuildStatus.WaitingForBuild) Logging.Log(Logging.LogType.Information, "Collections", "Beginning build of collection: " + collectionItem.Name);
// set starting
string sql = "UPDATE RomCollections SET BuiltStatus=@bs WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", collectionItem.Id);
dbDict.Add("bs", CollectionItem.CollectionBuildStatus.Building);
db.ExecuteCMD(sql, dbDict);
List<CollectionContents.CollectionPlatformItem> collectionPlatformItems = GetCollectionContent(collectionItem).Collection;
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, collectionItem.Id + ".zip");
string ZipFileTempPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, collectionItem.Id.ToString());
try
{ {
Logging.Log(Logging.LogType.Information, "Collections", "Beginning build of collection: " + collectionItem.Name);
// clean up if needed
// set starting if (File.Exists(ZipFilePath))
string sql = "UPDATE RomCollections SET BuiltStatus=@bs WHERE Id=@id";
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("id", collectionItem.Id);
dbDict.Add("bs", CollectionItem.CollectionBuildStatus.Building);
db.ExecuteCMD(sql, dbDict);
List<CollectionContents.CollectionPlatformItem> collectionPlatformItems = GetCollectionContent(collectionItem).Collection;
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, collectionItem.Id + ".zip");
string ZipFileTempPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, collectionItem.Id.ToString());
try
{ {
Logging.Log(Logging.LogType.Warning, "Collections", "Deleting existing build of collection: " + collectionItem.Name);
// clean up if needed File.Delete(ZipFilePath);
if (File.Exists(ZipFilePath)) }
{
Logging.Log(Logging.LogType.Warning, "Collections", "Deleting existing build of collection: " + collectionItem.Name);
File.Delete(ZipFilePath);
}
if (Directory.Exists(ZipFileTempPath)) if (Directory.Exists(ZipFileTempPath))
{ {
Directory.Delete(ZipFileTempPath, true); Directory.Delete(ZipFileTempPath, true);
} }
// gather collection files // gather collection files
Directory.CreateDirectory(ZipFileTempPath); Directory.CreateDirectory(ZipFileTempPath);
string ZipBiosPath = Path.Combine(ZipFileTempPath, "BIOS"); string ZipBiosPath = Path.Combine(ZipFileTempPath, "BIOS");
// get the games // get the games
foreach (CollectionContents.CollectionPlatformItem collectionPlatformItem in collectionPlatformItems) foreach (CollectionContents.CollectionPlatformItem collectionPlatformItem in collectionPlatformItems)
{
// get platform bios files if present
if (collectionItem.IncludeBIOSFiles == true)
{ {
// get platform bios files if present List<Bios.BiosItem> bios = Bios.GetBios(collectionPlatformItem.Id, true);
if (collectionItem.IncludeBIOSFiles == true) if (!Directory.Exists(ZipBiosPath)) {
Directory.CreateDirectory(ZipBiosPath);
}
foreach (Bios.BiosItem biosItem in bios)
{ {
List<Bios.BiosItem> bios = Bios.GetBios(collectionPlatformItem.Id, true); if (File.Exists(biosItem.biosPath))
if (!Directory.Exists(ZipBiosPath)) {
Directory.CreateDirectory(ZipBiosPath);
}
foreach (Bios.BiosItem biosItem in bios)
{ {
if (File.Exists(biosItem.biosPath)) Logging.Log(Logging.LogType.Information, "Collections", "Copying BIOS file: " + biosItem.filename);
{ File.Copy(biosItem.biosPath, Path.Combine(ZipBiosPath, biosItem.filename));
Logging.Log(Logging.LogType.Information, "Collections", "Copying BIOS file: " + biosItem.filename);
File.Copy(biosItem.biosPath, Path.Combine(ZipBiosPath, biosItem.filename));
}
} }
} }
}
// create platform directory // create platform directory
string ZipPlatformPath = ""; string ZipPlatformPath = "";
switch (collectionItem.FolderStructure) switch (collectionItem.FolderStructure)
{ {
case CollectionItem.FolderStructures.Gaseous: case CollectionItem.FolderStructures.Gaseous:
ZipPlatformPath = Path.Combine(ZipFileTempPath, collectionPlatformItem.Slug);
break;
case CollectionItem.FolderStructures.RetroPie:
try
{
PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(collectionPlatformItem.Id);
ZipPlatformPath = Path.Combine(ZipFileTempPath, "roms", platformMapItem.RetroPieDirectoryName);
}
catch
{
ZipPlatformPath = Path.Combine(ZipFileTempPath, collectionPlatformItem.Slug); ZipPlatformPath = Path.Combine(ZipFileTempPath, collectionPlatformItem.Slug);
break; }
case CollectionItem.FolderStructures.RetroPie: break;
try
{
PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(collectionPlatformItem.Id);
ZipPlatformPath = Path.Combine(ZipFileTempPath, "roms", platformMapItem.RetroPieDirectoryName);
}
catch
{
ZipPlatformPath = Path.Combine(ZipFileTempPath, collectionPlatformItem.Slug);
}
break; }
if (!Directory.Exists(ZipPlatformPath))
{
Directory.CreateDirectory(ZipPlatformPath);
}
} foreach (CollectionContents.CollectionPlatformItem.CollectionGameItem collectionGameItem in collectionPlatformItem.Games)
if (!Directory.Exists(ZipPlatformPath)) {
bool includeGame = false;
if (collectionGameItem.InclusionStatus == null)
{ {
Directory.CreateDirectory(ZipPlatformPath); includeGame = true;
} }
else
foreach (CollectionContents.CollectionPlatformItem.CollectionGameItem collectionGameItem in collectionPlatformItem.Games)
{ {
bool includeGame = false; if (collectionGameItem.InclusionStatus.InclusionState == CollectionItem.AlwaysIncludeStatus.AlwaysInclude)
if (collectionGameItem.InclusionStatus == null)
{ {
includeGame = true; includeGame = true;
} }
else }
{
if (collectionGameItem.InclusionStatus.InclusionState == CollectionItem.AlwaysIncludeStatus.AlwaysInclude)
{
includeGame = true;
}
}
if (includeGame == true) if (includeGame == true)
{
string ZipGamePath = "";
switch (collectionItem.FolderStructure)
{ {
string ZipGamePath = ""; case CollectionItem.FolderStructures.Gaseous:
switch (collectionItem.FolderStructure) // create game directory
{ ZipGamePath = Path.Combine(ZipPlatformPath, collectionGameItem.Slug);
case CollectionItem.FolderStructures.Gaseous: if (!Directory.Exists(ZipGamePath))
// create game directory
ZipGamePath = Path.Combine(ZipPlatformPath, collectionGameItem.Slug);
if (!Directory.Exists(ZipGamePath))
{
Directory.CreateDirectory(ZipGamePath);
}
break;
case CollectionItem.FolderStructures.RetroPie:
ZipGamePath = ZipPlatformPath;
break;
}
// copy in roms
foreach (Roms.GameRomItem gameRomItem in collectionGameItem.Roms)
{
if (File.Exists(gameRomItem.Path))
{ {
Logging.Log(Logging.LogType.Information, "Collections", "Copying ROM: " + gameRomItem.Name); Directory.CreateDirectory(ZipGamePath);
File.Copy(gameRomItem.Path, Path.Combine(ZipGamePath, gameRomItem.Name));
} }
break;
case CollectionItem.FolderStructures.RetroPie:
ZipGamePath = ZipPlatformPath;
break;
}
// copy in roms
foreach (Roms.GameRomItem gameRomItem in collectionGameItem.Roms)
{
if (File.Exists(gameRomItem.Path))
{
Logging.Log(Logging.LogType.Information, "Collections", "Copying ROM: " + gameRomItem.Name);
File.Copy(gameRomItem.Path, Path.Combine(ZipGamePath, gameRomItem.Name));
} }
} }
} }
} }
// compress to zip
Logging.Log(Logging.LogType.Information, "Collections", "Compressing collection");
ZipFile.CreateFromDirectory(ZipFileTempPath, ZipFilePath, CompressionLevel.SmallestSize, false);
// clean up
if (Directory.Exists(ZipFileTempPath))
{
Logging.Log(Logging.LogType.Information, "Collections", "Cleaning up");
Directory.Delete(ZipFileTempPath, true);
}
// set completed
dbDict["bs"] = CollectionItem.CollectionBuildStatus.Completed;
db.ExecuteCMD(sql, dbDict);
} }
catch (Exception ex)
// compress to zip
Logging.Log(Logging.LogType.Information, "Collections", "Compressing collection");
ZipFile.CreateFromDirectory(ZipFileTempPath, ZipFilePath, CompressionLevel.SmallestSize, false);
// clean up
if (Directory.Exists(ZipFileTempPath))
{ {
// clean up Logging.Log(Logging.LogType.Information, "Collections", "Cleaning up");
if (Directory.Exists(ZipFileTempPath)) Directory.Delete(ZipFileTempPath, true);
{
Directory.Delete(ZipFileTempPath, true);
}
if (File.Exists(ZipFilePath))
{
File.Delete(ZipFilePath);
}
// set failed
dbDict["bs"] = CollectionItem.CollectionBuildStatus.Failed;
db.ExecuteCMD(sql, dbDict);
Logging.Log(Logging.LogType.Critical, "Collection Builder", "Collection building has failed", ex);
} }
// set completed
dbDict["bs"] = CollectionItem.CollectionBuildStatus.Completed;
db.ExecuteCMD(sql, dbDict);
}
catch (Exception ex)
{
// clean up
if (Directory.Exists(ZipFileTempPath))
{
Directory.Delete(ZipFileTempPath, true);
}
if (File.Exists(ZipFilePath))
{
File.Delete(ZipFilePath);
}
// set failed
dbDict["bs"] = CollectionItem.CollectionBuildStatus.Failed;
db.ExecuteCMD(sql, dbDict);
Logging.Log(Logging.LogType.Critical, "Collection Builder", "Collection building has failed", ex);
} }
} }
} }

View File

@@ -77,10 +77,17 @@ namespace gaseous_server.Classes.Metadata
UpdateSubClasses(returnValue); UpdateSubClasses(returnValue);
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
UpdateSubClasses(returnValue); returnValue = await GetObjectFromServer(WhereClause);
break; Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<AgeRating>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<AgeRating>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<AgeRating>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -75,9 +75,17 @@ namespace gaseous_server.Classes.Metadata
Storage.NewCacheValue(returnValue); Storage.NewCacheValue(returnValue);
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
break; returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<AgeRatingContentDescription>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<AgeRatingContentDescription>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<AgeRatingContentDescription>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -75,9 +75,17 @@ namespace gaseous_server.Classes.Metadata
Storage.NewCacheValue(returnValue); Storage.NewCacheValue(returnValue);
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
break; returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<AlternativeName>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<AlternativeName>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<AlternativeName>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -78,10 +78,17 @@ namespace gaseous_server.Classes.Metadata
forceImageDownload = true; forceImageDownload = true;
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause, LogoPath); try
Storage.NewCacheValue(returnValue, true); {
forceImageDownload = true; returnValue = await GetObjectFromServer(WhereClause, LogoPath);
break; Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<Artwork>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Artwork>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<Artwork>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -75,9 +75,17 @@ namespace gaseous_server.Classes.Metadata
Storage.NewCacheValue(returnValue); Storage.NewCacheValue(returnValue);
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
break; returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<Collection>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Collection>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<Collection>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -74,9 +74,16 @@ namespace gaseous_server.Classes.Metadata
UpdateSubClasses(returnValue); UpdateSubClasses(returnValue);
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
if (returnValue != null) { Storage.NewCacheValue(returnValue, true); } {
UpdateSubClasses(returnValue); returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<Company>(returnValue, "id", (long)searchValue);
}
break; break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Company>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<Company>(returnValue, "id", (long)searchValue);

View File

@@ -80,12 +80,17 @@ namespace gaseous_server.Classes.Metadata
} }
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause, LogoPath); try
if (returnValue != null)
{ {
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
Storage.NewCacheValue(returnValue, true); Storage.NewCacheValue(returnValue, true);
forceImageDownload = true; forceImageDownload = true;
} }
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<CompanyLogo>(returnValue, "id", (long)searchValue);
}
break; break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<CompanyLogo>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<CompanyLogo>(returnValue, "id", (long)searchValue);

View File

@@ -77,10 +77,18 @@ namespace gaseous_server.Classes.Metadata
forceImageDownload = true; forceImageDownload = true;
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause, LogoPath); try
Storage.NewCacheValue(returnValue, true); {
forceImageDownload = true; returnValue = await GetObjectFromServer(WhereClause, LogoPath);
break; Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<Cover>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Cover>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<Cover>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -78,12 +78,17 @@ namespace gaseous_server.Classes.Metadata
} }
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
if (returnValue != null)
{ {
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true); Storage.NewCacheValue(returnValue, true);
} }
break; catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<ExternalGame>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<ExternalGame>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<ExternalGame>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -75,9 +75,17 @@ namespace gaseous_server.Classes.Metadata
Storage.NewCacheValue(returnValue); Storage.NewCacheValue(returnValue);
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
break; returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<Franchise>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Franchise>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<Franchise>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -68,18 +68,23 @@ namespace gaseous_server.Classes.Metadata
} }
GameMode returnValue = new GameMode(); GameMode returnValue = new GameMode();
bool forceImageDownload = false;
switch (cacheStatus) switch (cacheStatus)
{ {
case Storage.CacheStatus.NotPresent: case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause); returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue); Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
forceImageDownload = true; returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<GameMode>(returnValue, "id", (long)searchValue);
}
break; break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<GameMode>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<GameMode>(returnValue, "id", (long)searchValue);

View File

@@ -68,19 +68,24 @@ namespace gaseous_server.Classes.Metadata
} }
GameVideo returnValue = new GameVideo(); GameVideo returnValue = new GameVideo();
bool forceImageDownload = false;
switch (cacheStatus) switch (cacheStatus)
{ {
case Storage.CacheStatus.NotPresent: case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause); returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue); Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
forceImageDownload = true; returnValue = await GetObjectFromServer(WhereClause);
break; Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<GameVideo>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<GameVideo>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<GameVideo>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -102,9 +102,16 @@ namespace gaseous_server.Classes.Metadata
UpdateSubClasses(returnValue, getAllMetadata, followSubGames); UpdateSubClasses(returnValue, getAllMetadata, followSubGames);
return returnValue; return returnValue;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
UpdateSubClasses(returnValue, getAllMetadata, followSubGames); returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);
}
return returnValue; return returnValue;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
return Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue); return Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);

View File

@@ -68,19 +68,24 @@ namespace gaseous_server.Classes.Metadata
} }
Genre returnValue = new Genre(); Genre returnValue = new Genre();
bool forceImageDownload = false;
switch (cacheStatus) switch (cacheStatus)
{ {
case Storage.CacheStatus.NotPresent: case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause); returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue); Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
forceImageDownload = true; returnValue = await GetObjectFromServer(WhereClause);
break; Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<Genre>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Genre>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<Genre>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -74,9 +74,16 @@ namespace gaseous_server.Classes.Metadata
UpdateSubClasses(returnValue); UpdateSubClasses(returnValue);
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
UpdateSubClasses(returnValue); returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<InvolvedCompany>(returnValue, "id", (long)searchValue);
}
break; break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<InvolvedCompany>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<InvolvedCompany>(returnValue, "id", (long)searchValue);

View File

@@ -68,18 +68,23 @@ namespace gaseous_server.Classes.Metadata
} }
MultiplayerMode returnValue = new MultiplayerMode(); MultiplayerMode returnValue = new MultiplayerMode();
bool forceImageDownload = false;
switch (cacheStatus) switch (cacheStatus)
{ {
case Storage.CacheStatus.NotPresent: case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause); returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue); Storage.NewCacheValue(returnValue);
forceImageDownload = true;
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
forceImageDownload = true; returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<MultiplayerMode>(returnValue, "id", (long)searchValue);
}
break; break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<MultiplayerMode>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<MultiplayerMode>(returnValue, "id", (long)searchValue);

View File

@@ -80,12 +80,17 @@ namespace gaseous_server.Classes.Metadata
} }
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause, LogoPath); try
if (returnValue != null)
{ {
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
Storage.NewCacheValue(returnValue, true); Storage.NewCacheValue(returnValue, true);
forceImageDownload = true; forceImageDownload = true;
} }
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<PlatformLogo>(returnValue, "id", (long)searchValue);
}
break; break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<PlatformLogo>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<PlatformLogo>(returnValue, "id", (long)searchValue);

View File

@@ -78,12 +78,17 @@ namespace gaseous_server.Classes.Metadata
} }
return returnValue; return returnValue;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
if (returnValue != null)
{ {
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true); Storage.NewCacheValue(returnValue, true);
UpdateSubClasses(ParentPlatform, returnValue); UpdateSubClasses(ParentPlatform, returnValue);
} }
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<PlatformVersion>(returnValue, "id", (long)searchValue);
}
return returnValue; return returnValue;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
return Storage.GetCacheValue<PlatformVersion>(returnValue, "id", (long)searchValue); return Storage.GetCacheValue<PlatformVersion>(returnValue, "id", (long)searchValue);

View File

@@ -99,11 +99,19 @@ namespace gaseous_server.Classes.Metadata
AddPlatformMapping(returnValue); AddPlatformMapping(returnValue);
return returnValue; return returnValue;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
UpdateSubClasses(returnValue); returnValue = await GetObjectFromServer(WhereClause);
AddPlatformMapping(returnValue); Storage.NewCacheValue(returnValue, true);
return returnValue; UpdateSubClasses(returnValue);
AddPlatformMapping(returnValue);
return returnValue;
}
catch (Exception ex)
{
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
return Storage.GetCacheValue<Platform>(returnValue, "id", (long)searchValue);
}
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
return Storage.GetCacheValue<Platform>(returnValue, "id", (long)searchValue); return Storage.GetCacheValue<Platform>(returnValue, "id", (long)searchValue);
default: default:
@@ -148,7 +156,7 @@ namespace gaseous_server.Classes.Metadata
IGDBSlug = platform.Slug, IGDBSlug = platform.Slug,
AlternateNames = new List<string>{ platform.AlternativeName } AlternateNames = new List<string>{ platform.AlternativeName }
}; };
Models.PlatformMapping.WritePlatformMap(item, false); Models.PlatformMapping.WritePlatformMap(item, false, true);
} }
} }

View File

@@ -77,9 +77,16 @@ namespace gaseous_server.Classes.Metadata
forceImageDownload = true; forceImageDownload = true;
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
forceImageDownload = true; returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<PlayerPerspective>(returnValue, "id", (long)searchValue);
}
break; break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<PlayerPerspective>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<PlayerPerspective>(returnValue, "id", (long)searchValue);

View File

@@ -78,10 +78,18 @@ namespace gaseous_server.Classes.Metadata
forceImageDownload = true; forceImageDownload = true;
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause, LogoPath); try
Storage.NewCacheValue(returnValue, true); {
forceImageDownload = true; returnValue = await GetObjectFromServer(WhereClause, LogoPath);
break; Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
returnValue = Storage.GetCacheValue<Screenshot>(returnValue, "id", (long)searchValue);
}
break;
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Screenshot>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<Screenshot>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -77,10 +77,17 @@ namespace gaseous_server.Classes.Metadata
forceImageDownload = true; forceImageDownload = true;
break; break;
case Storage.CacheStatus.Expired: case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause); try
Storage.NewCacheValue(returnValue, true); {
forceImageDownload = true; returnValue = await GetObjectFromServer(WhereClause);
break; Storage.NewCacheValue(returnValue, true);
return returnValue;
}
catch (Exception ex)
{
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
return Storage.GetCacheValue<Theme>(returnValue, "id", (long)searchValue);
}
case Storage.CacheStatus.Current: case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Theme>(returnValue, "id", (long)searchValue); returnValue = Storage.GetCacheValue<Theme>(returnValue, "id", (long)searchValue);
break; break;

View File

@@ -103,9 +103,9 @@ namespace gaseous_server.Classes
GameId = (long)romDR["gameid"], GameId = (long)romDR["gameid"],
Name = (string)romDR["name"], Name = (string)romDR["name"],
Size = (long)romDR["size"], Size = (long)romDR["size"],
CRC = (string)romDR["crc"], CRC = ((string)romDR["crc"]).ToLower(),
MD5 = (string)romDR["md5"], MD5 = ((string)romDR["md5"]).ToLower(),
SHA1 = (string)romDR["sha1"], SHA1 = ((string)romDR["sha1"]).ToLower(),
DevelopmentStatus = (string)romDR["developmentstatus"], DevelopmentStatus = (string)romDR["developmentstatus"],
Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(romDR["attributes"], "[ ]")), Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(romDR["attributes"], "[ ]")),
RomType = (int)romDR["romtype"], RomType = (int)romDR["romtype"],

View File

@@ -188,9 +188,9 @@ namespace gaseous_server.SignatureIngestors.XML
dbDict.Add("gameid", gameId); dbDict.Add("gameid", gameId);
dbDict.Add("name", Common.ReturnValueIfNull(romObject.Name, "")); dbDict.Add("name", Common.ReturnValueIfNull(romObject.Name, ""));
dbDict.Add("size", Common.ReturnValueIfNull(romObject.Size, "")); dbDict.Add("size", Common.ReturnValueIfNull(romObject.Size, ""));
dbDict.Add("crc", Common.ReturnValueIfNull(romObject.Crc, "")); dbDict.Add("crc", Common.ReturnValueIfNull(romObject.Crc, "").ToString().ToLower());
dbDict.Add("md5", Common.ReturnValueIfNull(romObject.Md5, "")); dbDict.Add("md5", Common.ReturnValueIfNull(romObject.Md5, "").ToString().ToLower());
dbDict.Add("sha1", Common.ReturnValueIfNull(romObject.Sha1, "")); dbDict.Add("sha1", Common.ReturnValueIfNull(romObject.Sha1, "").ToString().ToLower());
dbDict.Add("developmentstatus", Common.ReturnValueIfNull(romObject.DevelopmentStatus, "")); dbDict.Add("developmentstatus", Common.ReturnValueIfNull(romObject.DevelopmentStatus, ""));
if (romObject.Attributes != null) if (romObject.Attributes != null)

View File

@@ -13,9 +13,9 @@ namespace gaseous_server.Controllers
{ {
[HttpGet] [HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public List<Logging.LogItem> Logs() public List<Logging.LogItem> Logs(long? StartIndex, int PageNumber = 1, int PageSize = 100)
{ {
return Logging.GetLogs(); return Logging.GetLogs(StartIndex, PageNumber, PageSize);
} }
} }
} }

View File

@@ -110,32 +110,32 @@ namespace gaseous_server.Controllers
return Ok(new { count = files.Count, size }); return Ok(new { count = files.Count, size });
} }
[HttpPost] // [HttpPost]
[Route("{PlatformId}")] // [Route("{PlatformId}")]
[ProducesResponseType(typeof(PlatformMapping.PlatformMapItem), StatusCodes.Status200OK)] // [ProducesResponseType(typeof(PlatformMapping.PlatformMapItem), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] // [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status409Conflict)] // [ProducesResponseType(StatusCodes.Status409Conflict)]
public ActionResult NewPlatformMap(long PlatformId, PlatformMapping.PlatformMapItem Map) // public ActionResult NewPlatformMap(long PlatformId, PlatformMapping.PlatformMapItem Map)
{ // {
try // try
{ // {
PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(PlatformId); // PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(PlatformId);
if (platformMapItem != null) // if (platformMapItem != null)
{ // {
return Conflict(); // return Conflict();
} // }
else // else
{ // {
PlatformMapping.WritePlatformMap(Map, false); // PlatformMapping.WritePlatformMap(Map, false, false);
return Ok(PlatformMapping.GetPlatformMap(PlatformId)); // return Ok(PlatformMapping.GetPlatformMap(PlatformId));
} // }
} // }
catch // catch
{ // {
return NotFound(); // return NotFound();
} // }
} // }
[HttpPatch] [HttpPatch]
[Route("{PlatformId}")] [Route("{PlatformId}")]
@@ -149,7 +149,7 @@ namespace gaseous_server.Controllers
if (platformMapItem != null) if (platformMapItem != null)
{ {
PlatformMapping.WritePlatformMap(Map, true); PlatformMapping.WritePlatformMap(Map, true, false);
return Ok(PlatformMapping.GetPlatformMap(PlatformId)); return Ok(PlatformMapping.GetPlatformMap(PlatformId));
} }
else else

View File

@@ -88,8 +88,8 @@ namespace gaseous_server.Controllers
Name = (string)sigDbRow["romname"], Name = (string)sigDbRow["romname"],
Size = (Int64)sigDbRow["Size"], Size = (Int64)sigDbRow["Size"],
Crc = (string)sigDbRow["CRC"], Crc = (string)sigDbRow["CRC"],
Md5 = (string)sigDbRow["MD5"], Md5 = ((string)sigDbRow["MD5"]).ToLower(),
Sha1 = (string)sigDbRow["SHA1"], Sha1 = ((string)sigDbRow["SHA1"]).ToLower(),
DevelopmentStatus = (string)sigDbRow["DevelopmentStatus"], DevelopmentStatus = (string)sigDbRow["DevelopmentStatus"],
Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(sigDbRow["Attributes"], "[]")), Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(sigDbRow["Attributes"], "[]")),
RomType = (Models.Signatures_Games.RomItem.RomTypes)(int)sigDbRow["RomType"], RomType = (Models.Signatures_Games.RomItem.RomTypes)(int)sigDbRow["RomType"],

View File

@@ -25,7 +25,10 @@ namespace gaseous_server.Models
{ {
string rawJson = reader.ReadToEnd(); string rawJson = reader.ReadToEnd();
List<PlatformMapItem> platforms = new List<PlatformMapItem>(); List<PlatformMapItem> platforms = new List<PlatformMapItem>();
platforms = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson); Newtonsoft.Json.JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings{
MaxDepth = 64
};
platforms = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson, jsonSerializerSettings);
foreach (PlatformMapItem mapItem in platforms) foreach (PlatformMapItem mapItem in platforms)
{ {
@@ -41,7 +44,7 @@ namespace gaseous_server.Models
} }
else else
{ {
WritePlatformMap(mapItem, true); WritePlatformMap(mapItem, true, true);
Logging.Log(Logging.LogType.Information, "Platform Map", "Overwriting " + mapItem.IGDBName + " with default values."); Logging.Log(Logging.LogType.Information, "Platform Map", "Overwriting " + mapItem.IGDBName + " with default values.");
} }
} }
@@ -49,7 +52,7 @@ namespace gaseous_server.Models
{ {
Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + mapItem.IGDBName + " from predefined data."); Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + mapItem.IGDBName + " from predefined data.");
// doesn't exist - add it // doesn't exist - add it
WritePlatformMap(mapItem, false); WritePlatformMap(mapItem, false, true);
} }
} }
} }
@@ -73,13 +76,13 @@ namespace gaseous_server.Models
// still here? we must have found the item we're looking for! overwrite it // still here? we must have found the item we're looking for! overwrite it
Logging.Log(Logging.LogType.Information, "Platform Map", "Replacing " + mapItem.IGDBName + " from external JSON file."); Logging.Log(Logging.LogType.Information, "Platform Map", "Replacing " + mapItem.IGDBName + " from external JSON file.");
WritePlatformMap(mapItem, true); WritePlatformMap(mapItem, true, true);
} }
catch catch
{ {
// we caught a not found error, insert a new record // we caught a not found error, insert a new record
Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + mapItem.IGDBName + " from external JSON file."); Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + mapItem.IGDBName + " from external JSON file.");
WritePlatformMap(mapItem, false); WritePlatformMap(mapItem, false, true);
} }
} }
} }
@@ -126,7 +129,7 @@ namespace gaseous_server.Models
} }
} }
public static void WritePlatformMap(PlatformMapItem item, bool Update) public static void WritePlatformMap(PlatformMapItem item, bool Update, bool AllowAvailableEmulatorOverwrite)
{ {
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = ""; string sql = "";
@@ -134,12 +137,19 @@ namespace gaseous_server.Models
if (Update == false) if (Update == false)
{ {
// insert // insert
sql = "INSERT INTO PlatformMap (Id, RetroPieDirectoryName, WebEmulator_Type, WebEmulator_Core) VALUES (@Id, @RetroPieDirectoryName, @WebEmulator_Type, @WebEmulator_Core)"; sql = "INSERT INTO PlatformMap (Id, RetroPieDirectoryName, WebEmulator_Type, WebEmulator_Core, AvailableWebEmulators) VALUES (@Id, @RetroPieDirectoryName, @WebEmulator_Type, @WebEmulator_Core, @AvailableWebEmulators)";
} }
else else
{ {
// update // update
sql = "UPDATE PlatformMap SET RetroPieDirectoryName=@RetroPieDirectoryName, WebEmulator_Type=@WebEmulator_Type, WebEmulator_Core=@WebEmulator_Core WHERE Id = @Id"; if (AllowAvailableEmulatorOverwrite == true)
{
sql = "UPDATE PlatformMap SET RetroPieDirectoryName=@RetroPieDirectoryName, WebEmulator_Type=@WebEmulator_Type, WebEmulator_Core=@WebEmulator_Core, AvailableWebEmulators=@AvailableWebEmulators WHERE Id = @Id";
}
else
{
sql = "UPDATE PlatformMap SET RetroPieDirectoryName=@RetroPieDirectoryName, WebEmulator_Type=@WebEmulator_Type, WebEmulator_Core=@WebEmulator_Core WHERE Id = @Id";
}
} }
dbDict.Add("Id", item.IGDBId); dbDict.Add("Id", item.IGDBId);
dbDict.Add("RetroPieDirectoryName", item.RetroPieDirectoryName); dbDict.Add("RetroPieDirectoryName", item.RetroPieDirectoryName);
@@ -147,11 +157,13 @@ namespace gaseous_server.Models
{ {
dbDict.Add("WebEmulator_Type", item.WebEmulator.Type); dbDict.Add("WebEmulator_Type", item.WebEmulator.Type);
dbDict.Add("WebEmulator_Core", item.WebEmulator.Core); dbDict.Add("WebEmulator_Core", item.WebEmulator.Core);
dbDict.Add("AvailableWebEmulators", Newtonsoft.Json.JsonConvert.SerializeObject(item.WebEmulator.AvailableWebEmulators));
} }
else else
{ {
dbDict.Add("WebEmulator_Type", ""); dbDict.Add("WebEmulator_Type", "");
dbDict.Add("WebEmulator_Core", ""); dbDict.Add("WebEmulator_Core", "");
dbDict.Add("AvailableWebEmulators", "");
} }
db.ExecuteCMD(sql, dbDict); db.ExecuteCMD(sql, dbDict);
@@ -286,7 +298,7 @@ namespace gaseous_server.Models
{ {
filename = (string)Common.ReturnValueIfNull(biosRow["Filename"], ""), filename = (string)Common.ReturnValueIfNull(biosRow["Filename"], ""),
description = (string)Common.ReturnValueIfNull(biosRow["Description"], ""), description = (string)Common.ReturnValueIfNull(biosRow["Description"], ""),
hash = (string)Common.ReturnValueIfNull(biosRow["Hash"], "") hash = ((string)Common.ReturnValueIfNull(biosRow["Hash"], "")).ToLower()
}; };
bioss.Add(bios); bioss.Add(bios);
} }
@@ -304,7 +316,8 @@ namespace gaseous_server.Models
mapItem.RetroPieDirectoryName = (string)Common.ReturnValueIfNull(row["RetroPieDirectoryName"], ""); mapItem.RetroPieDirectoryName = (string)Common.ReturnValueIfNull(row["RetroPieDirectoryName"], "");
mapItem.WebEmulator = new PlatformMapItem.WebEmulatorItem{ mapItem.WebEmulator = new PlatformMapItem.WebEmulatorItem{
Type = (string)Common.ReturnValueIfNull(row["WebEmulator_Type"], ""), Type = (string)Common.ReturnValueIfNull(row["WebEmulator_Type"], ""),
Core = (string)Common.ReturnValueIfNull(row["WebEmulator_Core"], "") Core = (string)Common.ReturnValueIfNull(row["WebEmulator_Core"], ""),
AvailableWebEmulators = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem.WebEmulatorItem.AvailableWebEmulatorItem>>((string)Common.ReturnValueIfNull(row["AvailableWebEmulators"], "[]"))
}; };
mapItem.Bios = bioss; mapItem.Bios = bioss;
@@ -378,6 +391,21 @@ namespace gaseous_server.Models
{ {
public string Type { get; set; } public string Type { get; set; }
public string Core { get; set; } public string Core { get; set; }
public List<AvailableWebEmulatorItem> AvailableWebEmulators { get; set; } = new List<AvailableWebEmulatorItem>();
public class AvailableWebEmulatorItem
{
public string EmulatorType { get; set; }
public List<AvailableWebEmulatorCoreItem> AvailableWebEmulatorCores { get; set; } = new List<AvailableWebEmulatorCoreItem>();
public class AvailableWebEmulatorCoreItem
{
public string Core { get; set; }
public string? AlternateCoreName { get; set; } = "";
public bool Default { get; set; } = false;
}
}
} }
public List<EmulatorBiosItem> Bios { get; set; } public List<EmulatorBiosItem> Bios { get; set; }

View File

@@ -9,34 +9,52 @@ namespace gaseous_server
public class QueueItem public class QueueItem
{ {
public QueueItem(QueueItemType ItemType, int ExecutionInterval, bool AllowManualStart = true) public QueueItem(QueueItemType ItemType, int ExecutionInterval, bool AllowManualStart = true, bool RemoveWhenStopped = false)
{ {
_ItemType = ItemType; _ItemType = ItemType;
_ItemState = QueueItemState.NeverStarted; _ItemState = QueueItemState.NeverStarted;
_LastRunTime = DateTime.UtcNow.AddMinutes(ExecutionInterval); _LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ")));
_Interval = ExecutionInterval; _Interval = ExecutionInterval;
_AllowManualStart = AllowManualStart; _AllowManualStart = AllowManualStart;
_RemoveWhenStopped = RemoveWhenStopped;
} }
public QueueItem(QueueItemType ItemType, int ExecutionInterval, List<QueueItemType> Blocks, bool AllowManualStart = true) public QueueItem(QueueItemType ItemType, int ExecutionInterval, List<QueueItemType> Blocks, bool AllowManualStart = true, bool RemoveWhenStopped = false)
{ {
_ItemType = ItemType; _ItemType = ItemType;
_ItemState = QueueItemState.NeverStarted; _ItemState = QueueItemState.NeverStarted;
_LastRunTime = DateTime.UtcNow.AddMinutes(ExecutionInterval); _LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ")));
_Interval = ExecutionInterval; _Interval = ExecutionInterval;
_AllowManualStart = AllowManualStart; _AllowManualStart = AllowManualStart;
_RemoveWhenStopped = RemoveWhenStopped;
_Blocks = Blocks; _Blocks = Blocks;
} }
private QueueItemType _ItemType = QueueItemType.NotConfigured; private QueueItemType _ItemType = QueueItemType.NotConfigured;
private QueueItemState _ItemState = QueueItemState.NeverStarted; private QueueItemState _ItemState = QueueItemState.NeverStarted;
private DateTime _LastRunTime = DateTime.UtcNow; private DateTime _LastRunTime = DateTime.UtcNow;
private DateTime _LastFinishTime = DateTime.UtcNow; private DateTime _LastFinishTime
{
get
{
return DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ")));
}
set
{
if (_SaveLastRunTime == true)
{
Config.SetSetting("LastRun_" + _ItemType.ToString(), value.ToString("yyyy-MM-ddThh:mm:ssZ"));
}
}
}
private bool _SaveLastRunTime = false;
private int _Interval = 0; private int _Interval = 0;
private string _LastResult = ""; private string _LastResult = "";
private string? _LastError = null; private string? _LastError = null;
private bool _ForceExecute = false; private bool _ForceExecute = false;
private bool _AllowManualStart = true; private bool _AllowManualStart = true;
private bool _RemoveWhenStopped = false;
private bool _IsBlocked = false;
private List<QueueItemType> _Blocks = new List<QueueItemType>(); private List<QueueItemType> _Blocks = new List<QueueItemType>();
public QueueItemType ItemType => _ItemType; public QueueItemType ItemType => _ItemType;
@@ -54,6 +72,9 @@ namespace gaseous_server
public string? LastError => _LastError; public string? LastError => _LastError;
public bool Force => _ForceExecute; public bool Force => _ForceExecute;
public bool AllowManualStart => _AllowManualStart; public bool AllowManualStart => _AllowManualStart;
public bool RemoveWhenStopped => _RemoveWhenStopped;
public bool IsBlocked => _IsBlocked;
public object? Options { get; set; } = null;
public List<QueueItemType> Blocks => _Blocks; public List<QueueItemType> Blocks => _Blocks;
public void Execute() public void Execute()
@@ -87,32 +108,52 @@ namespace gaseous_server
Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing MAME MESS files"); Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing MAME MESS files");
tIngest.Import(Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, "MAME MESS"), gaseous_signature_parser.parser.SignatureParser.MAMEMess); tIngest.Import(Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, "MAME MESS"), gaseous_signature_parser.parser.SignatureParser.MAMEMess);
_SaveLastRunTime = true;
break; break;
case QueueItemType.TitleIngestor: case QueueItemType.TitleIngestor:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Title Ingestor"); Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Title Ingestor");
Classes.ImportGames importGames = new Classes.ImportGames(Config.LibraryConfiguration.LibraryImportDirectory); Classes.ImportGames importGames = new Classes.ImportGames(Config.LibraryConfiguration.LibraryImportDirectory);
_SaveLastRunTime = true;
break; break;
case QueueItemType.MetadataRefresh: case QueueItemType.MetadataRefresh:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Metadata Refresher"); Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Metadata Refresher");
Classes.MetadataManagement.RefreshMetadata(true); Classes.MetadataManagement.RefreshMetadata(true);
_SaveLastRunTime = true;
break; break;
case QueueItemType.OrganiseLibrary: case QueueItemType.OrganiseLibrary:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Library Organiser"); Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Library Organiser");
Classes.ImportGame.OrganiseLibrary(); Classes.ImportGame.OrganiseLibrary();
_SaveLastRunTime = true;
break; break;
case QueueItemType.LibraryScan: case QueueItemType.LibraryScan:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Library Scanner"); Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Library Scanner");
Classes.ImportGame.LibraryScan(); Classes.ImportGame.LibraryScan();
_SaveLastRunTime = true;
break; break;
case QueueItemType.CollectionCompiler: case QueueItemType.CollectionCompiler:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Collection Compiler"); Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Collection Compiler");
Classes.Collections.CompileCollections(); Classes.Collections.CompileCollections((long)Options);
break; break;
case QueueItemType.BackgroundDatabaseUpgrade:
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Background Upgrade");
gaseous_tools.DatabaseMigration.UpgradeScriptBackgroundTasks();
break;
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -133,17 +174,59 @@ namespace gaseous_server
{ {
_ForceExecute = true; _ForceExecute = true;
} }
public void BlockedState(bool BlockState)
{
_IsBlocked = BlockState;
}
} }
public enum QueueItemType public enum QueueItemType
{ {
/// <summary>
/// Reserved for blocking all services - no actual background service is tied to this type
/// </summary>
All,
/// <summary>
/// Default type - no background service is tied to this type
/// </summary>
NotConfigured, NotConfigured,
/// <summary>
/// Ingests signature DAT files into the database
/// </summary>
SignatureIngestor, SignatureIngestor,
/// <summary>
/// Imports game files into the database and moves them to the required location on disk
/// </summary>
TitleIngestor, TitleIngestor,
/// <summary>
/// Forces stored metadata to be refreshed
/// </summary>
MetadataRefresh, MetadataRefresh,
/// <summary>
/// Ensures all managed files are where they are supposed to be
/// </summary>
OrganiseLibrary, OrganiseLibrary,
/// <summary>
/// Looks for orphaned files in the library and re-adds them to the database
/// </summary>
LibraryScan, LibraryScan,
CollectionCompiler
/// <summary>
/// Builds collections - set the options attribute to the id of the collection to build
/// </summary>
CollectionCompiler,
/// <summary>
/// Performs and post database upgrade scripts that can be processed as a background task
/// </summary>
BackgroundDatabaseUpgrade
} }
public enum QueueItemState public enum QueueItemState

View File

@@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
Logging.WriteToDiskOnly = true;
Logging.Log(Logging.LogType.Information, "Startup", "Starting Gaseous Server " + Assembly.GetExecutingAssembly().GetName().Version); Logging.Log(Logging.LogType.Information, "Startup", "Starting Gaseous Server " + Assembly.GetExecutingAssembly().GetName().Version);
// set up db // set up db
@@ -29,6 +30,23 @@ if (Config.ReadSetting("API Key", "Test API Key") == "Test API Key")
Config.SetSetting("API Key", APIKey.ToString()); Config.SetSetting("API Key", APIKey.ToString());
} }
// kick off any delayed upgrade tasks
// run 1002 background updates in the background on every start
DatabaseMigration.BackgroundUpgradeTargetSchemaVersions.Add(1002);
// start the task
ProcessQueue.QueueItem queueItem = new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.BackgroundDatabaseUpgrade,
1,
new List<ProcessQueue.QueueItemType>
{
ProcessQueue.QueueItemType.All
},
false,
true
);
queueItem.ForceExecute();
ProcessQueue.QueueItems.Add(queueItem);
// set up server // set up server
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@@ -164,13 +182,13 @@ ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
}) })
); );
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem( ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
ProcessQueue.QueueItemType.LibraryScan, 30, new List<ProcessQueue.QueueItemType> ProcessQueue.QueueItemType.LibraryScan, 1440, new List<ProcessQueue.QueueItemType>
{ {
ProcessQueue.QueueItemType.TitleIngestor,
ProcessQueue.QueueItemType.OrganiseLibrary ProcessQueue.QueueItemType.OrganiseLibrary
}) })
); );
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(ProcessQueue.QueueItemType.CollectionCompiler, 5, false));
Logging.WriteToDiskOnly = false;
// start the app // start the app
app.Run(); app.Run();

File diff suppressed because one or more lines are too long

View File

@@ -33,9 +33,23 @@ namespace gaseous_server
//_logger.LogInformation( //_logger.LogInformation(
// "Timed Hosted Service is working. Count: {Count}", count); // "Timed Hosted Service is working. Count: {Count}", count);
foreach (ProcessQueue.QueueItem qi in ProcessQueue.QueueItems) { List<ProcessQueue.QueueItem> ActiveList = new List<ProcessQueue.QueueItem>();
if ((DateTime.UtcNow > qi.NextRunTime || qi.Force == true) && CheckProcessBlockList(qi) == true) { ActiveList.AddRange(ProcessQueue.QueueItems);
qi.Execute(); foreach (ProcessQueue.QueueItem qi in ActiveList) {
if (CheckIfProcessIsBlockedByOthers(qi) == false) {
qi.BlockedState(false);
if (DateTime.UtcNow > qi.NextRunTime || qi.Force == true)
{
qi.Execute();
if (qi.RemoveWhenStopped == true && qi.ItemState == ProcessQueue.QueueItemState.Stopped)
{
ProcessQueue.QueueItems.Remove(qi);
}
}
}
else
{
qi.BlockedState(true);
} }
} }
} }
@@ -55,24 +69,24 @@ namespace gaseous_server
_timer?.Dispose(); _timer?.Dispose();
} }
private bool CheckProcessBlockList(ProcessQueue.QueueItem queueItem) private bool CheckIfProcessIsBlockedByOthers(ProcessQueue.QueueItem queueItem)
{ {
if (queueItem.Blocks.Count > 0) foreach (ProcessQueue.QueueItem qi in ProcessQueue.QueueItems)
{ {
foreach (ProcessQueue.QueueItem qi in ProcessQueue.QueueItems) if (qi.ItemState == ProcessQueue.QueueItemState.Running) {
{ // other service is running, check if queueItem is blocked by it
if (queueItem.Blocks.Contains(qi.ItemType) && qi.ItemState == ProcessQueue.QueueItemState.Running) if (
qi.Blocks.Contains(queueItem.ItemType) ||
qi.Blocks.Contains(ProcessQueue.QueueItemType.All)
)
{ {
return false; Console.WriteLine(queueItem.ItemType.ToString() + " is blocked by " + qi.ItemType.ToString());
return true;
} }
} }
}
return true; return false;
}
else
{
return true;
}
} }
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 17H12.01M12 14C12.8906 12.0938 15 12.2344 15 10C15 8.5 14 7 12 7C10.4521 7 9.50325 7.89844 9.15332 9M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 541 B

View File

@@ -394,7 +394,10 @@
} }
modalAlwaysInclude = alwaysInclude; modalAlwaysInclude = alwaysInclude;
console.log(JSON.stringify(modalAlwaysInclude));
if (!alwaysInclude) {
alwaysInclude = [];
}
var item = { var item = {
"name": document.getElementById('collection_name').value, "name": document.getElementById('collection_name').value,
@@ -414,6 +417,8 @@
"alwaysInclude": alwaysInclude "alwaysInclude": alwaysInclude
} }
console.log("Item: " + JSON.stringify(item));
return item; return item;
} }

View File

@@ -27,7 +27,7 @@
<h4>Standard Directory Naming</h4> <h4>Standard Directory Naming</h4>
</td> </td>
<td style="text-align: right;"> <td style="text-align: right;">
<input id="mapping_edit_igdbslug" readonly="readonly" type="text" style="width: 95%;"/> <input id="mapping_edit_igdbslug" readonly="readonly" type="text" style="width: 98%;"/>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -38,7 +38,7 @@
<h4>RetroPie Directory Naming</h4> <h4>RetroPie Directory Naming</h4>
</td> </td>
<td style="text-align: right;"> <td style="text-align: right;">
<input id="mapping_edit_retropie" type="text" style="width: 95%;"/> <input id="mapping_edit_retropie" type="text" style="width: 98%;"/>
</td> </td>
</tr> </tr>
</table> </table>
@@ -53,23 +53,32 @@
<input id="mapping_edit_enablewebemulator" type="checkbox"><label for="mapping_edit_enablewebemulator" style="margin-left: 5px;">Enabled</label> <input id="mapping_edit_enablewebemulator" type="checkbox"><label for="mapping_edit_enablewebemulator" style="margin-left: 5px;">Enabled</label>
</td> </td>
</tr> </tr>
<tr> <tr name="mapping_edit_webemulator">
<td style="width: 25%;"> <td style="width: 25%;">
<h4>Engine</h4> <h4>Engine</h4>
</td> </td>
<td> <td>
<select id="mapping_edit_webemulatorengine" style="width: 100%;"> <select id="mapping_edit_webemulatorengine" style="width: 100%;">
<option value="">-</option>
<option value="EmulatorJS">EmulatorJS</option>
</select> </select>
</td> </td>
</tr> </tr>
<tr> <tr name="mapping_edit_webemulator">
<td style="width: 25%;"> <td style="width: 25%;">
<h4>Core</h4> <h4>Core</h4>
</td> </td>
<td style="text-align: right;"> <td>
<input id="mapping_edit_webemulatorcore" type="text" style="width: 95%;"/> <select id="mapping_edit_webemulatorcore" style="width: 100%;">
</select>
</td>
</tr>
<tr name="mapping_edit_webemulator">
<td style="width: 25%;">
</td>
<td id="mapping_edit_webemulatorhelp">
</td> </td>
</tr> </tr>
</table> </table>
@@ -91,6 +100,10 @@
modalContent[0].classList.add('collections_modal'); modalContent[0].classList.add('collections_modal');
} }
var availableWebEmulators = [];
DisplayWebEmulatorContent(false);
ajaxCall( ajaxCall(
'/api/v1/PlatformMaps/' + modalVariables, '/api/v1/PlatformMaps/' + modalVariables,
'GET', 'GET',
@@ -125,14 +138,48 @@
document.getElementById('mapping_edit_igdbslug').value = result.igdbSlug; document.getElementById('mapping_edit_igdbslug').value = result.igdbSlug;
document.getElementById('mapping_edit_retropie').value = result.retroPieDirectoryName; document.getElementById('mapping_edit_retropie').value = result.retroPieDirectoryName;
// set up web emulator drop downs
$('#mapping_edit_webemulatorengine').select2(); $('#mapping_edit_webemulatorengine').select2();
if (result.webEmulator.type.length > 0) { $('#mapping_edit_webemulatorcore').select2();
document.getElementById('mapping_edit_enablewebemulator').checked = true;
$('#mapping_edit_webemulatorengine').val(result.webEmulator.type); // start populating drop downs
$('#mapping_edit_webemulatorengine').trigger('change'); if (result.webEmulator) {
document.getElementById('mapping_edit_webemulatorcore').value = result.webEmulator.core; if (result.webEmulator.availableWebEmulators.length > 0) {
availableWebEmulators = result.webEmulator.availableWebEmulators;
var offOption = new Option("-", "", false, false);
$('#mapping_edit_webemulatorengine').append(offOption).trigger('change');
for (var e = 0; e < result.webEmulator.availableWebEmulators.length; e++) {
var newOption = new Option(result.webEmulator.availableWebEmulators[e].emulatorType, result.webEmulator.availableWebEmulators[e].emulatorType, false, false);
$('#mapping_edit_webemulatorengine').append(newOption).trigger('change');
}
$('#mapping_edit_webemulatorengine').val(result.webEmulator.type);
$('#mapping_edit_webemulatorengine').trigger('change');
// select cores
RenderWebEmulatorCores(result.webEmulator.core);
if (result.webEmulator.type.length > 0) {
document.getElementById('mapping_edit_enablewebemulator').checked = true;
}
DisplayWebEmulatorHelp(result.webEmulator.type);
$('#mapping_edit_webemulatorengine').on('change', function(e) {
RenderWebEmulatorCores();
});
if (result.webEmulator.type.length > 0) {
DisplayWebEmulatorContent(true);
} else {
DisplayWebEmulatorContent(false);
}
} else {
// no emulators available
DisplayWebEmulatorContent(false);
}
} else { } else {
document.getElementById('mapping_edit_enablewebemulator').checked = false; // no emulators available
DisplayWebEmulatorContent(false);
} }
var biosTableHeaders = [ var biosTableHeaders = [
@@ -160,6 +207,55 @@
} }
); );
function RenderWebEmulatorCores(preSelectCore) {
var selectedEngine = document.getElementById('mapping_edit_webemulatorengine').value;
console.log("Engine: " + selectedEngine);
console.log("Preselect: " + preSelectCore);
console.log(JSON.stringify(availableWebEmulators));
$('#mapping_edit_webemulatorcore').empty().trigger("change");
// get cores for currently selected emulator
if (availableWebEmulators && (selectedEngine != undefined && selectedEngine != "")) {
if (availableWebEmulators.length > 0) {
var emuFound = false;
for (var e = 0; e < availableWebEmulators.length; e++) {
if (availableWebEmulators[e].emulatorType == selectedEngine) {
emuFound = true;
for (var c = 0; c < availableWebEmulators[e].availableWebEmulatorCores.length; c++) {
var coreName = availableWebEmulators[e].availableWebEmulatorCores[c].core;
if (availableWebEmulators[e].availableWebEmulatorCores[c].alternateCoreName) {
coreName += " (Maps to core: " + availableWebEmulators[e].availableWebEmulatorCores[c].alternateCoreName + ")";
}
if (availableWebEmulators[e].availableWebEmulatorCores[c].default == true) {
coreName += " (Default)";
}
console.log(coreName);
var newOption;
if (availableWebEmulators[e].availableWebEmulatorCores[c].core == preSelectCore) {
newOption = new Option(coreName, availableWebEmulators[e].availableWebEmulatorCores[c].core, true, true);
} else {
newOption = new Option(coreName, availableWebEmulators[e].availableWebEmulatorCores[c].core, false, false);
}
$('#mapping_edit_webemulatorcore').append(newOption).trigger('change');
}
}
}
if (emuFound == false) {
var newOption = new Option("-", "", true, true);
$('#mapping_edit_webemulatorcore').append(newOption).trigger('change');
}
} else {
var newOption = new Option("-", "", true, true);
$('#mapping_edit_webemulatorcore').append(newOption).trigger('change');
}
} else {
var newOption = new Option("-", "", true, true);
$('#mapping_edit_webemulatorcore').append(newOption).trigger('change');
}
}
function AddTokensFromList(selectObj, tagList) { function AddTokensFromList(selectObj, tagList) {
for (var i = 0; i < tagList.length; i++) { for (var i = 0; i < tagList.length; i++) {
var data = { var data = {
@@ -254,4 +350,39 @@
JSON.stringify(item) JSON.stringify(item)
); );
} }
$('#mapping_edit_webemulatorengine').on('select2:select', function (e) {
DisplayWebEmulatorHelp(e.params.data.id);
});
function DisplayWebEmulatorHelp(Emulator) {
var helpCell = document.getElementById('mapping_edit_webemulatorhelp');
switch (Emulator) {
case 'EmulatorJS':
helpCell.innerHTML = '<img src="/images/help.svg" class="banner_button_image banner_button_image_smaller" alt="Help" title="Help" /> See <a href="https://emulatorjs.org/docs4devs/Cores.html" target="_blank" class="romlink">https://emulatorjs.org/docs4devs/Cores.html</a> for more information regarding EmulatorJS cores.';
break;
default:
helpCell.innerHTML = '';
break;
}
}
$('#mapping_edit_enablewebemulator').change(function() {
DisplayWebEmulatorContent(this.checked);
});
function DisplayWebEmulatorContent(showContent) {
console.log(showContent);
var webEmulatorRows = document.getElementsByName('mapping_edit_webemulator');
for (var i = 0; i < webEmulatorRows.length; i++) {
if (showContent == true) {
webEmulatorRows[i].style.display = '';
} else {
webEmulatorRows[i].style.display = 'none';
}
}
}
</script> </script>

View File

@@ -375,7 +375,11 @@
var launchButton = ''; var launchButton = '';
if (result[i].emulator) { if (result[i].emulator) {
launchButton = '<a href="/index.html?page=emulator&engine=' + result[i].emulator.type + '&core=' + result[i].emulator.core + '&platformid=' + result[i].platform.id + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/' + encodeURIComponent(result[i].name)) + '" class="romstart">Launch</a>'; if (result[i].emulator.type) {
if (result[i].emulator.type.length > 0) {
launchButton = '<a href="/index.html?page=emulator&engine=' + result[i].emulator.type + '&core=' + result[i].emulator.core + '&platformid=' + result[i].platform.id + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1/Games/' + gameId + '/roms/' + result[i].id + '/' + encodeURIComponent(result[i].name)) + '" class="romstart">Launch</a>';
}
}
} }
var newRow = [ var newRow = [

View File

@@ -4,13 +4,17 @@
<table style="width: 100%;"> <table style="width: 100%;">
<tr> <tr>
<th>Home Page</th> <th style="width: 20%;">Home Page</th>
<td><a href="https://github.com/gaseous-project/gaseous-server" class="romlink">https://github.com/gaseous-project/gaseous-server</a></td> <td><a href="https://github.com/gaseous-project/gaseous-server" class="romlink">https://github.com/gaseous-project/gaseous-server</a></td>
</tr> </tr>
<tr> <tr>
<th>Bugs and Feature Requests</th> <th>Bugs and Feature Requests</th>
<td><a href="https://github.com/gaseous-project/gaseous-server/issues" class="romlink">https://github.com/gaseous-project/gaseous-server/issues</a></td> <td><a href="https://github.com/gaseous-project/gaseous-server/issues" class="romlink">https://github.com/gaseous-project/gaseous-server/issues</a></td>
</tr> </tr>
<tr>
<th>Join our Discord</th>
<td><a href="https://discord.gg/Nhu7wpT3k4" class="romlink">https://discord.gg/Nhu7wpT3k4</a></td>
</tr>
<tr> <tr>
<th>Server Version</th> <th>Server Version</th>
<td id="settings_appversion"></td> <td id="settings_appversion"></td>
@@ -19,6 +23,18 @@
<th>Database Schema Version</th> <th>Database Schema Version</th>
<td id="settings_dbversion"></td> <td id="settings_dbversion"></td>
</tr> </tr>
<tr>
<td colspan="2">
<h3>Projects That Make Gaseous Possible</h3>
</td>
</tr>
<tr>
<td style="text-align: center;"><a href="https://github.com/EmulatorJS/EmulatorJS" target="_blank"><img src="/images/EmulatorJS.png" style="height: 36px;" /></a></td>
<td>
The EmulatorJS Project<br />
<a href="https://github.com/EmulatorJS/EmulatorJS" target="_blank" class="romlink">https://github.com/EmulatorJS/EmulatorJS</a>
</td>
</tr>
<tr> <tr>
<td colspan="2"> <td colspan="2">
<h3>Data Sources</h2> <h3>Data Sources</h2>
@@ -26,11 +42,12 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td style="text-align: center;">
<a href="https://www.igdb.com/" target="_blank"><img src="/images/IGDB_logo.svg" style="filter: invert(100%); height: 36px;" /></a> <a href="https://www.igdb.com/" target="_blank"><img src="/images/IGDB_logo.svg" style="filter: invert(100%); height: 36px;" /></a>
</td> </td>
<td> <td>
The Internet Game Database The Internet Game Database<br />
<a href="https://www.igdb.com/" target="_blank" class="romlink">https://www.igdb.com/</a>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -39,19 +56,21 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td style="text-align: center;">
<a href="https://www.tosecdev.org/" target="_blank"><img src="/images/TOSEC_logo.gif" style="height: 36px;" /></a> <a href="https://www.tosecdev.org/" target="_blank"><img src="/images/TOSEC_logo.gif" style="height: 36px;" /></a>
</td> </td>
<td> <td>
The Old School Emulation Center The Old School Emulation Center<br />
<a href="https://www.tosecdev.org/" target="_blank" class="romlink">https://www.tosecdev.org/</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td style="text-align: center;">
<a href="https://www.progettosnaps.net/index.php" target="_blank"><img src="/images/ProgettoSnaps.gif" style="height: 36px;" /></a> <a href="https://www.progettosnaps.net/index.php" target="_blank"><img src="/images/ProgettoSnaps.gif" style="height: 36px;" /></a>
</td> </td>
<td> <td>
Progetto-Snaps Progetto-Snaps<br />
<a href="https://www.progettosnaps.net/index.php" target="_blank" class="romlink">https://www.progettosnaps.net/index.php</a>
</td> </td>
</tr> </tr>
</table> </table>

View File

@@ -7,30 +7,53 @@
</table> </table>
<div style="width: 960px; text-align: center;">
<button value="Load More" onclick="loadLogs(lastStartIndex, currentPage);">Load More</button>
</div>
<script type="text/javascript"> <script type="text/javascript">
function loadLogs() { var lastStartIndex = 0;
var currentPage = 1;
function loadLogs(StartIndex, PageNumber) {
var apiQuery = '';
if (StartIndex && PageNumber) {
currentPage += 1;
apiQuery = '?StartIndex=' + StartIndex + '&PageNumber=' + PageNumber;
} else {
currentPage = 1;
}
ajaxCall( ajaxCall(
'/api/v1/Logs', '/api/v1/Logs' + apiQuery,
'GET', 'GET',
function (result) { function (result) {
var newTable = document.getElementById('settings_events_table'); var newTable = document.getElementById('settings_events_table');
newTable.innerHTML = ''; if (currentPage == 1) {
newTable.appendChild( newTable.innerHTML = '';
createTableRow(
true, newTable.appendChild(
[ createTableRow(
['Event Time', 'logs_table_cell_150px'], true,
['Severity', 'logs_table_cell_150px'], [
'Process', //'Id',
'Message' ['Event Time', 'logs_table_cell_150px'],
], ['Severity', 'logs_table_cell_150px'],
'', 'Process',
'' 'Message'
) ],
); '',
''
)
);
}
for (var i = 0; i < result.length; i++) { for (var i = 0; i < result.length; i++) {
lastStartIndex = result[i].id;
var newRow = [ var newRow = [
//result[i].id,
moment(result[i].eventTime).fromNow(), moment(result[i].eventTime).fromNow(),
result[i].eventType, result[i].eventType,
result[i].process, result[i].process,

View File

@@ -48,7 +48,7 @@
} }
var newRow = [ var newRow = [
'<span onclick="ShowPlatformMappingDialog(' + result[i].igdbId + ');" class="romlink">' + result[i].igdbName + '</span>', '<a href="#/" onclick="ShowPlatformMappingDialog(' + result[i].igdbId + ');" class="romlink">' + result[i].igdbName + '</a>',
result[i].extensions.supportedFileExtensions.join(', '), result[i].extensions.supportedFileExtensions.join(', '),
result[i].extensions.uniqueFileExtensions.join(', '), result[i].extensions.uniqueFileExtensions.join(', '),
hasWebEmulator hasWebEmulator

View File

@@ -52,7 +52,10 @@
itemTypeName = "Library scan"; itemTypeName = "Library scan";
break; break;
case 'CollectionCompiler': case 'CollectionCompiler':
itemTypeName = "Compress collections"; itemTypeName = "Compress collection id: " + result[i].options;
break;
case 'BackgroundDatabaseUpgrade':
itemTypeName = "Background database upgrade";
break; break;
default: default:
itemTypeName = result[i].itemType; itemTypeName = result[i].itemType;
@@ -61,36 +64,48 @@
var itemStateName; var itemStateName;
var itemLastStart; var itemLastStart;
switch (result[i].itemState) { if (result[i].isBlocked == false) {
case 'NeverStarted': switch (result[i].itemState) {
itemStateName = "Never started"; case 'NeverStarted':
itemLastStart = '-'; itemStateName = "Never started";
break; itemLastStart = '-';
case 'Stopped': break;
itemStateName = "Stopped"; case 'Stopped':
itemLastStart = moment(result[i].lastRunTime).fromNow(); itemStateName = "Stopped";
break; itemLastStart = moment(result[i].lastRunTime).fromNow();
case 'Running': break;
itemStateName = "Running"; case 'Running':
itemLastStart = moment(result[i].lastRunTime).fromNow(); itemStateName = "Running";
break; itemLastStart = moment(result[i].lastRunTime).fromNow();
default: break;
itemStateName = "Unknown status"; default:
itemLastStart = moment(result[i].lastRunTime).fromNow(); itemStateName = "Unknown status";
break; itemLastStart = moment(result[i].lastRunTime).fromNow();
break;
}
} else {
itemStateName = "Blocked";
itemLastStart = moment(result[i].lastRunTime).fromNow();
} }
var itemInterval = result[i].interval;
var nextRunTime = moment(result[i].nextRunTime).fromNow();
var startButton = ''; var startButton = '';
if (result[i].allowManualStart == true && result[i].itemState != "Running") { if (result[i].allowManualStart == true && result[i].itemState != "Running") {
startButton = "<span id='startProcess' class='romstart' onclick='StartProcess(\"" + result[i].itemType + "\");'>Start</span>"; startButton = "<span id='startProcess' class='romstart' onclick='StartProcess(\"" + result[i].itemType + "\");'>Start</span>";
} }
if (result[i].allowManualStart == false && result[i].removeWhenStopped == true) {
itemInterval = '';
nextRunTime = '';
}
var newRow = [ var newRow = [
itemTypeName, itemTypeName,
itemStateName, itemStateName,
result[i].interval, itemInterval,
itemLastStart, itemLastStart,
moment(result[i].nextRunTime).fromNow(), nextRunTime,
startButton startButton
]; ];
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell')); newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));

View File

@@ -61,7 +61,7 @@ namespace gaseous_tools
{ {
get get
{ {
return _md5hash; return _md5hash.ToLower();
} }
set set
{ {
@@ -73,7 +73,7 @@ namespace gaseous_tools
{ {
get get
{ {
return _sha1hash; return _sha1hash.ToLower();
} }
set set
{ {

View File

@@ -0,0 +1,2 @@
ALTER TABLE `PlatformMap`
ADD COLUMN `AvailableWebEmulators` JSON NULL;

View File

@@ -5,26 +5,43 @@ namespace gaseous_tools
{ {
public static class DatabaseMigration public static class DatabaseMigration
{ {
public static void PreUpgradeScript(int TargetSchemaVersion, gaseous_tools.Database.databaseType? DatabaseType) { public static List<int> BackgroundUpgradeTargetSchemaVersions = new List<int>();
public static void PreUpgradeScript(int TargetSchemaVersion, gaseous_tools.Database.databaseType? DatabaseType)
{
} }
public static void PostUpgradeScript(int TargetSchemaVersion, gaseous_tools.Database.databaseType? DatabaseType) { public static void PostUpgradeScript(int TargetSchemaVersion, gaseous_tools.Database.databaseType? DatabaseType)
{
switch(DatabaseType) switch(DatabaseType)
{ {
case gaseous_tools.Database.databaseType.MySql: case Database.databaseType.MySql:
switch (TargetSchemaVersion) switch (TargetSchemaVersion)
{ {
case 1002: case 1002:
MySql_1002_MigrateMetadataVersion(); // this is a safe background task
BackgroundUpgradeTargetSchemaVersions.Add(1002);
break; break;
} }
break; break;
} }
} }
private static void MySql_1002_MigrateMetadataVersion() { public static void UpgradeScriptBackgroundTasks()
{
foreach (int TargetSchemaVersion in BackgroundUpgradeTargetSchemaVersions)
{
switch (TargetSchemaVersion)
{
case 1002:
MySql_1002_MigrateMetadataVersion();
break;
}
}
}
public static void MySql_1002_MigrateMetadataVersion() {
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = ""; string sql = "";
Dictionary<string, object> dbDict = new Dictionary<string, object>(); Dictionary<string, object> dbDict = new Dictionary<string, object>();

View File

@@ -8,6 +8,8 @@ namespace gaseous_tools
{ {
public class Logging public class Logging
{ {
public static bool WriteToDiskOnly { get; set; } = false;
static public void Log(LogType EventType, string ServerProcess, string Message, Exception? ExceptionValue = null, bool LogToDiskOnly = false) static public void Log(LogType EventType, string ServerProcess, string Message, Exception? ExceptionValue = null, bool LogToDiskOnly = false)
{ {
LogItem logItem = new LogItem LogItem logItem = new LogItem
@@ -61,6 +63,11 @@ namespace gaseous_tools
Console.WriteLine(TraceOutput); Console.WriteLine(TraceOutput);
Console.ResetColor(); Console.ResetColor();
if (WriteToDiskOnly == true)
{
LogToDiskOnly = true;
}
if (LogToDiskOnly == false) if (LogToDiskOnly == false)
{ {
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
@@ -104,17 +111,30 @@ namespace gaseous_tools
File.AppendAllText(Config.LogFilePath, TraceOutput); File.AppendAllText(Config.LogFilePath, TraceOutput);
} }
static public List<LogItem> GetLogs() static public List<LogItem> GetLogs(long? StartIndex, int PageNumber = 1, int PageSize = 100)
{ {
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
string sql = "SELECT * FROM ServerLogs ORDER BY Id DESC"; string sql = "";
DataTable dataTable = db.ExecuteCMD(sql); if (StartIndex == null)
{
sql = "SELECT * FROM ServerLogs ORDER BY Id DESC LIMIT @PageSize OFFSET @PageNumber;";
}
else
{
sql = "SELECT * FROM ServerLogs WHERE Id < @StartIndex ORDER BY Id DESC LIMIT @PageSize OFFSET @PageNumber;";
}
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("StartIndex", StartIndex);
dbDict.Add("PageNumber", (PageNumber - 1) * PageSize);
dbDict.Add("PageSize", PageSize);
DataTable dataTable = db.ExecuteCMD(sql, dbDict);
List<LogItem> logs = new List<LogItem>(); List<LogItem> logs = new List<LogItem>();
foreach (DataRow row in dataTable.Rows) foreach (DataRow row in dataTable.Rows)
{ {
LogItem log = new LogItem LogItem log = new LogItem
{ {
Id = (long)row["Id"],
EventTime = DateTime.Parse(((DateTime)row["EventTime"]).ToString("yyyy-MM-ddThh:mm:ss") + 'Z'), EventTime = DateTime.Parse(((DateTime)row["EventTime"]).ToString("yyyy-MM-ddThh:mm:ss") + 'Z'),
EventType = (LogType)row["EventType"], EventType = (LogType)row["EventType"],
Process = (string)row["Process"], Process = (string)row["Process"],
@@ -138,6 +158,7 @@ namespace gaseous_tools
public class LogItem public class LogItem
{ {
public long Id { get; set; }
public DateTime EventTime { get; set; } public DateTime EventTime { get; set; }
public LogType? EventType { get; set; } public LogType? EventType { get; set; }
public string Process { get; set; } = ""; public string Process { get; set; } = "";

View File

@@ -18,6 +18,7 @@
<None Remove="Database\MySQL\gaseous-1000.sql" /> <None Remove="Database\MySQL\gaseous-1000.sql" />
<None Remove="Database\MySQL\gaseous-1001.sql" /> <None Remove="Database\MySQL\gaseous-1001.sql" />
<None Remove="Database\MySQL\gaseous-1002.sql" /> <None Remove="Database\MySQL\gaseous-1002.sql" />
<None Remove="Database\MySQL\gaseous-1003.sql" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Database\" /> <Folder Include="Database\" />
@@ -27,5 +28,6 @@
<EmbeddedResource Include="Database\MySQL\gaseous-1000.sql" /> <EmbeddedResource Include="Database\MySQL\gaseous-1000.sql" />
<EmbeddedResource Include="Database\MySQL\gaseous-1001.sql" /> <EmbeddedResource Include="Database\MySQL\gaseous-1001.sql" />
<EmbeddedResource Include="Database\MySQL\gaseous-1002.sql" /> <EmbeddedResource Include="Database\MySQL\gaseous-1002.sql" />
<EmbeddedResource Include="Database\MySQL\gaseous-1003.sql" />
</ItemGroup> </ItemGroup>
</Project> </Project>