Compare commits
16 Commits
v1.6.0-pre
...
v1.6.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1ade1922df | ||
![]() |
f9d6cc4bdc | ||
![]() |
1934558595 | ||
![]() |
fc09db60ab | ||
![]() |
906456782a | ||
![]() |
d6d6a5d808 | ||
![]() |
586f2c69d8 | ||
![]() |
45e4666c51 | ||
![]() |
d94c921815 | ||
![]() |
fff22ea8d9 | ||
![]() |
9b930b2a51 | ||
![]() |
a0408a1d1d | ||
![]() |
f2c58bb172 | ||
![]() |
7eb418d6a2 | ||
![]() |
60fab488a2 | ||
![]() |
5a5a2f94fb |
16
README.MD
16
README.MD
@@ -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
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
## 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.
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
176
gaseous-server/Classes/GameLibrary.cs
Normal file
176
gaseous-server/Classes/GameLibrary.cs
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using gaseous_server.Classes.Metadata;
|
||||||
|
using gaseous_tools;
|
||||||
|
using IGDB.Models;
|
||||||
|
using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow;
|
||||||
|
|
||||||
|
namespace gaseous_server
|
||||||
|
{
|
||||||
|
public static class GameLibrary
|
||||||
|
{
|
||||||
|
// exceptions
|
||||||
|
public class PathExists : Exception
|
||||||
|
{
|
||||||
|
public PathExists(string path) : base("The library path " + path + " already exists.")
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PathNotFound : Exception
|
||||||
|
{
|
||||||
|
public PathNotFound(string path) : base("The path " + path + " does not exist.")
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LibraryNotFound : Exception
|
||||||
|
{
|
||||||
|
public LibraryNotFound(int LibraryId) : base("Library id " + LibraryId + " does not exist.")
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CannotDeleteDefaultLibrary : Exception
|
||||||
|
{
|
||||||
|
public CannotDeleteDefaultLibrary() : base("Unable to delete the default library.")
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// code
|
||||||
|
public static LibraryItem GetDefaultLibrary
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT * FROM GameLibraries WHERE DefaultLibrary=1 LIMIT 1";
|
||||||
|
DataTable data = db.ExecuteCMD(sql);
|
||||||
|
DataRow row = data.Rows[0];
|
||||||
|
LibraryItem library = new LibraryItem((int)row["Id"], (string)row["Name"], (string)row["Path"], (long)row["DefaultPlatform"], Convert.ToBoolean((int)row["DefaultLibrary"]));
|
||||||
|
|
||||||
|
return library;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<LibraryItem> GetLibraries
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<LibraryItem> libraryItems = new List<LibraryItem>();
|
||||||
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT * FROM GameLibraries";
|
||||||
|
DataTable data = db.ExecuteCMD(sql);
|
||||||
|
foreach (DataRow row in data.Rows)
|
||||||
|
{
|
||||||
|
LibraryItem library = new LibraryItem((int)row["Id"], (string)row["Name"], (string)row["Path"], (long)row["DefaultPlatform"], Convert.ToBoolean((int)row["DefaultLibrary"]));
|
||||||
|
libraryItems.Add(library);
|
||||||
|
}
|
||||||
|
|
||||||
|
return libraryItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LibraryItem AddLibrary(string Name, string Path, long DefaultPlatformId)
|
||||||
|
{
|
||||||
|
string PathName = Common.NormalizePath(Path);
|
||||||
|
|
||||||
|
// check path isn't already in place
|
||||||
|
foreach (LibraryItem item in GetLibraries)
|
||||||
|
{
|
||||||
|
if (Common.NormalizePath(PathName) == Common.NormalizePath(item.Path))
|
||||||
|
{
|
||||||
|
// already existing path!
|
||||||
|
throw new PathExists(PathName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!System.IO.Path.Exists(PathName))
|
||||||
|
{
|
||||||
|
throw new PathNotFound(PathName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "INSERT INTO GameLibraries (Name, Path, DefaultPlatform, DefaultLibrary) VALUES (@name, @path, @defaultplatform, 0); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
dbDict.Add("name", Name);
|
||||||
|
dbDict.Add("path", PathName);
|
||||||
|
dbDict.Add("defaultplatform", DefaultPlatformId);
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
int newLibraryId = (int)(long)data.Rows[0][0];
|
||||||
|
|
||||||
|
return GetLibrary(newLibraryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DeleteLibrary(int LibraryId)
|
||||||
|
{
|
||||||
|
if (GetLibrary(LibraryId).IsDefaultLibrary == false)
|
||||||
|
{
|
||||||
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "DELETE FROM Games_Roms WHERE LibraryId=@id; DELETE FROM GameLibraries WHERE Id=@id;";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
dbDict.Add("id", LibraryId);
|
||||||
|
db.ExecuteCMD(sql, dbDict);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new CannotDeleteDefaultLibrary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LibraryItem GetLibrary(int LibraryId)
|
||||||
|
{
|
||||||
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT * FROM GameLibraries WHERE Id=@id";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
dbDict.Add("id", LibraryId);
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
if (data.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
DataRow row = data.Rows[0];
|
||||||
|
LibraryItem library = new LibraryItem((int)row["Id"], (string)row["Name"], (string)row["Path"], (long)row["DefaultPlatform"], Convert.ToBoolean((int)row["DefaultLibrary"]));
|
||||||
|
return library;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new LibraryNotFound(LibraryId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LibraryItem
|
||||||
|
{
|
||||||
|
public LibraryItem(int Id, string Name, string Path, long DefaultPlatformId, bool IsDefaultLibrary)
|
||||||
|
{
|
||||||
|
_Id = Id;
|
||||||
|
_Name = Name;
|
||||||
|
_Path = Path;
|
||||||
|
_DefaultPlatformId = DefaultPlatformId;
|
||||||
|
_IsDefaultLibrary = IsDefaultLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _Id = 0;
|
||||||
|
string _Name = "";
|
||||||
|
string _Path = "";
|
||||||
|
long _DefaultPlatformId = 0;
|
||||||
|
bool _IsDefaultLibrary = false;
|
||||||
|
|
||||||
|
public int Id => _Id;
|
||||||
|
public string Name => _Name;
|
||||||
|
public string Path => _Path;
|
||||||
|
public long DefaultPlatformId => _DefaultPlatformId;
|
||||||
|
public string? DefaultPlatformName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_DefaultPlatformId != 0)
|
||||||
|
{
|
||||||
|
Platform platform = Platforms.GetPlatform(_DefaultPlatformId);
|
||||||
|
return platform.Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool IsDefaultLibrary => _IsDefaultLibrary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -4,6 +4,7 @@ using System.IO.Compression;
|
|||||||
using System.Security.Policy;
|
using System.Security.Policy;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using gaseous_server.Classes.Metadata;
|
||||||
using gaseous_tools;
|
using gaseous_tools;
|
||||||
using IGDB.Models;
|
using IGDB.Models;
|
||||||
using MySqlX.XDevAPI;
|
using MySqlX.XDevAPI;
|
||||||
@@ -98,7 +99,7 @@ namespace gaseous_server.Classes
|
|||||||
IGDB.Models.Game determinedGame = SearchForGame(discoveredSignature.Game.Name, discoveredSignature.Flags.IGDBPlatformId);
|
IGDB.Models.Game determinedGame = SearchForGame(discoveredSignature.Game.Name, discoveredSignature.Flags.IGDBPlatformId);
|
||||||
|
|
||||||
// add to database
|
// add to database
|
||||||
StoreROM(hash, determinedGame, determinedPlatform, discoveredSignature, GameFileImportPath);
|
StoreROM(GameLibrary.GetDefaultLibrary, hash, determinedGame, determinedPlatform, discoveredSignature, GameFileImportPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -391,7 +392,7 @@ namespace gaseous_server.Classes
|
|||||||
return SearchCandidates;
|
return SearchCandidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long StoreROM(Common.hashObject hash, IGDB.Models.Game determinedGame, IGDB.Models.Platform determinedPlatform, Models.Signatures_Games discoveredSignature, string GameFileImportPath, long UpdateId = 0)
|
public static long StoreROM(GameLibrary.LibraryItem library, Common.hashObject hash, IGDB.Models.Game determinedGame, IGDB.Models.Platform determinedPlatform, Models.Signatures_Games discoveredSignature, string GameFileImportPath, long UpdateId = 0)
|
||||||
{
|
{
|
||||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
|
||||||
@@ -401,7 +402,7 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
if (UpdateId == 0)
|
if (UpdateId == 0)
|
||||||
{
|
{
|
||||||
sql = "INSERT INTO Games_Roms (PlatformId, GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, Path, MetadataSource, MetadataGameName, MetadataVersion) VALUES (@platformid, @gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @Attributes, @romtype, @romtypemedia, @medialabel, @path, @metadatasource, @metadatagamename, @metadataversion); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
sql = "INSERT INTO Games_Roms (PlatformId, GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, Path, MetadataSource, MetadataGameName, MetadataVersion, LibraryId) VALUES (@platformid, @gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @Attributes, @romtype, @romtypemedia, @medialabel, @path, @metadatasource, @metadatagamename, @metadataversion, @libraryid); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
sql = "UPDATE Games_Roms SET PlatformId=platformid, GameId=@gameid, Name=@name, Size=@size, DevelopmentStatus=@developmentstatus, Attributes=@Attributes, RomType=@romtype, RomTypeMedia=@romtypemedia, MediaLabel=@medialabel, MetadataSource=@metadatasource, MetadataGameName=@metadatagamename, MetadataVersion=@metadataversion WHERE Id=@id;";
|
sql = "UPDATE Games_Roms SET PlatformId=platformid, GameId=@gameid, Name=@name, Size=@size, DevelopmentStatus=@developmentstatus, Attributes=@Attributes, RomType=@romtype, RomTypeMedia=@romtypemedia, MediaLabel=@medialabel, MetadataSource=@metadatasource, MetadataGameName=@metadatagamename, MetadataVersion=@metadataversion WHERE Id=@id;";
|
||||||
@@ -418,6 +419,7 @@ namespace gaseous_server.Classes
|
|||||||
dbDict.Add("metadatasource", discoveredSignature.Rom.SignatureSource);
|
dbDict.Add("metadatasource", discoveredSignature.Rom.SignatureSource);
|
||||||
dbDict.Add("metadatagamename", discoveredSignature.Game.Name);
|
dbDict.Add("metadatagamename", discoveredSignature.Game.Name);
|
||||||
dbDict.Add("metadataversion", 2);
|
dbDict.Add("metadataversion", 2);
|
||||||
|
dbDict.Add("libraryid", library.Id);
|
||||||
|
|
||||||
if (discoveredSignature.Rom.Attributes != null)
|
if (discoveredSignature.Rom.Attributes != null)
|
||||||
{
|
{
|
||||||
@@ -450,7 +452,10 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// move to destination
|
// move to destination
|
||||||
MoveGameFile(romId);
|
if (library.IsDefaultLibrary == true)
|
||||||
|
{
|
||||||
|
MoveGameFile(romId);
|
||||||
|
}
|
||||||
|
|
||||||
return romId;
|
return romId;
|
||||||
}
|
}
|
||||||
@@ -474,7 +479,7 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
gameSlug = game.Slug;
|
gameSlug = game.Slug;
|
||||||
}
|
}
|
||||||
string DestinationPath = Path.Combine(Config.LibraryConfiguration.LibraryDataDirectory, gameSlug, platformSlug);
|
string DestinationPath = Path.Combine(GameLibrary.GetDefaultLibrary.Path, gameSlug, platformSlug);
|
||||||
if (!Directory.Exists(DestinationPath))
|
if (!Directory.Exists(DestinationPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(DestinationPath);
|
Directory.CreateDirectory(DestinationPath);
|
||||||
@@ -532,12 +537,16 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
public static void OrganiseLibrary()
|
public static void OrganiseLibrary()
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Organise Library", "Starting library organisation");
|
Logging.Log(Logging.LogType.Information, "Organise Library", "Starting default library organisation");
|
||||||
|
|
||||||
|
GameLibrary.LibraryItem library = GameLibrary.GetDefaultLibrary;
|
||||||
|
|
||||||
// move rom files to their new location
|
// move rom files to their new location
|
||||||
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 Games_Roms";
|
string sql = "SELECT * FROM Games_Roms WHERE LibraryId = @libraryid";
|
||||||
DataTable romDT = db.ExecuteCMD(sql);
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
dbDict.Add("libraryid", library.Id);
|
||||||
|
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
if (romDT.Rows.Count > 0)
|
if (romDT.Rows.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -550,9 +559,9 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clean up empty directories
|
// clean up empty directories
|
||||||
DeleteOrphanedDirectories(Config.LibraryConfiguration.LibraryDataDirectory);
|
DeleteOrphanedDirectories(GameLibrary.GetDefaultLibrary.Path);
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Organise Library", "Finsihed library organisation");
|
Logging.Log(Logging.LogType.Information, "Organise Library", "Finsihed default library organisation");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DeleteOrphanedDirectories(string startLocation)
|
private static void DeleteOrphanedDirectories(string startLocation)
|
||||||
@@ -570,154 +579,179 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
public static void LibraryScan()
|
public static void LibraryScan()
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Starting library scan");
|
foreach (GameLibrary.LibraryItem library in GameLibrary.GetLibraries)
|
||||||
|
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Looking for duplicate library files to clean up");
|
|
||||||
string duplicateSql = "DELETE r1 FROM Games_Roms r1 INNER JOIN Games_Roms r2 WHERE r1.Id > r2.Id AND r1.MD5 = r2.MD5;";
|
|
||||||
db.ExecuteCMD(duplicateSql);
|
|
||||||
|
|
||||||
string sql = "SELECT * FROM Games_Roms ORDER BY `name`";
|
|
||||||
DataTable dtRoms = db.ExecuteCMD(sql);
|
|
||||||
|
|
||||||
// clean out database entries in the import folder
|
|
||||||
if (dtRoms.Rows.Count > 0)
|
|
||||||
{
|
{
|
||||||
for (var i = 0; i < dtRoms.Rows.Count; i++)
|
Logging.Log(Logging.LogType.Information, "Library Scan", "Starting library scan. Library " + library.Name);
|
||||||
|
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
|
||||||
|
Logging.Log(Logging.LogType.Information, "Library Scan", "Looking for duplicate library files to clean up");
|
||||||
|
string duplicateSql = "DELETE r1 FROM Games_Roms r1 INNER JOIN Games_Roms r2 WHERE r1.Id > r2.Id AND r1.MD5 = r2.MD5 AND r1.LibraryId=@libraryid AND r2.LibraryId=@libraryid;";
|
||||||
|
Dictionary<string, object> dupDict = new Dictionary<string, object>();
|
||||||
|
dupDict.Add("libraryid", library.Id);
|
||||||
|
db.ExecuteCMD(duplicateSql, dupDict);
|
||||||
|
|
||||||
|
string sql = "SELECT * FROM Games_Roms WHERE LibraryId=@libraryid ORDER BY `name`";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
dbDict.Add("libraryid", library.Id);
|
||||||
|
DataTable dtRoms = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
// clean out database entries in the import folder
|
||||||
|
if (dtRoms.Rows.Count > 0)
|
||||||
{
|
{
|
||||||
long romId = (long)dtRoms.Rows[i]["Id"];
|
|
||||||
string romPath = (string)dtRoms.Rows[i]["Path"];
|
|
||||||
|
|
||||||
if (!romPath.StartsWith(Config.LibraryConfiguration.LibraryDataDirectory))
|
|
||||||
{
|
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Deleting database entry for files with incorrect directory " + romPath);
|
|
||||||
string deleteSql = "DELETE FROM Games_Roms WHERE Id=@id";
|
|
||||||
Dictionary<string, object> deleteDict = new Dictionary<string, object>();
|
|
||||||
deleteDict.Add("Id", romId);
|
|
||||||
db.ExecuteCMD(deleteSql, deleteDict);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sql = "SELECT * FROM Games_Roms ORDER BY `name`";
|
|
||||||
dtRoms = db.ExecuteCMD(sql);
|
|
||||||
|
|
||||||
// search for files in the library that aren't in the database
|
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Looking for orphaned library files to add");
|
|
||||||
string[] LibraryFiles = Directory.GetFiles(Config.LibraryConfiguration.LibraryDataDirectory, "*.*", SearchOption.AllDirectories);
|
|
||||||
foreach (string LibraryFile in LibraryFiles)
|
|
||||||
{
|
|
||||||
if (!Common.SkippableFiles.Contains<string>(Path.GetFileName(LibraryFile), StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Common.hashObject LibraryFileHash = new Common.hashObject(LibraryFile);
|
|
||||||
|
|
||||||
// check if file is in database
|
|
||||||
bool romFound = false;
|
|
||||||
for (var i = 0; i < dtRoms.Rows.Count; i++)
|
for (var i = 0; i < dtRoms.Rows.Count; i++)
|
||||||
{
|
{
|
||||||
long romId = (long)dtRoms.Rows[i]["Id"];
|
long romId = (long)dtRoms.Rows[i]["Id"];
|
||||||
string romPath = (string)dtRoms.Rows[i]["Path"];
|
string romPath = (string)dtRoms.Rows[i]["Path"];
|
||||||
string romMd5 = (string)dtRoms.Rows[i]["MD5"];
|
|
||||||
|
|
||||||
if ((LibraryFile == romPath) || (LibraryFileHash.md5hash == romMd5))
|
if (!romPath.StartsWith(library.Path))
|
||||||
{
|
{
|
||||||
romFound = true;
|
Logging.Log(Logging.LogType.Information, "Library Scan", " Deleting database entry for files with incorrect directory " + romPath);
|
||||||
break;
|
string deleteSql = "DELETE FROM Games_Roms WHERE Id=@id AND LibraryId=@libraryid";
|
||||||
|
Dictionary<string, object> deleteDict = new Dictionary<string, object>();
|
||||||
|
deleteDict.Add("Id", romId);
|
||||||
|
deleteDict.Add("libraryid", library.Id);
|
||||||
|
db.ExecuteCMD(deleteSql, deleteDict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (romFound == false)
|
|
||||||
{
|
|
||||||
// file is not in database - process it
|
|
||||||
Common.hashObject hash = new Common.hashObject(LibraryFile);
|
|
||||||
FileInfo fi = new FileInfo(LibraryFile);
|
|
||||||
|
|
||||||
Models.Signatures_Games sig = GetFileSignature(hash, fi, LibraryFile);
|
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Orphaned file found in library: " + LibraryFile);
|
|
||||||
|
|
||||||
// get discovered platform
|
|
||||||
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
|
|
||||||
if (determinedPlatform == null)
|
|
||||||
{
|
|
||||||
determinedPlatform = new IGDB.Models.Platform();
|
|
||||||
}
|
|
||||||
|
|
||||||
IGDB.Models.Game determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
|
|
||||||
|
|
||||||
StoreROM(hash, determinedGame, determinedPlatform, sig, LibraryFile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sql = "SELECT * FROM Games_Roms ORDER BY `name`";
|
sql = "SELECT * FROM Games_Roms ORDER BY `name`";
|
||||||
dtRoms = db.ExecuteCMD(sql);
|
dtRoms = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
// check all roms to see if their local file still exists
|
// search for files in the library that aren't in the database
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Checking library files exist on disk");
|
Logging.Log(Logging.LogType.Information, "Library Scan", "Looking for orphaned library files to add");
|
||||||
if (dtRoms.Rows.Count > 0)
|
string[] LibraryFiles = Directory.GetFiles(library.Path, "*.*", SearchOption.AllDirectories);
|
||||||
{
|
foreach (string LibraryFile in LibraryFiles)
|
||||||
for (var i = 0; i < dtRoms.Rows.Count; i++)
|
|
||||||
{
|
{
|
||||||
long romId = (long)dtRoms.Rows[i]["Id"];
|
if (!Common.SkippableFiles.Contains<string>(Path.GetFileName(LibraryFile), StringComparer.OrdinalIgnoreCase))
|
||||||
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"];
|
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Processing ROM at path " + romPath);
|
|
||||||
|
|
||||||
if (File.Exists(romPath))
|
|
||||||
{
|
{
|
||||||
// file exists, so lets check to make sure the signature was matched, and update if a signature can be found
|
Common.hashObject LibraryFileHash = new Common.hashObject(LibraryFile);
|
||||||
if (
|
|
||||||
romMetadataSource == gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType.None ||
|
// check if file is in database
|
||||||
(int)dtRoms.Rows[i]["MetadataVersion"] == 1
|
bool romFound = false;
|
||||||
)
|
for (var i = 0; i < dtRoms.Rows.Count; i++)
|
||||||
{
|
{
|
||||||
Common.hashObject hash = new Common.hashObject
|
long romId = (long)dtRoms.Rows[i]["Id"];
|
||||||
|
string romPath = (string)dtRoms.Rows[i]["Path"];
|
||||||
|
string romMd5 = (string)dtRoms.Rows[i]["MD5"];
|
||||||
|
|
||||||
|
if ((LibraryFile == romPath) || (LibraryFileHash.md5hash == romMd5))
|
||||||
{
|
{
|
||||||
md5hash = (string)dtRoms.Rows[i]["MD5"],
|
romFound = true;
|
||||||
sha1hash = (string)dtRoms.Rows[i]["SHA1"]
|
break;
|
||||||
};
|
|
||||||
FileInfo fi = new FileInfo(romPath);
|
|
||||||
|
|
||||||
Models.Signatures_Games sig = GetFileSignature(hash, fi, romPath);
|
|
||||||
if (sig.Rom.SignatureSource != gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType.None)
|
|
||||||
{
|
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Update signature found for " + romPath);
|
|
||||||
|
|
||||||
// get discovered platform
|
|
||||||
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
|
|
||||||
if (determinedPlatform == null)
|
|
||||||
{
|
|
||||||
determinedPlatform = new IGDB.Models.Platform();
|
|
||||||
}
|
|
||||||
|
|
||||||
IGDB.Models.Game determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
|
|
||||||
|
|
||||||
StoreROM(hash, determinedGame, determinedPlatform, sig, romPath, romId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (romPath != ComputeROMPath(romId))
|
if (romFound == false)
|
||||||
{
|
{
|
||||||
MoveGameFile(romId);
|
// file is not in database - process it
|
||||||
|
Common.hashObject hash = new Common.hashObject(LibraryFile);
|
||||||
|
FileInfo fi = new FileInfo(LibraryFile);
|
||||||
|
|
||||||
|
Models.Signatures_Games sig = GetFileSignature(hash, fi, LibraryFile);
|
||||||
|
|
||||||
|
Logging.Log(Logging.LogType.Information, "Library Scan", " Orphaned file found in library: " + LibraryFile);
|
||||||
|
|
||||||
|
// get discovered platform
|
||||||
|
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
|
||||||
|
|
||||||
|
IGDB.Models.Game determinedGame = new Game();
|
||||||
|
if (determinedPlatform == null)
|
||||||
|
{
|
||||||
|
if (library.DefaultPlatformId == 0)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
determinedGame = SearchForGame(sig.Game.Name, (long)determinedPlatform.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreROM(library, hash, determinedGame, determinedPlatform, sig, LibraryFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
// file doesn't exist where it's supposed to be! delete it from the db
|
|
||||||
Logging.Log(Logging.LogType.Warning, "Library Scan", " Deleting orphaned database entry for " + romPath);
|
|
||||||
|
|
||||||
string deleteSql = "DELETE FROM Games_Roms WHERE Id = @id";
|
sql = "SELECT * FROM Games_Roms WHERE LibraryId=@libraryid ORDER BY `name`";
|
||||||
Dictionary<string, object> deleteDict = new Dictionary<string, object>();
|
dtRoms = db.ExecuteCMD(sql, dbDict);
|
||||||
deleteDict.Add("id", romId);
|
|
||||||
db.ExecuteCMD(deleteSql, deleteDict);
|
// check all roms to see if their local file still exists
|
||||||
|
Logging.Log(Logging.LogType.Information, "Library Scan", "Checking library files exist on disk");
|
||||||
|
if (dtRoms.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < dtRoms.Rows.Count; i++)
|
||||||
|
{
|
||||||
|
long romId = (long)dtRoms.Rows[i]["Id"];
|
||||||
|
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"];
|
||||||
|
|
||||||
|
Logging.Log(Logging.LogType.Information, "Library Scan", " Processing ROM at path " + romPath);
|
||||||
|
|
||||||
|
if (File.Exists(romPath))
|
||||||
|
{
|
||||||
|
// file exists, so lets check to make sure the signature was matched, and update if a signature can be found
|
||||||
|
if (
|
||||||
|
romMetadataSource == gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType.None ||
|
||||||
|
(int)dtRoms.Rows[i]["MetadataVersion"] == 1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Common.hashObject hash = new Common.hashObject
|
||||||
|
{
|
||||||
|
md5hash = (string)dtRoms.Rows[i]["MD5"],
|
||||||
|
sha1hash = (string)dtRoms.Rows[i]["SHA1"]
|
||||||
|
};
|
||||||
|
FileInfo fi = new FileInfo(romPath);
|
||||||
|
|
||||||
|
Models.Signatures_Games sig = GetFileSignature(hash, fi, romPath);
|
||||||
|
if (sig.Rom.SignatureSource != gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType.None)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Information, "Library Scan", " Update signature found for " + romPath);
|
||||||
|
|
||||||
|
// get discovered platform
|
||||||
|
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
|
||||||
|
if (determinedPlatform == null)
|
||||||
|
{
|
||||||
|
determinedPlatform = new IGDB.Models.Platform();
|
||||||
|
}
|
||||||
|
|
||||||
|
IGDB.Models.Game determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
|
||||||
|
|
||||||
|
StoreROM(library, hash, determinedGame, determinedPlatform, sig, romPath, romId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (library.IsDefaultLibrary == true)
|
||||||
|
{
|
||||||
|
if (romPath != ComputeROMPath(romId))
|
||||||
|
{
|
||||||
|
MoveGameFile(romId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// file doesn't exist where it's supposed to be! delete it from the db
|
||||||
|
Logging.Log(Logging.LogType.Warning, "Library Scan", " Deleting orphaned database entry for " + romPath);
|
||||||
|
|
||||||
|
string deleteSql = "DELETE FROM Games_Roms WHERE Id = @id AND LibraryId = @libraryid";
|
||||||
|
Dictionary<string, object> deleteDict = new Dictionary<string, object>();
|
||||||
|
deleteDict.Add("id", romId);
|
||||||
|
deleteDict.Add("libraryid", library.Id);
|
||||||
|
db.ExecuteCMD(deleteSql, deleteDict);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Library scan completed");
|
Logging.Log(Logging.LogType.Information, "Library Scan", "Library scan completed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -4,6 +4,7 @@ using System.Reflection;
|
|||||||
using gaseous_tools;
|
using gaseous_tools;
|
||||||
using IGDB;
|
using IGDB;
|
||||||
using IGDB.Models;
|
using IGDB.Models;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
|
||||||
namespace gaseous_server.Classes.Metadata
|
namespace gaseous_server.Classes.Metadata
|
||||||
{
|
{
|
||||||
@@ -16,14 +17,32 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
Expired
|
Expired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, MemoryCacheObject> ObjectCache = new Dictionary<string, MemoryCacheObject>();
|
||||||
|
|
||||||
public static CacheStatus GetCacheStatus(string Endpoint, string Slug)
|
public static CacheStatus GetCacheStatus(string Endpoint, string Slug)
|
||||||
{
|
{
|
||||||
return _GetCacheStatus(Endpoint, "slug", Slug);
|
CacheClean();
|
||||||
|
if (ObjectCache.ContainsKey(Endpoint + Slug))
|
||||||
|
{
|
||||||
|
return CacheStatus.Current;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _GetCacheStatus(Endpoint, "slug", Slug);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CacheStatus GetCacheStatus(string Endpoint, long Id)
|
public static CacheStatus GetCacheStatus(string Endpoint, long Id)
|
||||||
{
|
{
|
||||||
return _GetCacheStatus(Endpoint, "id", Id);
|
CacheClean();
|
||||||
|
if (ObjectCache.ContainsKey(Endpoint + Id))
|
||||||
|
{
|
||||||
|
return CacheStatus.Current;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _GetCacheStatus(Endpoint, "id", Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CacheStatus GetCacheStatus(DataRow Row)
|
public static CacheStatus GetCacheStatus(DataRow Row)
|
||||||
@@ -164,6 +183,21 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
{
|
{
|
||||||
string Endpoint = EndpointType.GetType().Name;
|
string Endpoint = EndpointType.GetType().Name;
|
||||||
|
|
||||||
|
if (ObjectCache.ContainsKey(Endpoint + SearchValue))
|
||||||
|
{
|
||||||
|
MemoryCacheObject cacheObject = ObjectCache[Endpoint + SearchValue];
|
||||||
|
if (cacheObject.ExpiryTime < DateTime.UtcNow)
|
||||||
|
{
|
||||||
|
// object has expired, remove it
|
||||||
|
ObjectCache.Remove(Endpoint + SearchValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// object is valid, return it
|
||||||
|
return (T)cacheObject.Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 " + Endpoint + " WHERE " + SearchField + " = @" + SearchField;
|
string sql = "SELECT * FROM " + Endpoint + " WHERE " + SearchField + " = @" + SearchField;
|
||||||
@@ -181,7 +215,11 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DataRow dataRow = dt.Rows[0];
|
DataRow dataRow = dt.Rows[0];
|
||||||
return BuildCacheObject<T>(EndpointType, dataRow);
|
object returnObject = BuildCacheObject<T>(EndpointType, dataRow);
|
||||||
|
ObjectCache.Add(Endpoint + SearchValue, new MemoryCacheObject{
|
||||||
|
Object = returnObject
|
||||||
|
});
|
||||||
|
return (T)returnObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,6 +418,35 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
|
|
||||||
return EndpointType;
|
return EndpointType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void CacheClean()
|
||||||
|
{
|
||||||
|
if (ObjectCache == null)
|
||||||
|
{
|
||||||
|
ObjectCache = new Dictionary<string, MemoryCacheObject>();
|
||||||
|
}
|
||||||
|
Dictionary<string, MemoryCacheObject> workCache = ObjectCache;
|
||||||
|
foreach (KeyValuePair<string, MemoryCacheObject> objectCache in workCache)
|
||||||
|
{
|
||||||
|
if (objectCache.Value.ExpiryTime < DateTime.UtcNow)
|
||||||
|
{
|
||||||
|
ObjectCache.Remove(objectCache.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MemoryCacheObject
|
||||||
|
{
|
||||||
|
public object Object { get; set; }
|
||||||
|
public DateTime CreationTime { get; } = DateTime.UtcNow;
|
||||||
|
public DateTime ExpiryTime
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return CreationTime.AddMinutes(60);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -81,16 +81,19 @@ namespace gaseous_server.Classes
|
|||||||
public static void DeleteRom(long RomId)
|
public static void DeleteRom(long RomId)
|
||||||
{
|
{
|
||||||
GameRomItem rom = GetRom(RomId);
|
GameRomItem rom = GetRom(RomId);
|
||||||
if (File.Exists(rom.Path))
|
if (rom.Library.IsDefaultLibrary == true)
|
||||||
{
|
{
|
||||||
File.Delete(rom.Path);
|
if (File.Exists(rom.Path))
|
||||||
}
|
{
|
||||||
|
File.Delete(rom.Path);
|
||||||
|
}
|
||||||
|
|
||||||
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 = "DELETE FROM Games_Roms WHERE Id = @id";
|
string sql = "DELETE FROM Games_Roms WHERE 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);
|
||||||
db.ExecuteCMD(sql, dbDict);
|
db.ExecuteCMD(sql, dbDict);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GameRomItem BuildRom(DataRow romDR)
|
private static GameRomItem BuildRom(DataRow romDR)
|
||||||
@@ -103,9 +106,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"],
|
||||||
@@ -113,7 +116,8 @@ namespace gaseous_server.Classes
|
|||||||
MediaLabel = (string)romDR["medialabel"],
|
MediaLabel = (string)romDR["medialabel"],
|
||||||
Path = (string)romDR["path"],
|
Path = (string)romDR["path"],
|
||||||
Source = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(Int32)romDR["metadatasource"],
|
Source = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(Int32)romDR["metadatasource"],
|
||||||
SignatureSourceGameTitle = (string)Common.ReturnValueIfNull(romDR["MetadataGameName"], "")
|
SignatureSourceGameTitle = (string)Common.ReturnValueIfNull(romDR["MetadataGameName"], ""),
|
||||||
|
Library = GameLibrary.GetLibrary((int)romDR["LibraryId"])
|
||||||
};
|
};
|
||||||
|
|
||||||
// check for a web emulator and update the romItem
|
// check for a web emulator and update the romItem
|
||||||
@@ -153,6 +157,7 @@ namespace gaseous_server.Classes
|
|||||||
public string? Path { get; set; }
|
public string? Path { get; set; }
|
||||||
public gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType Source { get; set; }
|
public gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType Source { get; set; }
|
||||||
public string? SignatureSourceGameTitle { get; set;}
|
public string? SignatureSourceGameTitle { get; set;}
|
||||||
|
public GameLibrary.LibraryItem Library { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
@@ -212,12 +212,13 @@ namespace gaseous_server.SignatureIngestors.XML
|
|||||||
dbDict.Add("romtypemedia", Common.ReturnValueIfNull(romObject.RomTypeMedia, ""));
|
dbDict.Add("romtypemedia", Common.ReturnValueIfNull(romObject.RomTypeMedia, ""));
|
||||||
dbDict.Add("medialabel", Common.ReturnValueIfNull(romObject.MediaLabel, ""));
|
dbDict.Add("medialabel", Common.ReturnValueIfNull(romObject.MediaLabel, ""));
|
||||||
dbDict.Add("metadatasource", romObject.SignatureSource);
|
dbDict.Add("metadatasource", romObject.SignatureSource);
|
||||||
|
dbDict.Add("ingestorversion", 2);
|
||||||
|
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
if (sigDB.Rows.Count == 0)
|
if (sigDB.Rows.Count == 0)
|
||||||
{
|
{
|
||||||
// entry not present, insert it
|
// entry not present, insert it
|
||||||
sql = "INSERT INTO Signatures_Roms (GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, MetadataSource) VALUES (@gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @attributes, @romtype, @romtypemedia, @medialabel, @metadatasource); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
sql = "INSERT INTO Signatures_Roms (GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, MetadataSource, IngestorVersion) VALUES (@gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @attributes, @romtype, @romtypemedia, @medialabel, @metadatasource, @ingestorversion); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
|
||||||
|
77
gaseous-server/Controllers/LibraryController.cs
Normal file
77
gaseous-server/Controllers/LibraryController.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace gaseous_server.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/v1/[controller]")]
|
||||||
|
public class LibraryController : Controller
|
||||||
|
{
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType(typeof(List<GameLibrary.LibraryItem>), StatusCodes.Status200OK)]
|
||||||
|
public ActionResult GetLibraries()
|
||||||
|
{
|
||||||
|
return Ok(GameLibrary.GetLibraries);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{LibraryId}")]
|
||||||
|
[ProducesResponseType(typeof(GameLibrary.LibraryItem), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
public ActionResult GetLibrary(int LibraryId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Ok(GameLibrary.GetLibrary(LibraryId));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ProducesResponseType(typeof(GameLibrary.LibraryItem), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
||||||
|
public ActionResult AddLibrary(string Name, string Path, long DefaultPlatformId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Ok(GameLibrary.AddLibrary(Name, Path, DefaultPlatformId));
|
||||||
|
}
|
||||||
|
catch (GameLibrary.PathExists exPE)
|
||||||
|
{
|
||||||
|
return Conflict("Path already used in another library");
|
||||||
|
}
|
||||||
|
catch (GameLibrary.PathNotFound exPNF)
|
||||||
|
{
|
||||||
|
return NotFound("Path not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{LibraryId}")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
public ActionResult DelLibrary(int LibraryId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GameLibrary.DeleteLibrary(LibraryId);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
catch (GameLibrary.CannotDeleteDefaultLibrary exCDDL)
|
||||||
|
{
|
||||||
|
return BadRequest(exCDDL.ToString());
|
||||||
|
}
|
||||||
|
catch (GameLibrary.LibraryNotFound exLNF)
|
||||||
|
{
|
||||||
|
return NotFound(exLNF.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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
|
||||||
|
@@ -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"],
|
||||||
|
@@ -24,8 +24,10 @@ namespace gaseous_server.Controllers
|
|||||||
|
|
||||||
// disk size
|
// disk size
|
||||||
List<SystemInfo.PathItem> Disks = new List<SystemInfo.PathItem>();
|
List<SystemInfo.PathItem> Disks = new List<SystemInfo.PathItem>();
|
||||||
//Disks.Add(GetDisk(gaseous_tools.Config.ConfigurationPath));
|
foreach (GameLibrary.LibraryItem libraryItem in GameLibrary.GetLibraries)
|
||||||
Disks.Add(GetDisk(gaseous_tools.Config.LibraryConfiguration.LibraryRootDirectory));
|
{
|
||||||
|
Disks.Add(GetDisk(libraryItem.Path));
|
||||||
|
}
|
||||||
ReturnValue.Paths = Disks;
|
ReturnValue.Paths = Disks;
|
||||||
|
|
||||||
// database size
|
// database size
|
||||||
|
@@ -15,6 +15,8 @@ namespace gaseous_server.Models
|
|||||||
{
|
{
|
||||||
public class PlatformMapping
|
public class PlatformMapping
|
||||||
{
|
{
|
||||||
|
private static Dictionary<string, PlatformMapItem> PlatformMapCache = new Dictionary<string, PlatformMapItem>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the platform map from the embedded platform map resource
|
/// Updates the platform map from the embedded platform map resource
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -25,7 +27,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 +46,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 +54,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 +78,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +100,15 @@ namespace gaseous_server.Models
|
|||||||
List<PlatformMapItem> platformMaps = new List<PlatformMapItem>();
|
List<PlatformMapItem> platformMaps = new List<PlatformMapItem>();
|
||||||
foreach (DataRow row in data.Rows)
|
foreach (DataRow row in data.Rows)
|
||||||
{
|
{
|
||||||
platformMaps.Add(BuildPlatformMapItem(row));
|
long mapId = (long)row["Id"];
|
||||||
|
if (PlatformMapCache.ContainsKey(mapId.ToString()))
|
||||||
|
{
|
||||||
|
platformMaps.Add(PlatformMapCache[mapId.ToString()]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
platformMaps.Add(BuildPlatformMapItem(row));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
platformMaps.Sort((x, y) => x.IGDBName.CompareTo(y.IGDBName));
|
platformMaps.Sort((x, y) => x.IGDBName.CompareTo(y.IGDBName));
|
||||||
@@ -106,27 +119,34 @@ namespace gaseous_server.Models
|
|||||||
|
|
||||||
public static PlatformMapItem GetPlatformMap(long Id)
|
public static PlatformMapItem GetPlatformMap(long Id)
|
||||||
{
|
{
|
||||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
if (PlatformMapCache.ContainsKey(Id.ToString()))
|
||||||
string sql = "SELECT * FROM PlatformMap WHERE Id = @Id";
|
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
|
||||||
dbDict.Add("Id", Id);
|
|
||||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
|
||||||
|
|
||||||
if (data.Rows.Count > 0)
|
|
||||||
{
|
{
|
||||||
PlatformMapItem platformMap = BuildPlatformMapItem(data.Rows[0]);
|
return PlatformMapCache[Id.ToString()];
|
||||||
|
|
||||||
return platformMap;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Exception exception = new Exception("Platform Map Id " + Id + " does not exist.");
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
Logging.Log(Logging.LogType.Critical, "Platform Map", "Platform Map Id " + Id + " does not exist.", exception);
|
string sql = "SELECT * FROM PlatformMap WHERE Id = @Id";
|
||||||
throw exception;
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
dbDict.Add("Id", Id);
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
if (data.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
PlatformMapItem platformMap = BuildPlatformMapItem(data.Rows[0]);
|
||||||
|
|
||||||
|
return platformMap;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Exception exception = new Exception("Platform Map Id " + Id + " does not exist.");
|
||||||
|
Logging.Log(Logging.LogType.Critical, "Platform Map", "Platform Map Id " + Id + " does not exist.", exception);
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 +154,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 +174,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);
|
||||||
|
|
||||||
@@ -206,6 +235,11 @@ namespace gaseous_server.Models
|
|||||||
db.ExecuteCMD(sql, dbDict);
|
db.ExecuteCMD(sql, dbDict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PlatformMapCache.ContainsKey(item.IGDBId.ToString()))
|
||||||
|
{
|
||||||
|
PlatformMapCache.Remove(item.IGDBId.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PlatformMapItem BuildPlatformMapItem(DataRow row)
|
static PlatformMapItem BuildPlatformMapItem(DataRow row)
|
||||||
@@ -286,7 +320,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,10 +338,20 @@ 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;
|
||||||
|
|
||||||
|
if (PlatformMapCache.ContainsKey(IGDBId.ToString()))
|
||||||
|
{
|
||||||
|
PlatformMapCache[IGDBId.ToString()] = mapItem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlatformMapCache.Add(IGDBId.ToString(), mapItem);
|
||||||
|
}
|
||||||
|
|
||||||
return mapItem;
|
return mapItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,6 +422,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; }
|
||||||
|
@@ -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
|
||||||
|
@@ -9,10 +9,27 @@ 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
|
|
||||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
|
||||||
|
// check db availability
|
||||||
|
bool dbOnline = false;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Information, "Startup", "Waiting for database...");
|
||||||
|
if (db.TestConnection() == true)
|
||||||
|
{
|
||||||
|
dbOnline = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Thread.Sleep(30000);
|
||||||
|
}
|
||||||
|
} while (dbOnline == true);
|
||||||
|
|
||||||
|
// set up db
|
||||||
db.InitDB();
|
db.InitDB();
|
||||||
|
|
||||||
// load app settings
|
// load app settings
|
||||||
@@ -29,6 +46,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 +198,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
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Submodule gaseous-server/wwwroot/emulators/EmulatorJS updated: 4e8d11ece7...921f7a01c6
BIN
gaseous-server/wwwroot/images/EmulatorJS.png
Normal file
BIN
gaseous-server/wwwroot/images/EmulatorJS.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
4
gaseous-server/wwwroot/images/help.svg
Normal file
4
gaseous-server/wwwroot/images/help.svg
Normal 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 |
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
gaseous-server/wwwroot/pages/dialogs/librarydelete.html
Normal file
27
gaseous-server/wwwroot/pages/dialogs/librarydelete.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<p>Are you sure you want to delete this library?</p>
|
||||||
|
<p><strong>Warning:</strong> This cannot be undone!</p>
|
||||||
|
<div style="width: 100%; text-align: center;">
|
||||||
|
<div style="display: inline-block; margin-right: 20px;">
|
||||||
|
<button class="redbutton" value="Delete" onclick="deleteLibrary();">Delete</button>
|
||||||
|
</div>
|
||||||
|
<div style="display: inline-block; margin-left: 20px;">
|
||||||
|
<button value="Cancel" onclick="closeSubDialog();">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function deleteLibrary() {
|
||||||
|
ajaxCall(
|
||||||
|
'/api/v1/Library/' + subModalVariables,
|
||||||
|
'DELETE',
|
||||||
|
function (result) {
|
||||||
|
drawLibrary();
|
||||||
|
closeSubDialog();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
drawLibrary();
|
||||||
|
closeSubDialog();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
</script>
|
91
gaseous-server/wwwroot/pages/dialogs/librarynew.html
Normal file
91
gaseous-server/wwwroot/pages/dialogs/librarynew.html
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<div style="padding-top: 5px;">
|
||||||
|
<strong>New Library</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="width: 300px;">
|
||||||
|
<table style="width: 98%; margin-top: 15px; margin-bottom: 15px;">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<td><input type="text" id="newlibrary_name" style="width: 95%;" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Default Platform</th>
|
||||||
|
<td><select id="newlibrary_defaultplatform" style="width: 100%;"></select></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Path</th>
|
||||||
|
<td><input type="text" id="newlibrary_path" style="width: 95%;" /></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div style="width: 100%; text-align: right;">
|
||||||
|
<div style="display: inline-block; margin-right: 20px;">
|
||||||
|
<button value="OK" onclick="newLibrary();">OK</button>
|
||||||
|
</div>
|
||||||
|
<div style="display: inline-block;">
|
||||||
|
<button value="Cancel" onclick="closeSubDialog();">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$('#newlibrary_defaultplatform').select2({
|
||||||
|
minimumInputLength: 3,
|
||||||
|
ajax: {
|
||||||
|
url: '/api/v1/Search/Platform',
|
||||||
|
data: function (params) {
|
||||||
|
var query = {
|
||||||
|
SearchString: params.term
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query parameters will be ?SearchString=[term]
|
||||||
|
return query;
|
||||||
|
},
|
||||||
|
processResults: function (data) {
|
||||||
|
var arr = [];
|
||||||
|
|
||||||
|
arr.push({
|
||||||
|
id: 0,
|
||||||
|
text: 'Any'
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
arr.push({
|
||||||
|
id: data[i].id,
|
||||||
|
text: data[i].name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
results: arr
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.getElementById('newlibrary_defaultplatform').innerHTML = "<option value='" + 0 + "' selected='selected'>Any</option>";
|
||||||
|
|
||||||
|
function newLibrary() {
|
||||||
|
var libName = document.getElementById('newlibrary_name').value;
|
||||||
|
var libPlatform = $('#newlibrary_defaultplatform').select2('data');
|
||||||
|
var libPath = document.getElementById('newlibrary_path').value;
|
||||||
|
|
||||||
|
if (libName.length == 0) {
|
||||||
|
alert("A library name must be provided.")
|
||||||
|
} else if (libPath.length == 0) {
|
||||||
|
alert("A path must be provided.");
|
||||||
|
} else {
|
||||||
|
ajaxCall(
|
||||||
|
'/api/v1/Library?Name=' + encodeURIComponent(libName) + '&DefaultPlatformId=' + libPlatform[0].id + '&Path=' + encodeURIComponent(libPath),
|
||||||
|
'POST',
|
||||||
|
function(result) {
|
||||||
|
drawLibrary();
|
||||||
|
closeSubDialog();
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
alert('An error occurred while creating the library:\n\n' + JSON.stringify(error.responseText));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@@ -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>
|
@@ -7,6 +7,10 @@
|
|||||||
<div id="properties_bodypanel">
|
<div id="properties_bodypanel">
|
||||||
<div id="properties_bodypanel_general" name="properties_tab" style="display: none;">
|
<div id="properties_bodypanel_general" name="properties_tab" style="display: none;">
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
|
<tr>
|
||||||
|
<th>Library</th>
|
||||||
|
<td id="rominfo_library"></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Platform</th>
|
<th>Platform</th>
|
||||||
<td id="rominfo_platform"></td>
|
<td id="rominfo_platform"></td>
|
||||||
@@ -117,6 +121,7 @@
|
|||||||
ajaxCall('/api/v1/Games/' + gameId + '/roms/' + modalVariables, 'GET', function (result) {
|
ajaxCall('/api/v1/Games/' + gameId + '/roms/' + modalVariables, 'GET', function (result) {
|
||||||
romData = result;
|
romData = result;
|
||||||
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_platform').innerHTML = result.platform.name;
|
document.getElementById('rominfo_platform').innerHTML = result.platform.name;
|
||||||
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);
|
||||||
@@ -130,6 +135,10 @@
|
|||||||
document.getElementById('properties_fixplatform').innerHTML = "<option value='" + result.platform.id + "' selected='selected'>" + result.platform.name + "</option>";
|
document.getElementById('properties_fixplatform').innerHTML = "<option value='" + result.platform.id + "' selected='selected'>" + result.platform.name + "</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) {
|
||||||
|
document.getElementById('romDelete').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
if (result.attributes.length > 0) {
|
if (result.attributes.length > 0) {
|
||||||
document.getElementById('properties_bodypanel_attributes').appendChild(BuildAttributesTable(result.attributes, result.source));
|
document.getElementById('properties_bodypanel_attributes').appendChild(BuildAttributesTable(result.attributes, result.source));
|
||||||
} else {
|
} else {
|
||||||
|
@@ -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 = [
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
<div id="properties_toc" class="settings_toc">
|
<div id="properties_toc" class="settings_toc">
|
||||||
<div class="filter_header">Settings</div>
|
<div class="filter_header">Settings</div>
|
||||||
<div id="properties_toc_system" name="properties_toc_item" onclick="SelectTab('system');">System</div>
|
<div id="properties_toc_system" name="properties_toc_item" onclick="SelectTab('system');">System</div>
|
||||||
|
<div id="properties_toc_settings" name="properties_toc_item" onclick="SelectTab('settings');">Settings</div>
|
||||||
<div id="properties_toc_mapping" name="properties_toc_item" onclick="SelectTab('mapping');">Platform Mapping</div>
|
<div id="properties_toc_mapping" name="properties_toc_item" onclick="SelectTab('mapping');">Platform Mapping</div>
|
||||||
<div id="properties_toc_bios" name="properties_toc_item" onclick="SelectTab('bios');">Firmware</div>
|
<div id="properties_toc_bios" name="properties_toc_item" onclick="SelectTab('bios');">Firmware</div>
|
||||||
<div id="properties_toc_logs" name="properties_toc_item" onclick="SelectTab('logs');">Logs</div>
|
<div id="properties_toc_logs" name="properties_toc_item" onclick="SelectTab('logs');">Logs</div>
|
||||||
|
@@ -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>
|
||||||
|
@@ -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,
|
||||||
|
@@ -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
|
||||||
|
63
gaseous-server/wwwroot/pages/settings/settings.html
Normal file
63
gaseous-server/wwwroot/pages/settings/settings.html
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<div id="gametitle">
|
||||||
|
<h1 id="gametitle_label">Settings</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Libraries</h3>
|
||||||
|
<table id="settings_libraries" class="romtable" style="width: 100%;" cellspacing="0">
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<div style="text-align: right;"><button id="settings_newlibrary" onclick="showSubDialog('librarynew');">New Library</button></div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function drawLibrary() {
|
||||||
|
ajaxCall(
|
||||||
|
'/api/v1/Library',
|
||||||
|
'GET',
|
||||||
|
function (result) {
|
||||||
|
var newTable = document.getElementById('settings_libraries');
|
||||||
|
newTable.innerHTML = '';
|
||||||
|
newTable.appendChild(createTableRow(true, ['Name', 'Path', 'Default Platform', 'Default Library', '']));
|
||||||
|
|
||||||
|
for (var i = 0; i < result.length; i++) {
|
||||||
|
var platformName = '';
|
||||||
|
if (result[i].defaultPlatformId == 0) {
|
||||||
|
if (result[i].isDefaultLibrary == true) {
|
||||||
|
platformName = "n/a";
|
||||||
|
} else {
|
||||||
|
platformName = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
platformName = result[i].defaultPlatformName;
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultLibrary = '';
|
||||||
|
if (result[i].isDefaultLibrary == true) {
|
||||||
|
defaultLibrary = "Yes";
|
||||||
|
} else {
|
||||||
|
defaultLibrary = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
var deleteButton = '';
|
||||||
|
if (result[i].isDefaultLibrary == false) {
|
||||||
|
var deleteButton = '<a href="#" onclick="showSubDialog(\'librarydelete\', ' + result[i].id + ');" class="romlink"><img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" /></a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
newTable.appendChild(createTableRow(
|
||||||
|
false,
|
||||||
|
[
|
||||||
|
result[i].name,
|
||||||
|
result[i].path,
|
||||||
|
platformName,
|
||||||
|
defaultLibrary,
|
||||||
|
'<div style="text-align: right;">' + deleteButton + '</div>'
|
||||||
|
],
|
||||||
|
'romrow',
|
||||||
|
'romcell'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawLibrary();
|
||||||
|
</script>
|
@@ -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'));
|
||||||
|
@@ -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
|
||||||
{
|
{
|
||||||
@@ -104,6 +104,12 @@ namespace gaseous_tools
|
|||||||
".DS_STORE",
|
".DS_STORE",
|
||||||
"desktop.ini"
|
"desktop.ini"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static string NormalizePath(string path)
|
||||||
|
{
|
||||||
|
return Path.GetFullPath(new Uri(path).LocalPath)
|
||||||
|
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -183,7 +183,7 @@ namespace gaseous_tools
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "SELECT * FROM Settings WHERE Setting = @SettingName";
|
string sql = "SELECT Value FROM Settings WHERE Setting = @SettingName";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("SettingName", SettingName);
|
dbDict.Add("SettingName", SettingName);
|
||||||
dbDict.Add("Value", DefaultValue);
|
dbDict.Add("Value", DefaultValue);
|
||||||
@@ -337,13 +337,13 @@ namespace gaseous_tools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string LibraryDataDirectory
|
// public string LibraryDataDirectory
|
||||||
{
|
// {
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
return Path.Combine(LibraryRootDirectory, "Library");
|
// return Path.Combine(LibraryRootDirectory, "Library");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public string LibraryBIOSDirectory
|
public string LibraryBIOSDirectory
|
||||||
{
|
{
|
||||||
@@ -418,7 +418,6 @@ namespace gaseous_tools
|
|||||||
{
|
{
|
||||||
if (!Directory.Exists(LibraryRootDirectory)) { Directory.CreateDirectory(LibraryRootDirectory); }
|
if (!Directory.Exists(LibraryRootDirectory)) { Directory.CreateDirectory(LibraryRootDirectory); }
|
||||||
if (!Directory.Exists(LibraryImportDirectory)) { Directory.CreateDirectory(LibraryImportDirectory); }
|
if (!Directory.Exists(LibraryImportDirectory)) { Directory.CreateDirectory(LibraryImportDirectory); }
|
||||||
if (!Directory.Exists(LibraryDataDirectory)) { Directory.CreateDirectory(LibraryDataDirectory); }
|
|
||||||
if (!Directory.Exists(LibraryBIOSDirectory)) { Directory.CreateDirectory(LibraryBIOSDirectory); }
|
if (!Directory.Exists(LibraryBIOSDirectory)) { Directory.CreateDirectory(LibraryBIOSDirectory); }
|
||||||
if (!Directory.Exists(LibraryUploadDirectory)) { Directory.CreateDirectory(LibraryUploadDirectory); }
|
if (!Directory.Exists(LibraryUploadDirectory)) { Directory.CreateDirectory(LibraryUploadDirectory); }
|
||||||
if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); }
|
if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); }
|
||||||
|
@@ -206,6 +206,18 @@ namespace gaseous_tools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TestConnection()
|
||||||
|
{
|
||||||
|
switch (_ConnectorType)
|
||||||
|
{
|
||||||
|
case databaseType.MySql:
|
||||||
|
MySQLServerConnector conn = new MySQLServerConnector(_ConnectionString);
|
||||||
|
return conn.TestConnection();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class SQLTransactionItem
|
public class SQLTransactionItem
|
||||||
{
|
{
|
||||||
public SQLTransactionItem()
|
public SQLTransactionItem()
|
||||||
@@ -314,6 +326,20 @@ namespace gaseous_tools
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TestConnection()
|
||||||
|
{
|
||||||
|
MySqlConnection conn = new MySqlConnection(DBConn);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
conn.Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
gaseous-tools/Database/MySQL/gaseous-1003.sql
Normal file
2
gaseous-tools/Database/MySQL/gaseous-1003.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE `PlatformMap`
|
||||||
|
ADD COLUMN `AvailableWebEmulators` JSON NULL;
|
11
gaseous-tools/Database/MySQL/gaseous-1004.sql
Normal file
11
gaseous-tools/Database/MySQL/gaseous-1004.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
CREATE TABLE `GameLibraries` (
|
||||||
|
`Id` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`Name` VARCHAR(255) NOT NULL,
|
||||||
|
`Path` longtext NOT NULL,
|
||||||
|
`DefaultLibrary` int NOT NULL DEFAULT '0',
|
||||||
|
`DefaultPlatform` bigint NOT NULL DEFAULT '0',
|
||||||
|
PRIMARY KEY (`Id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE `Games_Roms`
|
||||||
|
ADD COLUMN `LibraryId` INT NULL DEFAULT 0 AFTER `MetadataVersion`;
|
@@ -5,26 +5,66 @@ 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)
|
||||||
|
{
|
||||||
|
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
case 1004:
|
||||||
|
// needs to run on start up
|
||||||
|
|
||||||
|
// copy root path to new libraries format
|
||||||
|
string oldRoot = Path.Combine(Config.LibraryConfiguration.LibraryRootDirectory, "Library");
|
||||||
|
string sql = "INSERT INTO GameLibraries (Name, Path, DefaultLibrary, DefaultPlatform) VALUES (@name, @path, @defaultlibrary, @defaultplatform); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
|
dbDict.Add("name", "Default");
|
||||||
|
dbDict.Add("path", oldRoot);
|
||||||
|
dbDict.Add("defaultlibrary", 1);
|
||||||
|
dbDict.Add("defaultplatform", 0);
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
// apply the new library id to the existing roms
|
||||||
|
sql = "UPDATE Games_Roms SET LibraryId=@libraryid;";
|
||||||
|
dbDict.Clear();
|
||||||
|
dbDict.Add("libraryid", data.Rows[0][0]);
|
||||||
|
db.ExecuteCMD(sql, dbDict);
|
||||||
|
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>();
|
||||||
|
@@ -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; } = "";
|
||||||
|
@@ -18,6 +18,8 @@
|
|||||||
<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" />
|
||||||
|
<None Remove="Database\MySQL\gaseous-1004.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Database\" />
|
<Folder Include="Database\" />
|
||||||
@@ -27,5 +29,7 @@
|
|||||||
<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" />
|
||||||
|
<EmbeddedResource Include="Database\MySQL\gaseous-1004.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
Reference in New Issue
Block a user