Integrate new Hasheous client (#354)
The new Hasheous client has been integrated into Gaseous to take advantage of the new updates to Hasheous that bring improved matching and community contributions.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -405,3 +405,5 @@ ASALocalRun/
|
||||
.localhistory/
|
||||
gaseous-server/.DS_Store
|
||||
gaseous-server/wwwroot/emulators/EmulatorJS
|
||||
.devcontainer/.env
|
||||
.mono/
|
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@@ -24,7 +24,8 @@
|
||||
},
|
||||
"sourceFileMap": {
|
||||
"/Views": "${workspaceFolder}/Views"
|
||||
}
|
||||
},
|
||||
"enableStepFiltering": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
|
20
Gaseous.sln
20
Gaseous.sln
@@ -1,4 +1,4 @@
|
||||
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 25.0.1704.4
|
||||
@@ -27,30 +27,18 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{08699C93-15CD-4E39-9053-D3C8056CE938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{08699C93-15CD-4E39-9053-D3C8056CE938}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{08699C93-15CD-4E39-9053-D3C8056CE938}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{08699C93-15CD-4E39-9053-D3C8056CE938}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {979BF092-AFBC-4F19-B55F-32E73959BD1A}
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{F1A847C7-57BC-4DA9-8F83-CD060A7F5122} = {17FA6F12-8532-420C-9489-CB8FDE42137C}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {979BF092-AFBC-4F19-B55F-32E73959BD1A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.IO.Compression;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
@@ -19,7 +20,8 @@ namespace gaseous_server.Classes
|
||||
if (ObjectToCheck == null || ObjectToCheck == System.DBNull.Value)
|
||||
{
|
||||
return IfNullValue;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
return ObjectToCheck;
|
||||
}
|
||||
@@ -155,6 +157,50 @@ namespace gaseous_server.Classes
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetLookupByCode(LookupTypes LookupType, string Code)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT Id FROM " + LookupType.ToString() + " WHERE Code = @code";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>{
|
||||
{ "code", Code }
|
||||
};
|
||||
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
if (data.Rows.Count == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (int)data.Rows[0]["Id"];
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetLookupByValue(LookupTypes LookupType, string Value)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT Id FROM " + LookupType.ToString() + " WHERE Value = @value";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>{
|
||||
{ "value", Value }
|
||||
};
|
||||
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
if (data.Rows.Count == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (int)data.Rows[0]["Id"];
|
||||
}
|
||||
}
|
||||
|
||||
public enum LookupTypes
|
||||
{
|
||||
Country,
|
||||
Language
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -80,7 +80,8 @@ namespace gaseous_server.Classes
|
||||
get
|
||||
{
|
||||
string logPath = Path.Combine(ConfigurationPath, "Logs");
|
||||
if (!Directory.Exists(logPath)) {
|
||||
if (!Directory.Exists(logPath))
|
||||
{
|
||||
Directory.CreateDirectory(logPath);
|
||||
}
|
||||
return logPath;
|
||||
@@ -131,7 +132,7 @@ namespace gaseous_server.Classes
|
||||
_config.DatabaseConfiguration.DatabaseName = (string)Common.GetEnvVar("dbname", _config.DatabaseConfiguration.DatabaseName);
|
||||
_config.DatabaseConfiguration.Port = int.Parse((string)Common.GetEnvVar("dbport", _config.DatabaseConfiguration.Port.ToString()));
|
||||
_config.MetadataConfiguration.MetadataSource = (HasheousClient.Models.MetadataModel.MetadataSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.MetadataSources), (string)Common.GetEnvVar("metadatasource", _config.MetadataConfiguration.MetadataSource.ToString()));
|
||||
_config.MetadataConfiguration.SignatureSource = (HasheousClient.Models.MetadataModel.SignatureSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.SignatureSources), (string)Common.GetEnvVar("signaturesource", _config.MetadataConfiguration.SignatureSource.ToString()));;
|
||||
_config.MetadataConfiguration.SignatureSource = (HasheousClient.Models.MetadataModel.SignatureSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.SignatureSources), (string)Common.GetEnvVar("signaturesource", _config.MetadataConfiguration.SignatureSource.ToString())); ;
|
||||
_config.MetadataConfiguration.MaxLibraryScanWorkers = int.Parse((string)Common.GetEnvVar("maxlibraryscanworkers", _config.MetadataConfiguration.MaxLibraryScanWorkers.ToString()));
|
||||
_config.MetadataConfiguration.HasheousHost = (string)Common.GetEnvVar("hasheoushost", _config.MetadataConfiguration.HasheousHost);
|
||||
_config.IGDBConfiguration.ClientId = (string)Common.GetEnvVar("igdbclientid", _config.IGDBConfiguration.ClientId);
|
||||
@@ -427,7 +428,8 @@ namespace gaseous_server.Classes
|
||||
|
||||
public class Database
|
||||
{
|
||||
private static string _DefaultHostName {
|
||||
private static string _DefaultHostName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("dbhost")))
|
||||
@@ -643,7 +645,7 @@ namespace gaseous_server.Classes
|
||||
return MetadataPath;
|
||||
}
|
||||
|
||||
public string LibrarySignatureImportDirectory
|
||||
public string LibrarySignaturesDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -651,6 +653,14 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
|
||||
public string LibrarySignaturesProcessedDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(LibraryRootDirectory, "Signatures - Processed");
|
||||
}
|
||||
}
|
||||
|
||||
public void InitLibrary()
|
||||
{
|
||||
if (!Directory.Exists(LibraryRootDirectory)) { Directory.CreateDirectory(LibraryRootDirectory); }
|
||||
@@ -660,7 +670,8 @@ namespace gaseous_server.Classes
|
||||
if (!Directory.Exists(LibraryMetadataDirectory)) { Directory.CreateDirectory(LibraryMetadataDirectory); }
|
||||
if (!Directory.Exists(LibraryTempDirectory)) { Directory.CreateDirectory(LibraryTempDirectory); }
|
||||
if (!Directory.Exists(LibraryCollectionsDirectory)) { Directory.CreateDirectory(LibraryCollectionsDirectory); }
|
||||
if (!Directory.Exists(LibrarySignatureImportDirectory)) { Directory.CreateDirectory(LibrarySignatureImportDirectory); }
|
||||
if (!Directory.Exists(LibrarySignaturesDirectory)) { Directory.CreateDirectory(LibrarySignaturesDirectory); }
|
||||
if (!Directory.Exists(LibrarySignaturesProcessedDirectory)) { Directory.CreateDirectory(LibrarySignaturesProcessedDirectory); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,6 +707,10 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _HasheousSubmitFixes { get; set; } = false;
|
||||
|
||||
private static string _HasheousAPIKey { get; set; } = "";
|
||||
|
||||
private static int _MaxLibraryScanWorkers
|
||||
{
|
||||
get
|
||||
@@ -730,6 +745,10 @@ namespace gaseous_server.Classes
|
||||
|
||||
public HasheousClient.Models.MetadataModel.SignatureSources SignatureSource = _SignatureSource;
|
||||
|
||||
public bool HasheousSubmitFixes = _HasheousSubmitFixes;
|
||||
|
||||
public string HasheousAPIKey = _HasheousAPIKey;
|
||||
|
||||
public int MaxLibraryScanWorkers = _MaxLibraryScanWorkers;
|
||||
|
||||
public string HasheousHost = _HasheousHost;
|
||||
|
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Models;
|
||||
using IGDB.Models;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
@@ -20,7 +23,7 @@ namespace gaseous_server.Classes
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Database", "Checking for pre-upgrade for schema version " + TargetSchemaVersion);
|
||||
|
||||
switch(DatabaseType)
|
||||
switch (DatabaseType)
|
||||
{
|
||||
case Database.databaseType.MySql:
|
||||
switch (TargetSchemaVersion)
|
||||
@@ -64,12 +67,14 @@ namespace gaseous_server.Classes
|
||||
|
||||
public static void PostUpgradeScript(int TargetSchemaVersion, Database.databaseType? DatabaseType)
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
DataTable data;
|
||||
|
||||
switch(DatabaseType)
|
||||
switch (DatabaseType)
|
||||
{
|
||||
case Database.databaseType.MySql:
|
||||
switch (TargetSchemaVersion)
|
||||
@@ -103,6 +108,51 @@ namespace gaseous_server.Classes
|
||||
sql = "DELETE FROM Settings WHERE Setting LIKE 'LastRun_%';";
|
||||
db.ExecuteNonQuery(sql);
|
||||
break;
|
||||
|
||||
case 1022:
|
||||
// load country list
|
||||
Logging.Log(Logging.LogType.Information, "Database Upgrade", "Adding country look up table contents");
|
||||
|
||||
string countryResourceName = "gaseous_server.Support.Country.txt";
|
||||
using (Stream stream = assembly.GetManifestResourceStream(countryResourceName))
|
||||
using (StreamReader reader = new StreamReader(stream))
|
||||
{
|
||||
do
|
||||
{
|
||||
string[] line = reader.ReadLine().Split("|");
|
||||
|
||||
sql = "INSERT INTO Country (Code, Value) VALUES (@code, @value);";
|
||||
dbDict = new Dictionary<string, object>{
|
||||
{ "code", line[0] },
|
||||
{ "value", line[1] }
|
||||
};
|
||||
db.ExecuteNonQuery(sql, dbDict);
|
||||
} while (reader.EndOfStream == false);
|
||||
}
|
||||
|
||||
// load language list
|
||||
Logging.Log(Logging.LogType.Information, "Database Upgrade", "Adding language look up table contents");
|
||||
|
||||
string languageResourceName = "gaseous_server.Support.Language.txt";
|
||||
using (Stream stream = assembly.GetManifestResourceStream(languageResourceName))
|
||||
using (StreamReader reader = new StreamReader(stream))
|
||||
{
|
||||
do
|
||||
{
|
||||
string[] line = reader.ReadLine().Split("|");
|
||||
|
||||
sql = "INSERT INTO Language (Code, Value) VALUES (@code, @value);";
|
||||
dbDict = new Dictionary<string, object>{
|
||||
{ "code", line[0] },
|
||||
{ "value", line[1] }
|
||||
};
|
||||
db.ExecuteNonQuery(sql, dbDict);
|
||||
} while (reader.EndOfStream == false);
|
||||
}
|
||||
|
||||
// this is a safe background task
|
||||
BackgroundUpgradeTargetSchemaVersions.Add(1022);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -117,11 +167,16 @@ namespace gaseous_server.Classes
|
||||
case 1002:
|
||||
MySql_1002_MigrateMetadataVersion();
|
||||
break;
|
||||
|
||||
case 1022:
|
||||
MySql_1022_MigrateMetadataVersion();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MySql_1002_MigrateMetadataVersion() {
|
||||
public static void MySql_1002_MigrateMetadataVersion()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
@@ -216,5 +271,36 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MySql_1022_MigrateMetadataVersion()
|
||||
{
|
||||
FileSignature fileSignature = new FileSignature();
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM Games_Roms WHERE RomDataVersion = 1;";
|
||||
DataTable data = db.ExecuteCMD(sql);
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Database Migration", "Updating ROM table for ROM: " + (string)row["Name"]);
|
||||
|
||||
GameLibrary.LibraryItem library = GameLibrary.GetLibrary((int)row["LibraryId"]);
|
||||
Common.hashObject hash = new Common.hashObject()
|
||||
{
|
||||
md5hash = (string)row["MD5"],
|
||||
sha1hash = (string)row["SHA1"]
|
||||
};
|
||||
Signatures_Games signature = fileSignature.GetFileSignature(
|
||||
library,
|
||||
hash,
|
||||
new FileInfo((string)row["Path"]),
|
||||
(string)row["Path"]
|
||||
);
|
||||
|
||||
Platform platform = Platforms.GetPlatform((long)row["PlatformId"], false);
|
||||
Game game = Games.GetGame((long)row["GameId"], false, false, false);
|
||||
|
||||
ImportGame.StoreROM(library, hash, game, platform, signature, (string)row["Path"], (long)row["Id"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,8 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO.Compression;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using HasheousClient.Models;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using NuGet.Common;
|
||||
using SevenZip;
|
||||
using SharpCompress.Archives;
|
||||
@@ -31,7 +33,7 @@ namespace gaseous_server.Classes
|
||||
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
|
||||
try
|
||||
{
|
||||
switch(ImportedFileExtension)
|
||||
switch (ImportedFileExtension)
|
||||
{
|
||||
case ".zip":
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Decompressing using zip");
|
||||
@@ -110,8 +112,10 @@ namespace gaseous_server.Classes
|
||||
// loop through contents until we find the first signature match
|
||||
List<ArchiveData> archiveFiles = new List<ArchiveData>();
|
||||
bool signatureFound = false;
|
||||
bool signatureSelectorAlreadyApplied = false;
|
||||
foreach (string file in Directory.GetFiles(ExtractPath, "*.*", SearchOption.AllDirectories))
|
||||
{
|
||||
bool signatureSelector = false;
|
||||
if (File.Exists(file))
|
||||
{
|
||||
FileInfo zfi = new FileInfo(file);
|
||||
@@ -121,15 +125,6 @@ namespace gaseous_server.Classes
|
||||
|
||||
if (zfi != null)
|
||||
{
|
||||
ArchiveData archiveData = new ArchiveData{
|
||||
FileName = Path.GetFileName(file),
|
||||
FilePath = zfi.Directory.FullName.Replace(ExtractPath, ""),
|
||||
Size = zfi.Length,
|
||||
MD5 = hash.md5hash,
|
||||
SHA1 = hash.sha1hash
|
||||
};
|
||||
archiveFiles.Add(archiveData);
|
||||
|
||||
if (signatureFound == false)
|
||||
{
|
||||
gaseous_server.Models.Signatures_Games zDiscoveredSignature = _GetFileSignature(zhash, zfi.Name, zfi.Extension, zfi.Length, file, true);
|
||||
@@ -151,15 +146,37 @@ namespace gaseous_server.Classes
|
||||
discoveredSignature = zDiscoveredSignature;
|
||||
|
||||
signatureFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (signatureSelectorAlreadyApplied == false)
|
||||
{
|
||||
signatureSelector = true;
|
||||
signatureSelectorAlreadyApplied = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
discoveredSignature.Rom.Attributes.Add(new KeyValuePair<string, object>(
|
||||
ArchiveData archiveData = new ArchiveData
|
||||
{
|
||||
FileName = Path.GetFileName(file),
|
||||
FilePath = zfi.Directory.FullName.Replace(ExtractPath, ""),
|
||||
Size = zfi.Length,
|
||||
MD5 = zhash.md5hash,
|
||||
SHA1 = zhash.sha1hash,
|
||||
isSignatureSelector = signatureSelector
|
||||
};
|
||||
archiveFiles.Add(archiveData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (discoveredSignature.Rom.Attributes == null)
|
||||
{
|
||||
discoveredSignature.Rom.Attributes = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
discoveredSignature.Rom.Attributes.Add(
|
||||
"ZipContents", Newtonsoft.Json.JsonConvert.SerializeObject(archiveFiles)
|
||||
));
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -264,29 +281,67 @@ namespace gaseous_server.Classes
|
||||
if (Config.MetadataConfiguration.SignatureSource == HasheousClient.Models.MetadataModel.SignatureSources.Hasheous)
|
||||
{
|
||||
HasheousClient.Hasheous hasheous = new HasheousClient.Hasheous();
|
||||
SignatureLookupItem? HasheousResult = hasheous.RetrieveFromHasheousAsync(new HashLookupModel{
|
||||
Console.WriteLine(HasheousClient.WebApp.HttpHelper.BaseUri);
|
||||
LookupItemModel? HasheousResult = null;
|
||||
try
|
||||
{
|
||||
HasheousResult = hasheous.RetrieveFromHasheous(new HashLookupModel
|
||||
{
|
||||
MD5 = hash.md5hash,
|
||||
SHA1 = hash.sha1hash
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Import Game", "An error occurred while importing " + ImageName, ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (HasheousResult != null)
|
||||
{
|
||||
if (HasheousResult.Signature != null)
|
||||
{
|
||||
gaseous_server.Models.Signatures_Games signature = new Models.Signatures_Games();
|
||||
signature.Game = HasheousResult.Signature.Game;
|
||||
signature.Rom = HasheousResult.Signature.Rom;
|
||||
string gameJson = Newtonsoft.Json.JsonConvert.SerializeObject(HasheousResult.Signature.Game);
|
||||
string romJson = Newtonsoft.Json.JsonConvert.SerializeObject(HasheousResult.Signature.Rom);
|
||||
signature.Game = Newtonsoft.Json.JsonConvert.DeserializeObject<Models.Signatures_Games.GameItem>(gameJson);
|
||||
signature.Rom = Newtonsoft.Json.JsonConvert.DeserializeObject<Models.Signatures_Games.RomItem>(romJson);
|
||||
|
||||
if (HasheousResult.MetadataResults != null)
|
||||
// get platform metadata
|
||||
if (HasheousResult.Platform != null)
|
||||
{
|
||||
if (HasheousResult.MetadataResults.Count > 0)
|
||||
if (HasheousResult.Platform.metadata.Count > 0)
|
||||
{
|
||||
foreach (SignatureLookupItem.MetadataResult metadataResult in HasheousResult.MetadataResults)
|
||||
foreach (HasheousClient.Models.MetadataItem metadataResult in HasheousResult.Platform.metadata)
|
||||
{
|
||||
if (metadataResult.Source == MetadataModel.MetadataSources.IGDB)
|
||||
if (metadataResult.Id.Length > 0)
|
||||
{
|
||||
signature.Flags.IGDBPlatformId = (long)metadataResult.PlatformId;
|
||||
signature.Flags.IGDBGameId = (long)metadataResult.GameId;
|
||||
switch (metadataResult.Source)
|
||||
{
|
||||
case HasheousClient.Models.MetadataSources.IGDB:
|
||||
signature.Flags.IGDBPlatformId = (long)Platforms.GetPlatform(metadataResult.Id, false).Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get game metadata
|
||||
if (HasheousResult.Metadata != null)
|
||||
{
|
||||
if (HasheousResult.Metadata.Count > 0)
|
||||
{
|
||||
foreach (HasheousClient.Models.MetadataItem metadataResult in HasheousResult.Metadata)
|
||||
{
|
||||
if (metadataResult.Id.Length > 0)
|
||||
{
|
||||
switch (metadataResult.Source)
|
||||
{
|
||||
case HasheousClient.Models.MetadataSources.IGDB:
|
||||
signature.Flags.IGDBGameId = (long)Games.GetGame(metadataResult.Id, false, false, false).Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -368,6 +423,7 @@ namespace gaseous_server.Classes
|
||||
public long Size { get; set; }
|
||||
public string MD5 { get; set; }
|
||||
public string SHA1 { get; set; }
|
||||
public bool isSignatureSelector { get; set; } = false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -28,7 +28,8 @@ namespace gaseous_server.Classes
|
||||
|
||||
// import files first
|
||||
int importCount = 1;
|
||||
foreach (string importContent in importContents) {
|
||||
foreach (string importContent in importContents)
|
||||
{
|
||||
SetStatus(importCount, importContents.Length, "Importing file: " + importContent);
|
||||
|
||||
ImportGameFile(importContent, null);
|
||||
@@ -197,8 +198,10 @@ namespace gaseous_server.Classes
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", " " + games.Length + " search results found");
|
||||
|
||||
// quite likely we've found sequels and alternate types
|
||||
foreach (Game game in games) {
|
||||
if (game.Name == SearchCandidate) {
|
||||
foreach (Game game in games)
|
||||
{
|
||||
if (game.Name == SearchCandidate)
|
||||
{
|
||||
// found game title matches the search candidate
|
||||
determinedGame = Metadata.Games.GetGame((long)games[0].Id, false, false, false);
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", "Found exact match!");
|
||||
@@ -273,7 +276,8 @@ namespace gaseous_server.Classes
|
||||
|
||||
// assumption: no games have () in their titles so we'll remove them
|
||||
int idx = GameName.IndexOf('(');
|
||||
if (idx >= 0) {
|
||||
if (idx >= 0)
|
||||
{
|
||||
GameName = GameName.Substring(0, idx);
|
||||
}
|
||||
|
||||
@@ -304,10 +308,11 @@ namespace gaseous_server.Classes
|
||||
|
||||
if (UpdateId == 0)
|
||||
{
|
||||
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
|
||||
sql = "INSERT INTO Games_Roms (PlatformId, GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, Path, MetadataSource, MetadataGameName, MetadataVersion, LibraryId, RomDataVersion) VALUES (@platformid, @gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @Attributes, @romtype, @romtypemedia, @medialabel, @path, @metadatasource, @metadatagamename, @metadataversion, @libraryid, @romdataversion); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
}
|
||||
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, RomDataVersion=@romdataversion WHERE Id=@id;";
|
||||
dbDict.Add("id", UpdateId);
|
||||
}
|
||||
dbDict.Add("platformid", Common.ReturnValueIfNull(determinedPlatform.Id, 0));
|
||||
@@ -322,6 +327,7 @@ namespace gaseous_server.Classes
|
||||
dbDict.Add("metadatagamename", discoveredSignature.Game.Name);
|
||||
dbDict.Add("metadataversion", 2);
|
||||
dbDict.Add("libraryid", library.Id);
|
||||
dbDict.Add("romdataversion", 2);
|
||||
|
||||
if (discoveredSignature.Rom.Attributes != null)
|
||||
{
|
||||
@@ -348,7 +354,8 @@ namespace gaseous_server.Classes
|
||||
if (UpdateId == 0)
|
||||
{
|
||||
romId = (long)romInsert.Rows[0][0];
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
romId = UpdateId;
|
||||
}
|
||||
@@ -645,7 +652,7 @@ namespace gaseous_server.Classes
|
||||
long PlatformId;
|
||||
IGDB.Models.Platform determinedPlatform;
|
||||
|
||||
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0 )
|
||||
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0)
|
||||
{
|
||||
// no platform discovered in the signature
|
||||
PlatformId = library.DefaultPlatformId;
|
||||
@@ -771,7 +778,7 @@ namespace gaseous_server.Classes
|
||||
long PlatformId;
|
||||
IGDB.Models.Platform determinedPlatform;
|
||||
|
||||
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0 )
|
||||
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0)
|
||||
{
|
||||
// no platform discovered in the signature
|
||||
PlatformId = library.DefaultPlatformId;
|
||||
|
@@ -17,7 +17,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
public class InvalidGameId : Exception
|
||||
{
|
||||
public InvalidGameId(long Id) : base("Unable to find Game by id " + Id)
|
||||
{}
|
||||
{ }
|
||||
}
|
||||
|
||||
public static Game? GetGame(long Id, bool getAllMetadata, bool followSubGames, bool forceRefresh)
|
||||
@@ -78,15 +78,17 @@ namespace gaseous_server.Classes.Metadata
|
||||
if (cacheStatus == Storage.CacheStatus.Current) { cacheStatus = Storage.CacheStatus.Expired; }
|
||||
}
|
||||
|
||||
// set up where clause
|
||||
string WhereClause = "";
|
||||
string searchField = "";
|
||||
switch (searchUsing)
|
||||
{
|
||||
case SearchUsing.id:
|
||||
WhereClause = "where id = " + searchValue;
|
||||
searchField = "id";
|
||||
break;
|
||||
case SearchUsing.slug:
|
||||
WhereClause = "where slug = " + searchValue;
|
||||
WhereClause = "where slug = \"" + searchValue + "\"";
|
||||
searchField = "slug";
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid search type");
|
||||
@@ -110,11 +112,11 @@ namespace gaseous_server.Classes.Metadata
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(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);
|
||||
returnValue = Storage.GetCacheValue<Game>(returnValue, searchField, searchValue);
|
||||
}
|
||||
return returnValue;
|
||||
case Storage.CacheStatus.Current:
|
||||
returnValue = Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);
|
||||
returnValue = Storage.GetCacheValue<Game>(returnValue, searchField, searchValue);
|
||||
UpdateSubClasses(returnValue, false, false, false);
|
||||
return returnValue;
|
||||
default:
|
||||
@@ -439,7 +441,8 @@ namespace gaseous_server.Classes.Metadata
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
Game game = new Game{
|
||||
Game game = new Game
|
||||
{
|
||||
Id = (long)row["Id"],
|
||||
Name = (string)Common.ReturnValueIfNull(row["Name"], ""),
|
||||
Slug = (string)Common.ReturnValueIfNull(row["Slug"], ""),
|
||||
|
@@ -44,7 +44,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
Task<Platform> RetVal = _GetPlatform(SearchUsing.id, Id, forceRefresh);
|
||||
return RetVal.Result;
|
||||
}
|
||||
catch(Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata", "An error occurred fetching Platform Id " + Id, ex);
|
||||
return null;
|
||||
@@ -78,13 +78,16 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
// set up where clause
|
||||
string WhereClause = "";
|
||||
string searchField = "";
|
||||
switch (searchUsing)
|
||||
{
|
||||
case SearchUsing.id:
|
||||
WhereClause = "where id = " + searchValue;
|
||||
searchField = "id";
|
||||
break;
|
||||
case SearchUsing.slug:
|
||||
WhereClause = "where slug = " + searchValue;
|
||||
WhereClause = "where slug = \"" + searchValue + "\"";
|
||||
searchField = "slug";
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid search type");
|
||||
@@ -111,10 +114,10 @@ namespace gaseous_server.Classes.Metadata
|
||||
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);
|
||||
return Storage.GetCacheValue<Platform>(returnValue, searchField, searchValue);
|
||||
}
|
||||
case Storage.CacheStatus.Current:
|
||||
return Storage.GetCacheValue<Platform>(returnValue, "id", (long)searchValue);
|
||||
return Storage.GetCacheValue<Platform>(returnValue, searchField, searchValue);
|
||||
default:
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
@@ -158,11 +161,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + platform.Name + " from predefined data.");
|
||||
// doesn't exist - add it
|
||||
item = new Models.PlatformMapping.PlatformMapItem{
|
||||
item = new Models.PlatformMapping.PlatformMapItem
|
||||
{
|
||||
IGDBId = (long)platform.Id,
|
||||
IGDBName = platform.Name,
|
||||
IGDBSlug = platform.Slug,
|
||||
AlternateNames = new List<string>{ platform.AlternativeName }
|
||||
AlternateNames = new List<string> { platform.AlternativeName }
|
||||
};
|
||||
Models.PlatformMapping.WritePlatformMap(item, false, true);
|
||||
}
|
||||
|
@@ -4,6 +4,9 @@ using gaseous_signature_parser.models.RomSignatureObject;
|
||||
using static gaseous_server.Classes.RomMediaGroup;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using IGDB.Models;
|
||||
using static HasheousClient.Models.FixMatchModel;
|
||||
using NuGet.Protocol.Core.Types;
|
||||
using static gaseous_server.Classes.FileSignature;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
@@ -12,7 +15,7 @@ namespace gaseous_server.Classes
|
||||
public class InvalidRomId : Exception
|
||||
{
|
||||
public InvalidRomId(long Id) : base("Unable to find ROM by id " + Id)
|
||||
{}
|
||||
{ }
|
||||
}
|
||||
|
||||
public static GameRomObject GetRoms(long GameId, long PlatformId = -1, string NameSearch = "", int pageNumber = 0, int pageSize = 0, string userid = "")
|
||||
@@ -37,13 +40,16 @@ namespace gaseous_server.Classes
|
||||
// platform query
|
||||
sqlPlatform = "SELECT DISTINCT Games_Roms.PlatformId, Platform.`Name` FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE GameId = @id ORDER BY Platform.`Name`;";
|
||||
|
||||
if (PlatformId == -1) {
|
||||
if (PlatformId == -1)
|
||||
{
|
||||
// data query
|
||||
sql = "SELECT DISTINCT Games_Roms.*, Platform.`Name` AS platformname, GameState.RomId AS SavedStateRomId FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id LEFT JOIN GameState ON (Games_Roms.Id = GameState.RomId AND GameState.UserId = @userid AND GameState.IsMediaGroup = 0) WHERE Games_Roms.GameId = @id" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
||||
|
||||
// count query
|
||||
sqlCount = "SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.GameId = @id" + NameSearchWhere + ";";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// data query
|
||||
sql = "SELECT DISTINCT Games_Roms.*, Platform.`Name` AS platformname, GameState.RomId AS SavedStateRomId FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id LEFT JOIN GameState ON (Games_Roms.Id = GameState.RomId AND GameState.UserId = @userid AND GameState.IsMediaGroup = 0) WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
||||
|
||||
@@ -118,6 +124,53 @@ namespace gaseous_server.Classes
|
||||
|
||||
GameRomItem rom = GetRom(RomId);
|
||||
|
||||
// send update to Hasheous if enabled
|
||||
if (PlatformId != 0 && GameId != 0)
|
||||
{
|
||||
if (Config.MetadataConfiguration.HasheousSubmitFixes == true)
|
||||
{
|
||||
if (
|
||||
Config.MetadataConfiguration.SignatureSource == HasheousClient.Models.MetadataModel.SignatureSources.Hasheous &&
|
||||
(
|
||||
Config.MetadataConfiguration.HasheousAPIKey != null &&
|
||||
Config.MetadataConfiguration.HasheousAPIKey != "")
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
// find signature used for identifing the rom
|
||||
string md5String = rom.Md5;
|
||||
string sha1String = rom.Sha1;
|
||||
if (rom.Attributes.ContainsKey("ZipContents"))
|
||||
{
|
||||
bool selectorFound = false;
|
||||
List<ArchiveData> archiveDataValues = Newtonsoft.Json.JsonConvert.DeserializeObject<List<ArchiveData>>(rom.Attributes["ZipContents"].ToString());
|
||||
foreach (ArchiveData archiveData in archiveDataValues)
|
||||
{
|
||||
if (archiveData.isSignatureSelector == true)
|
||||
{
|
||||
md5String = archiveData.MD5;
|
||||
sha1String = archiveData.SHA1;
|
||||
selectorFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HasheousClient.WebApp.HttpHelper.AddHeader("X-API-Key", Config.MetadataConfiguration.HasheousAPIKey);
|
||||
HasheousClient.Hasheous hasheousClient = new HasheousClient.Hasheous();
|
||||
List<MetadataMatch> metadataMatchList = new List<MetadataMatch>();
|
||||
metadataMatchList.Add(new MetadataMatch(HasheousClient.Models.MetadataSources.IGDB, platform.Slug, game.Slug));
|
||||
hasheousClient.FixMatch(new HasheousClient.Models.FixMatchModel(md5String, sha1String, metadataMatchList));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Fix Match", "An error occurred while sending a fixed match to Hasheous.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rom;
|
||||
}
|
||||
|
||||
@@ -150,6 +203,22 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string, object> romAttributes = new Dictionary<string, object>();
|
||||
if (romDR["attributes"] != DBNull.Value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ((string)romDR["attributes"] != "[ ]")
|
||||
{
|
||||
romAttributes = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>((string)romDR["attributes"]);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Roms", "Error parsing rom attributes: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
GameRomItem romItem = new GameRomItem
|
||||
{
|
||||
Id = (long)romDR["id"],
|
||||
@@ -162,8 +231,8 @@ namespace gaseous_server.Classes
|
||||
Md5 = ((string)romDR["md5"]).ToLower(),
|
||||
Sha1 = ((string)romDR["sha1"]).ToLower(),
|
||||
DevelopmentStatus = (string)romDR["developmentstatus"],
|
||||
Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(romDR["attributes"], "[ ]")),
|
||||
RomType = (HasheousClient.Models.LookupResponseModel.RomItem.RomTypes)(int)romDR["romtype"],
|
||||
Attributes = romAttributes,
|
||||
RomType = (HasheousClient.Models.SignatureModel.RomItem.RomTypes)(int)romDR["romtype"],
|
||||
RomTypeMedia = (string)romDR["romtypemedia"],
|
||||
MediaLabel = (string)romDR["medialabel"],
|
||||
Path = (string)romDR["path"],
|
||||
@@ -194,14 +263,14 @@ namespace gaseous_server.Classes
|
||||
public int Count { get; set; }
|
||||
}
|
||||
|
||||
public class GameRomItem : HasheousClient.Models.LookupResponseModel.RomItem
|
||||
public class GameRomItem : HasheousClient.Models.SignatureModel.RomItem
|
||||
{
|
||||
public long PlatformId { get; set; }
|
||||
public string Platform { get; set; }
|
||||
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
|
||||
public long GameId { get; set; }
|
||||
public string? Path { get; set; }
|
||||
public string? SignatureSourceGameTitle { get; set;}
|
||||
public string? SignatureSourceGameTitle { get; set; }
|
||||
public bool HasSaveStates { get; set; } = false;
|
||||
public GameLibrary.LibraryItem Library { get; set; }
|
||||
}
|
||||
|
@@ -8,21 +8,49 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
{
|
||||
public class XMLIngestor : QueueItemStatus
|
||||
{
|
||||
public void Import(string SearchPath, gaseous_signature_parser.parser.SignatureParser XMLType)
|
||||
public void Import(string SearchPath, string ProcessedDirectory, gaseous_signature_parser.parser.SignatureParser XMLType)
|
||||
{
|
||||
// connect to database
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
string? XMLDBSearchPath = null;
|
||||
string? XMLDBProcessedDirectory = null;
|
||||
if (XMLType == gaseous_signature_parser.parser.SignatureParser.NoIntro)
|
||||
{
|
||||
XMLDBSearchPath = Path.Combine(SearchPath, "DB");
|
||||
XMLDBProcessedDirectory = Path.Combine(ProcessedDirectory, "DB");
|
||||
SearchPath = Path.Combine(SearchPath, "DAT");
|
||||
ProcessedDirectory = Path.Combine(ProcessedDirectory, "DAT");
|
||||
}
|
||||
|
||||
// process provided files
|
||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - XML", "Importing from " + SearchPath);
|
||||
if (!Directory.Exists(SearchPath))
|
||||
{
|
||||
Directory.CreateDirectory(SearchPath);
|
||||
}
|
||||
if (!Directory.Exists(ProcessedDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(ProcessedDirectory);
|
||||
}
|
||||
|
||||
string[] PathContents = Directory.GetFiles(SearchPath);
|
||||
Array.Sort(PathContents);
|
||||
|
||||
string[]? DBPathContents = null;
|
||||
if (XMLDBSearchPath != null)
|
||||
{
|
||||
if (!Directory.Exists(XMLDBSearchPath))
|
||||
{
|
||||
Directory.CreateDirectory(XMLDBSearchPath);
|
||||
}
|
||||
if (!Directory.Exists(XMLDBProcessedDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(XMLDBProcessedDirectory);
|
||||
}
|
||||
|
||||
DBPathContents = Directory.GetFiles(XMLDBSearchPath);
|
||||
}
|
||||
|
||||
string sql = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
System.Data.DataTable sigDB;
|
||||
@@ -33,12 +61,28 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
|
||||
SetStatus(i + 1, PathContents.Length, "Processing signature file: " + XMLFile);
|
||||
|
||||
if (Common.SkippableFiles.Contains(Path.GetFileName(XMLFile), StringComparer.OrdinalIgnoreCase))
|
||||
Logging.Log(Logging.LogType.Information, "Signature Ingest", "(" + (i + 1) + " / " + PathContents.Length + ") Processing " + XMLType.ToString() + " DAT file: " + XMLFile);
|
||||
|
||||
string? DBFile = null;
|
||||
if (XMLDBSearchPath != null)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - XML", "Skipping file: " + XMLFile);
|
||||
switch (XMLType)
|
||||
{
|
||||
case gaseous_signature_parser.parser.SignatureParser.NoIntro:
|
||||
for (UInt16 x = 0; x < DBPathContents.Length; x++)
|
||||
{
|
||||
string tempDBFileName = Path.GetFileNameWithoutExtension(DBPathContents[x].Replace(" (DB Export)", ""));
|
||||
if (tempDBFileName == Path.GetFileNameWithoutExtension(XMLFile))
|
||||
{
|
||||
DBFile = DBPathContents[x];
|
||||
Logging.Log(Logging.LogType.Information, "Signature Ingest", "Using DB file: " + DBFile);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check xml file md5
|
||||
Common.hashObject hashObject = new Common.hashObject(XMLFile);
|
||||
sql = "SELECT * FROM Signatures_Sources WHERE SourceMD5=@sourcemd5";
|
||||
@@ -50,11 +94,9 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
{
|
||||
try
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - XML", "Importing file: " + XMLFile);
|
||||
|
||||
// start parsing file
|
||||
gaseous_signature_parser.parser Parser = new gaseous_signature_parser.parser();
|
||||
RomSignatureObject Object = Parser.ParseSignatureDAT(XMLFile, XMLType);
|
||||
RomSignatureObject Object = Parser.ParseSignatureDAT(XMLFile, DBFile, XMLType);
|
||||
|
||||
// store in database
|
||||
string[] flipNameAndDescription = {
|
||||
@@ -66,21 +108,27 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
bool processGames = false;
|
||||
if (Object.SourceMd5 != null)
|
||||
{
|
||||
sql = "SELECT * FROM Signatures_Sources WHERE SourceMD5=@sourcemd5";
|
||||
dbDict = new Dictionary<string, object>();
|
||||
string sourceUriStr = "";
|
||||
if (Object.Url != null)
|
||||
int sourceId = 0;
|
||||
|
||||
sql = "SELECT * FROM Signatures_Sources WHERE `SourceMD5`=@sourcemd5";
|
||||
dbDict = new Dictionary<string, object>
|
||||
{
|
||||
sourceUriStr = Object.Url.ToString();
|
||||
{ "name", Common.ReturnValueIfNull(Object.Name, "") },
|
||||
{ "description", Common.ReturnValueIfNull(Object.Description, "") },
|
||||
{ "category", Common.ReturnValueIfNull(Object.Category, "") },
|
||||
{ "version", Common.ReturnValueIfNull(Object.Version, "") },
|
||||
{ "author", Common.ReturnValueIfNull(Object.Author, "") },
|
||||
{ "email", Common.ReturnValueIfNull(Object.Email, "") },
|
||||
{ "homepage", Common.ReturnValueIfNull(Object.Homepage, "") }
|
||||
};
|
||||
if (Object.Url == null)
|
||||
{
|
||||
dbDict.Add("uri", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
dbDict.Add("uri", Common.ReturnValueIfNull(Object.Url.ToString(), ""));
|
||||
}
|
||||
dbDict.Add("name", Common.ReturnValueIfNull(Object.Name, ""));
|
||||
dbDict.Add("description", Common.ReturnValueIfNull(Object.Description, ""));
|
||||
dbDict.Add("category", Common.ReturnValueIfNull(Object.Category, ""));
|
||||
dbDict.Add("version", Common.ReturnValueIfNull(Object.Version, ""));
|
||||
dbDict.Add("author", Common.ReturnValueIfNull(Object.Author, ""));
|
||||
dbDict.Add("email", Common.ReturnValueIfNull(Object.Email, ""));
|
||||
dbDict.Add("homepage", Common.ReturnValueIfNull(Object.Homepage, ""));
|
||||
dbDict.Add("uri", sourceUriStr);
|
||||
dbDict.Add("sourcetype", Common.ReturnValueIfNull(Object.SourceType, ""));
|
||||
dbDict.Add("sourcemd5", Object.SourceMd5);
|
||||
dbDict.Add("sourcesha1", Object.SourceSHA1);
|
||||
@@ -89,9 +137,11 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
if (sigDB.Rows.Count == 0)
|
||||
{
|
||||
// entry not present, insert it
|
||||
sql = "INSERT INTO Signatures_Sources (Name, Description, Category, Version, Author, Email, Homepage, Url, SourceType, SourceMD5, SourceSHA1) VALUES (@name, @description, @category, @version, @author, @email, @homepage, @uri, @sourcetype, @sourcemd5, @sourcesha1)";
|
||||
sql = "INSERT INTO Signatures_Sources (`Name`, `Description`, `Category`, `Version`, `Author`, `Email`, `Homepage`, `Url`, `SourceType`, `SourceMD5`, `SourceSHA1`) VALUES (@name, @description, @category, @version, @author, @email, @homepage, @uri, @sourcetype, @sourcemd5, @sourcesha1); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
sourceId = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||
|
||||
processGames = true;
|
||||
}
|
||||
@@ -121,21 +171,88 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
dbDict.Add("platform", Common.ReturnValueIfNull(gameObject.System, ""));
|
||||
dbDict.Add("systemvariant", Common.ReturnValueIfNull(gameObject.SystemVariant, ""));
|
||||
dbDict.Add("video", Common.ReturnValueIfNull(gameObject.Video, ""));
|
||||
dbDict.Add("country", Common.ReturnValueIfNull(gameObject.Country, ""));
|
||||
dbDict.Add("language", Common.ReturnValueIfNull(gameObject.Language, ""));
|
||||
|
||||
List<int> gameCountries = new List<int>();
|
||||
if (
|
||||
gameObject.Country != null &&
|
||||
gameObject.Country != "Unknown"
|
||||
)
|
||||
{
|
||||
string[] countries = gameObject.Country.Split(",");
|
||||
foreach (string country in countries)
|
||||
{
|
||||
int countryId = -1;
|
||||
countryId = Common.GetLookupByCode(Common.LookupTypes.Country, (string)Common.ReturnValueIfNull(country.Trim(), ""));
|
||||
if (countryId == -1)
|
||||
{
|
||||
countryId = Common.GetLookupByValue(Common.LookupTypes.Country, (string)Common.ReturnValueIfNull(country.Trim(), ""));
|
||||
|
||||
if (countryId == -1)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Signature Ingest", "Unable to locate country id for " + country.Trim());
|
||||
sql = "INSERT INTO Country (`Code`, `Value`) VALUES (@code, @name); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
Dictionary<string, object> countryDict = new Dictionary<string, object>{
|
||||
{ "code", country.Trim() },
|
||||
{ "name", country.Trim() }
|
||||
};
|
||||
countryId = int.Parse(db.ExecuteCMD(sql, countryDict).Rows[0][0].ToString());
|
||||
}
|
||||
}
|
||||
|
||||
if (countryId > 0)
|
||||
{
|
||||
gameCountries.Add(countryId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<int> gameLanguages = new List<int>();
|
||||
if (
|
||||
gameObject.Language != null &&
|
||||
gameObject.Language != "nolang"
|
||||
)
|
||||
{
|
||||
string[] languages = gameObject.Language.Split(",");
|
||||
foreach (string language in languages)
|
||||
{
|
||||
int languageId = -1;
|
||||
languageId = Common.GetLookupByCode(Common.LookupTypes.Language, (string)Common.ReturnValueIfNull(language.Trim(), ""));
|
||||
if (languageId == -1)
|
||||
{
|
||||
languageId = Common.GetLookupByValue(Common.LookupTypes.Language, (string)Common.ReturnValueIfNull(language.Trim(), ""));
|
||||
|
||||
if (languageId == -1)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Signature Ingest", "Unable to locate language id for " + language.Trim());
|
||||
sql = "INSERT INTO Language (`Code`, `Value`) VALUES (@code, @name); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
Dictionary<string, object> langDict = new Dictionary<string, object>{
|
||||
{ "code", language.Trim() },
|
||||
{ "name", language.Trim() }
|
||||
};
|
||||
languageId = int.Parse(db.ExecuteCMD(sql, langDict).Rows[0][0].ToString());
|
||||
}
|
||||
}
|
||||
|
||||
if (languageId > 0)
|
||||
{
|
||||
gameLanguages.Add(languageId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbDict.Add("copyright", Common.ReturnValueIfNull(gameObject.Copyright, ""));
|
||||
|
||||
// store platform
|
||||
int gameSystem = 0;
|
||||
if (gameObject.System != null)
|
||||
{
|
||||
sql = "SELECT Id FROM Signatures_Platforms WHERE Platform=@platform";
|
||||
sql = "SELECT `Id` FROM Signatures_Platforms WHERE `Platform`=@platform";
|
||||
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
if (sigDB.Rows.Count == 0)
|
||||
{
|
||||
// entry not present, insert it
|
||||
sql = "INSERT INTO Signatures_Platforms (Platform) VALUES (@platform); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
sql = "INSERT INTO Signatures_Platforms (`Platform`) VALUES (@platform); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
gameSystem = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||
@@ -151,13 +268,13 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
int gamePublisher = 0;
|
||||
if (gameObject.Publisher != null)
|
||||
{
|
||||
sql = "SELECT * FROM Signatures_Publishers WHERE Publisher=@publisher";
|
||||
sql = "SELECT * FROM Signatures_Publishers WHERE `Publisher`=@publisher";
|
||||
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
if (sigDB.Rows.Count == 0)
|
||||
{
|
||||
// entry not present, insert it
|
||||
sql = "INSERT INTO Signatures_Publishers (Publisher) VALUES (@publisher); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
sql = "INSERT INTO Signatures_Publishers (`Publisher`) VALUES (@publisher); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
gamePublisher = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||
}
|
||||
@@ -169,16 +286,16 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
dbDict.Add("publisherid", gamePublisher);
|
||||
|
||||
// store game
|
||||
int gameId = 0;
|
||||
sql = "SELECT * FROM Signatures_Games WHERE Name=@name AND Year=@year AND Publisherid=@publisher AND Systemid=@systemid AND Country=@country AND Language=@language";
|
||||
long gameId = 0;
|
||||
sql = "SELECT * FROM Signatures_Games WHERE `Name`=@name AND `Year`=@year AND `PublisherId`=@publisherid AND `SystemId`=@systemid";
|
||||
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
if (sigDB.Rows.Count == 0)
|
||||
{
|
||||
// entry not present, insert it
|
||||
sql = "INSERT INTO Signatures_Games " +
|
||||
"(Name, Description, Year, PublisherId, Demo, SystemId, SystemVariant, Video, Country, Language, Copyright) VALUES " +
|
||||
"(@name, @description, @year, @publisherid, @demo, @systemid, @systemvariant, @video, @country, @language, @copyright); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
"(`Name`, `Description`, `Year`, `PublisherId`, `Demo`, `SystemId`, `SystemVariant`, `Video`, `Copyright`) VALUES " +
|
||||
"(@name, @description, @year, @publisherid, @demo, @systemid, @systemvariant, @video, @copyright); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
gameId = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||
@@ -188,13 +305,57 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
gameId = (int)sigDB.Rows[0][0];
|
||||
}
|
||||
|
||||
// insert countries
|
||||
foreach (int gameCountry in gameCountries)
|
||||
{
|
||||
try
|
||||
{
|
||||
sql = "SELECT * FROM Signatures_Games_Countries WHERE GameId = @gameid AND CountryId = @Countryid";
|
||||
Dictionary<string, object> countryDict = new Dictionary<string, object>{
|
||||
{ "gameid", gameId },
|
||||
{ "Countryid", gameCountry }
|
||||
};
|
||||
if (db.ExecuteCMD(sql, countryDict).Rows.Count == 0)
|
||||
{
|
||||
sql = "INSERT INTO Signatures_Games_Countries (GameId, CountryId) VALUES (@gameid, @Countryid)";
|
||||
db.ExecuteCMD(sql, countryDict);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Game id: " + gameId + " with Country " + gameCountry);
|
||||
}
|
||||
}
|
||||
|
||||
// insert languages
|
||||
foreach (int gameLanguage in gameLanguages)
|
||||
{
|
||||
try
|
||||
{
|
||||
sql = "SELECT * FROM Signatures_Games_Languages WHERE GameId = @gameid AND LanguageId = @languageid";
|
||||
Dictionary<string, object> langDict = new Dictionary<string, object>{
|
||||
{ "gameid", gameId },
|
||||
{ "languageid", gameLanguage }
|
||||
};
|
||||
if (db.ExecuteCMD(sql, langDict).Rows.Count == 0)
|
||||
{
|
||||
sql = "INSERT INTO Signatures_Games_Languages (GameId, LanguageId) VALUES (@gameid, @languageid)";
|
||||
db.ExecuteCMD(sql, langDict);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Game id: " + gameId + " with language " + gameLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
// store rom
|
||||
foreach (RomSignatureObject.Game.Rom romObject in gameObject.Roms)
|
||||
{
|
||||
if (romObject.Md5 != null || romObject.Sha1 != null)
|
||||
{
|
||||
int romId = 0;
|
||||
sql = "SELECT * FROM Signatures_Roms WHERE GameId=@gameid AND MD5=@md5";
|
||||
long romId = 0;
|
||||
sql = "SELECT * FROM Signatures_Roms WHERE `GameId`=@gameid AND (`MD5`=@md5 OR `SHA1`=@sha1)";
|
||||
dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("gameid", gameId);
|
||||
dbDict.Add("name", Common.ReturnValueIfNull(romObject.Name, ""));
|
||||
@@ -212,12 +373,12 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
}
|
||||
else
|
||||
{
|
||||
dbDict.Add("attributes", "[ ]");
|
||||
dbDict.Add("attributes", "");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbDict.Add("attributes", "[ ]");
|
||||
dbDict.Add("attributes", "");
|
||||
}
|
||||
dbDict.Add("romtype", (int)romObject.RomType);
|
||||
dbDict.Add("romtypemedia", Common.ReturnValueIfNull(romObject.RomTypeMedia, ""));
|
||||
@@ -229,30 +390,51 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
if (sigDB.Rows.Count == 0)
|
||||
{
|
||||
// entry not present, insert it
|
||||
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);";
|
||||
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);
|
||||
|
||||
|
||||
romId = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
romId = (int)sigDB.Rows[0][0];
|
||||
}
|
||||
|
||||
// map the rom to the source
|
||||
sql = "SELECT * FROM Signatures_RomToSource WHERE SourceId=@sourceid AND RomId=@romid;";
|
||||
dbDict.Add("romid", romId);
|
||||
dbDict.Add("sourceId", sourceId);
|
||||
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
if (sigDB.Rows.Count == 0)
|
||||
{
|
||||
sql = "INSERT INTO Signatures_RomToSource (`SourceId`, `RomId`) VALUES (@sourceid, @romid);";
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File.Move(XMLFile, Path.Combine(ProcessedDirectory, Path.GetFileName(XMLFile)));
|
||||
if (DBFile != null)
|
||||
{
|
||||
File.Move(DBFile, Path.Combine(XMLDBProcessedDirectory, Path.GetFileName(DBFile)));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Signature Ingestor - XML", "Invalid import file: " + XMLFile, ex);
|
||||
Logging.Log(Logging.LogType.Warning, "Signature Ingest", "Error ingesting " + XMLType.ToString() + " file: " + XMLFile, ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Debug, "Signature Ingestor - XML", "Rejecting already imported file: " + XMLFile);
|
||||
Logging.Log(Logging.LogType.Information, "Signature Ingest", "Rejecting already imported " + XMLType.ToString() + " file: " + XMLFile);
|
||||
File.Move(XMLFile, Path.Combine(ProcessedDirectory, Path.GetFileName(XMLFile)));
|
||||
if (DBFile != null)
|
||||
{
|
||||
File.Move(DBFile, Path.Combine(XMLDBProcessedDirectory, Path.GetFileName(DBFile)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System.Data;
|
||||
using gaseous_signature_parser.models.RomSignatureObject;
|
||||
using static gaseous_server.Classes.Common;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
@@ -10,7 +11,8 @@ namespace gaseous_server.Classes
|
||||
if (md5.Length > 0)
|
||||
{
|
||||
return _GetSignature("Signatures_Roms.md5 = @searchstring", md5);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
return _GetSignature("Signatures_Roms.sha1 = @searchstring", sha1);
|
||||
}
|
||||
@@ -21,7 +23,8 @@ namespace gaseous_server.Classes
|
||||
if (TosecName.Length > 0)
|
||||
{
|
||||
return _GetSignature("Signatures_Roms.name = @searchstring", TosecName);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -44,7 +47,7 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
Game = new gaseous_server.Models.Signatures_Games.GameItem
|
||||
{
|
||||
Id = (Int32)sigDbRow["Id"],
|
||||
Id = (long)(int)sigDbRow["Id"],
|
||||
Name = (string)sigDbRow["Name"],
|
||||
Description = (string)sigDbRow["Description"],
|
||||
Year = (string)sigDbRow["Year"],
|
||||
@@ -53,20 +56,20 @@ namespace gaseous_server.Classes
|
||||
System = (string)sigDbRow["Platform"],
|
||||
SystemVariant = (string)sigDbRow["SystemVariant"],
|
||||
Video = (string)sigDbRow["Video"],
|
||||
Country = (string)sigDbRow["Country"],
|
||||
Language = (string)sigDbRow["Language"],
|
||||
Countries = new Dictionary<string, string>(GetLookup(LookupTypes.Country, (long)(int)sigDbRow["Id"])),
|
||||
Languages = new Dictionary<string, string>(GetLookup(LookupTypes.Language, (long)(int)sigDbRow["Id"])),
|
||||
Copyright = (string)sigDbRow["Copyright"]
|
||||
},
|
||||
Rom = new gaseous_server.Models.Signatures_Games.RomItem
|
||||
{
|
||||
Id = (Int32)sigDbRow["romid"],
|
||||
Id = (long)(int)sigDbRow["romid"],
|
||||
Name = (string)sigDbRow["romname"],
|
||||
Size = (Int64)sigDbRow["Size"],
|
||||
Crc = (string)sigDbRow["CRC"],
|
||||
Md5 = ((string)sigDbRow["MD5"]).ToLower(),
|
||||
Sha1 = ((string)sigDbRow["SHA1"]).ToLower(),
|
||||
DevelopmentStatus = (string)sigDbRow["DevelopmentStatus"],
|
||||
Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(sigDbRow["Attributes"], "[]")),
|
||||
Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>((string)Common.ReturnValueIfNull(sigDbRow["Attributes"], "[]")),
|
||||
RomType = (gaseous_server.Models.Signatures_Games.RomItem.RomTypes)(int)sigDbRow["RomType"],
|
||||
RomTypeMedia = (string)sigDbRow["RomTypeMedia"],
|
||||
MediaLabel = (string)sigDbRow["MediaLabel"],
|
||||
@@ -77,5 +80,36 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
return GamesList;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetLookup(LookupTypes LookupType, long GameId)
|
||||
{
|
||||
string tableName = "";
|
||||
switch (LookupType)
|
||||
{
|
||||
case LookupTypes.Country:
|
||||
tableName = "Countries";
|
||||
break;
|
||||
|
||||
case LookupTypes.Language:
|
||||
tableName = "Languages";
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT " + LookupType.ToString() + ".Code, " + LookupType.ToString() + ".Value FROM Signatures_Games_" + tableName + " JOIN " + LookupType.ToString() + " ON Signatures_Games_" + tableName + "." + LookupType.ToString() + "Id = " + LookupType.ToString() + ".Id WHERE Signatures_Games_" + tableName + ".GameId = @id;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>{
|
||||
{ "id", GameId }
|
||||
};
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
Dictionary<string, string> returnDict = new Dictionary<string, string>();
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
returnDict.Add((string)row["Code"], (string)row["Value"]);
|
||||
}
|
||||
|
||||
return returnDict;
|
||||
}
|
||||
}
|
||||
}
|
@@ -70,7 +70,8 @@ namespace gaseous_server.Controllers
|
||||
[HttpGet]
|
||||
[Route("Version")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Version GetSystemVersion() {
|
||||
public Version GetSystemVersion()
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().GetName().Version;
|
||||
}
|
||||
|
||||
@@ -80,18 +81,19 @@ namespace gaseous_server.Controllers
|
||||
[Route("VersionFile")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public FileContentResult GetSystemVersionAsFile() {
|
||||
public FileContentResult GetSystemVersionAsFile()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
// get age ratings dictionary
|
||||
Dictionary<int, string> ClassificationBoardsStrings = new Dictionary<int, string>();
|
||||
foreach(IGDB.Models.AgeRatingCategory ageRatingCategory in Enum.GetValues(typeof(IGDB.Models.AgeRatingCategory)) )
|
||||
foreach (IGDB.Models.AgeRatingCategory ageRatingCategory in Enum.GetValues(typeof(IGDB.Models.AgeRatingCategory)))
|
||||
{
|
||||
ClassificationBoardsStrings.Add((int)ageRatingCategory, ageRatingCategory.ToString());
|
||||
}
|
||||
|
||||
Dictionary<int, string> AgeRatingsStrings = new Dictionary<int, string>();
|
||||
foreach(IGDB.Models.AgeRatingTitle ageRatingTitle in Enum.GetValues(typeof(IGDB.Models.AgeRatingTitle)) )
|
||||
foreach (IGDB.Models.AgeRatingTitle ageRatingTitle in Enum.GetValues(typeof(IGDB.Models.AgeRatingTitle)))
|
||||
{
|
||||
AgeRatingsStrings.Add((int)ageRatingTitle, ageRatingTitle.ToString());
|
||||
}
|
||||
@@ -99,13 +101,16 @@ namespace gaseous_server.Controllers
|
||||
string ver = "var AppVersion = \"" + Assembly.GetExecutingAssembly().GetName().Version.ToString() + "\";" + Environment.NewLine +
|
||||
"var DBSchemaVersion = \"" + db.GetDatabaseSchemaVersion() + "\";" + Environment.NewLine +
|
||||
"var FirstRunStatus = " + Config.ReadSetting<string>("FirstRunStatus", "0") + ";" + Environment.NewLine +
|
||||
"var AgeRatingBoardsStrings = " + JsonSerializer.Serialize(ClassificationBoardsStrings, new JsonSerializerOptions{
|
||||
"var AgeRatingBoardsStrings = " + JsonSerializer.Serialize(ClassificationBoardsStrings, new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
}) + ";" + Environment.NewLine +
|
||||
"var AgeRatingStrings = " + JsonSerializer.Serialize(AgeRatingsStrings, new JsonSerializerOptions{
|
||||
"var AgeRatingStrings = " + JsonSerializer.Serialize(AgeRatingsStrings, new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
}) + ";" + Environment.NewLine +
|
||||
"var AgeRatingGroups = " + JsonSerializer.Serialize(AgeGroups.AgeGroupingsFlat, new JsonSerializerOptions{
|
||||
"var AgeRatingGroups = " + JsonSerializer.Serialize(AgeGroups.AgeGroupingsFlat, new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
}) + ";" + Environment.NewLine +
|
||||
"var emulatorDebugMode = " + Config.ReadSetting<string>("emulatorDebugMode", false.ToString()).ToLower() + ";";
|
||||
@@ -251,10 +256,18 @@ namespace gaseous_server.Controllers
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public ActionResult GetSystemSettings()
|
||||
{
|
||||
SystemSettingsModel systemSettingsModel = new SystemSettingsModel{
|
||||
SystemSettingsModel systemSettingsModel = new SystemSettingsModel
|
||||
{
|
||||
AlwaysLogToDisk = Config.LoggingConfiguration.AlwaysLogToDisk,
|
||||
MinimumLogRetentionPeriod = Config.LoggingConfiguration.LogRetention,
|
||||
EmulatorDebugMode = Boolean.Parse(Config.ReadSetting<string>("emulatorDebugMode", false.ToString()))
|
||||
EmulatorDebugMode = Boolean.Parse(Config.ReadSetting<string>("emulatorDebugMode", false.ToString())),
|
||||
SignatureSource = new SystemSettingsModel.SignatureSourceItem()
|
||||
{
|
||||
Source = Config.MetadataConfiguration.SignatureSource,
|
||||
HasheousHost = Config.MetadataConfiguration.HasheousHost,
|
||||
HasheousSubmitFixes = (bool)Config.MetadataConfiguration.HasheousSubmitFixes,
|
||||
HasheousAPIKey = Config.MetadataConfiguration.HasheousAPIKey
|
||||
}
|
||||
};
|
||||
|
||||
return Ok(systemSettingsModel);
|
||||
@@ -273,6 +286,10 @@ namespace gaseous_server.Controllers
|
||||
Config.LoggingConfiguration.AlwaysLogToDisk = model.AlwaysLogToDisk;
|
||||
Config.LoggingConfiguration.LogRetention = model.MinimumLogRetentionPeriod;
|
||||
Config.SetSetting<string>("emulatorDebugMode", model.EmulatorDebugMode.ToString());
|
||||
Config.MetadataConfiguration.SignatureSource = model.SignatureSource.Source;
|
||||
Config.MetadataConfiguration.HasheousHost = model.SignatureSource.HasheousHost;
|
||||
Config.MetadataConfiguration.HasheousAPIKey = model.SignatureSource.HasheousAPIKey;
|
||||
Config.MetadataConfiguration.HasheousSubmitFixes = model.SignatureSource.HasheousSubmitFixes;
|
||||
Config.UpdateConfig();
|
||||
}
|
||||
|
||||
@@ -281,7 +298,8 @@ namespace gaseous_server.Controllers
|
||||
|
||||
private SystemInfo.PathItem GetDisk(string Path)
|
||||
{
|
||||
SystemInfo.PathItem pathItem = new SystemInfo.PathItem {
|
||||
SystemInfo.PathItem pathItem = new SystemInfo.PathItem
|
||||
{
|
||||
LibraryPath = Path,
|
||||
SpaceUsed = Common.DirSize(new DirectoryInfo(Path)),
|
||||
SpaceAvailable = new DriveInfo(Path).AvailableFreeSpace,
|
||||
@@ -293,7 +311,8 @@ namespace gaseous_server.Controllers
|
||||
|
||||
public class SystemInfo
|
||||
{
|
||||
public Version ApplicationVersion {
|
||||
public Version ApplicationVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().GetName().Version;
|
||||
@@ -589,7 +608,8 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
private bool _UserManageable;
|
||||
public bool UserManageable => _UserManageable;
|
||||
public int Interval {
|
||||
public int Interval
|
||||
{
|
||||
get
|
||||
{
|
||||
return int.Parse(Config.ReadSetting<string>("Interval_" + Task, DefaultInterval.ToString()));
|
||||
@@ -710,5 +730,14 @@ namespace gaseous_server.Controllers
|
||||
public bool AlwaysLogToDisk { get; set; }
|
||||
public int MinimumLogRetentionPeriod { get; set; }
|
||||
public bool EmulatorDebugMode { get; set; }
|
||||
public SignatureSourceItem SignatureSource { get; set; }
|
||||
|
||||
public class SignatureSourceItem
|
||||
{
|
||||
public HasheousClient.Models.MetadataModel.SignatureSources Source { get; set; }
|
||||
public string HasheousHost { get; set; }
|
||||
public string HasheousAPIKey { get; set; }
|
||||
public bool HasheousSubmitFixes { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,12 +4,36 @@ using gaseous_signature_parser.models.RomSignatureObject;
|
||||
|
||||
namespace gaseous_server.Models
|
||||
{
|
||||
public class Signatures_Games : HasheousClient.Models.LookupResponseModel
|
||||
public class Signatures_Games : HasheousClient.Models.SignatureModel
|
||||
{
|
||||
public Signatures_Games()
|
||||
{
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public int Score
|
||||
{
|
||||
get
|
||||
{
|
||||
int _score = 0;
|
||||
|
||||
if (Game != null)
|
||||
{
|
||||
_score = _score + Game.Score;
|
||||
}
|
||||
|
||||
if (Rom != null)
|
||||
{
|
||||
_score = _score + Rom.Score;
|
||||
}
|
||||
|
||||
return _score;
|
||||
}
|
||||
}
|
||||
|
||||
public GameItem Game = new GameItem();
|
||||
public RomItem Rom = new RomItem();
|
||||
|
||||
public SignatureFlags Flags = new SignatureFlags();
|
||||
|
||||
public class SignatureFlags
|
||||
@@ -18,6 +42,213 @@ namespace gaseous_server.Models
|
||||
public string IGDBPlatformName { get; set; }
|
||||
public long IGDBGameId { get; set; }
|
||||
}
|
||||
|
||||
public class GameItem : HasheousClient.Models.SignatureModel.GameItem
|
||||
{
|
||||
public GameItem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public int Score
|
||||
{
|
||||
get
|
||||
{
|
||||
// calculate a score based on the availablility of data
|
||||
int _score = 0;
|
||||
var properties = this.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
switch (prop.Name.ToLower())
|
||||
{
|
||||
case "id":
|
||||
case "score":
|
||||
break;
|
||||
case "name":
|
||||
case "year":
|
||||
case "publisher":
|
||||
case "system":
|
||||
if (prop.PropertyType == typeof(string))
|
||||
{
|
||||
if (prop.GetValue(this) != null)
|
||||
{
|
||||
string propVal = prop.GetValue(this).ToString();
|
||||
if (propVal.Length > 0)
|
||||
{
|
||||
_score = _score + 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (prop.PropertyType == typeof(string))
|
||||
{
|
||||
if (prop.GetValue(this) != null)
|
||||
{
|
||||
string propVal = prop.GetValue(this).ToString();
|
||||
if (propVal.Length > 0)
|
||||
{
|
||||
_score = _score + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RomItem : HasheousClient.Models.SignatureModel.RomItem
|
||||
{
|
||||
[JsonIgnore]
|
||||
public int Score
|
||||
{
|
||||
get
|
||||
{
|
||||
// calculate a score based on the availablility of data
|
||||
int _score = 0;
|
||||
var properties = this.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
switch (prop.Name.ToLower())
|
||||
{
|
||||
case "name":
|
||||
case "size":
|
||||
case "crc":
|
||||
case "developmentstatus":
|
||||
case "flags":
|
||||
case "attributes":
|
||||
case "romtypemedia":
|
||||
case "medialabel":
|
||||
if (prop.PropertyType == typeof(string) || prop.PropertyType == typeof(Int64) || prop.PropertyType == typeof(List<string>))
|
||||
{
|
||||
if (prop.GetValue(this) != null)
|
||||
{
|
||||
string propVal = prop.GetValue(this).ToString();
|
||||
if (propVal.Length > 0)
|
||||
{
|
||||
_score = _score + 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (prop.PropertyType == typeof(string))
|
||||
{
|
||||
if (prop.GetValue(this) != null)
|
||||
{
|
||||
string propVal = prop.GetValue(this).ToString();
|
||||
if (propVal.Length > 0)
|
||||
{
|
||||
_score = _score + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _score;
|
||||
}
|
||||
}
|
||||
|
||||
public class MediaType
|
||||
{
|
||||
public MediaType(SignatureSourceType Source, string MediaTypeString)
|
||||
{
|
||||
switch (Source)
|
||||
{
|
||||
case RomItem.SignatureSourceType.TOSEC:
|
||||
string[] typeString = MediaTypeString.Split(" ");
|
||||
|
||||
string inType = "";
|
||||
foreach (string typeStringVal in typeString)
|
||||
{
|
||||
if (inType == "")
|
||||
{
|
||||
switch (typeStringVal.ToLower())
|
||||
{
|
||||
case "disk":
|
||||
Media = RomItem.RomTypes.Disk;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "disc":
|
||||
Media = RomItem.RomTypes.Disc;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "file":
|
||||
Media = RomItem.RomTypes.File;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "part":
|
||||
Media = RomItem.RomTypes.Part;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "tape":
|
||||
Media = RomItem.RomTypes.Tape;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "of":
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "side":
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (inType.ToLower())
|
||||
{
|
||||
case "disk":
|
||||
case "disc":
|
||||
case "file":
|
||||
case "part":
|
||||
case "tape":
|
||||
Number = int.Parse(typeStringVal);
|
||||
break;
|
||||
case "of":
|
||||
Count = int.Parse(typeStringVal);
|
||||
break;
|
||||
case "side":
|
||||
Side = typeStringVal;
|
||||
break;
|
||||
}
|
||||
inType = "";
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public RomItem.RomTypes? Media { get; set; }
|
||||
|
||||
public int? Number { get; set; }
|
||||
|
||||
public int? Count { get; set; }
|
||||
|
||||
public string? Side { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -245,14 +245,32 @@ namespace gaseous_server
|
||||
CallingQueueItem = this
|
||||
};
|
||||
|
||||
Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing TOSEC files");
|
||||
tIngest.Import(Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, "TOSEC"), gaseous_signature_parser.parser.SignatureParser.TOSEC);
|
||||
foreach (int i in Enum.GetValues(typeof(gaseous_signature_parser.parser.SignatureParser)))
|
||||
{
|
||||
gaseous_signature_parser.parser.SignatureParser parserType = (gaseous_signature_parser.parser.SignatureParser)i;
|
||||
if (
|
||||
parserType != gaseous_signature_parser.parser.SignatureParser.Auto &&
|
||||
parserType != gaseous_signature_parser.parser.SignatureParser.Unknown
|
||||
)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing " + parserType + " files");
|
||||
|
||||
Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing MAME Arcade files");
|
||||
tIngest.Import(Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, "MAME Arcade"), gaseous_signature_parser.parser.SignatureParser.MAMEArcade);
|
||||
string SignaturePath = Path.Combine(Config.LibraryConfiguration.LibrarySignaturesDirectory, parserType.ToString());
|
||||
string SignatureProcessedPath = Path.Combine(Config.LibraryConfiguration.LibrarySignaturesProcessedDirectory, parserType.ToString());
|
||||
|
||||
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);
|
||||
if (!Directory.Exists(SignaturePath))
|
||||
{
|
||||
Directory.CreateDirectory(SignaturePath);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(SignatureProcessedPath))
|
||||
{
|
||||
Directory.CreateDirectory(SignatureProcessedPath);
|
||||
}
|
||||
|
||||
tIngest.Import(SignaturePath, SignatureProcessedPath, parserType);
|
||||
}
|
||||
}
|
||||
|
||||
_SaveLastRunTime = true;
|
||||
|
||||
|
@@ -64,6 +64,7 @@ if (Directory.Exists(Config.LibraryConfiguration.LibraryUploadDirectory))
|
||||
// kick off any delayed upgrade tasks
|
||||
// run 1002 background updates in the background on every start
|
||||
DatabaseMigration.BackgroundUpgradeTargetSchemaVersions.Add(1002);
|
||||
DatabaseMigration.BackgroundUpgradeTargetSchemaVersions.Add(1022);
|
||||
// start the task
|
||||
ProcessQueue.QueueItem queueItem = new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.BackgroundDatabaseUpgrade,
|
||||
@@ -307,7 +308,7 @@ app.Use(async (context, next) =>
|
||||
string userIdentity;
|
||||
try
|
||||
{
|
||||
userIdentity = context.User.Claims.Where(x=>x.Type==System.Security.Claims.ClaimTypes.NameIdentifier).FirstOrDefault().Value;
|
||||
userIdentity = context.User.Claims.Where(x => x.Type == System.Security.Claims.ClaimTypes.NameIdentifier).FirstOrDefault().Value;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
73
gaseous-server/Support/Country.txt
Normal file
73
gaseous-server/Support/Country.txt
Normal file
@@ -0,0 +1,73 @@
|
||||
AE|United Arab Emirates
|
||||
AL|Albania
|
||||
AS|Asia
|
||||
AT|Austria
|
||||
AU|Australia
|
||||
BA|Bosnia and Herzegovina
|
||||
BE|Belgium
|
||||
BG|Bulgaria
|
||||
BR|Brazil
|
||||
CA|Canada
|
||||
CH|Switzerland
|
||||
CL|Chile
|
||||
CN|China
|
||||
CS|Serbia and Montenegro
|
||||
CY|Cyprus
|
||||
CZ|Czech Republic
|
||||
DE|Germany
|
||||
DK|Denmark
|
||||
EE|Estonia
|
||||
EG|Egypt
|
||||
ES|Spain
|
||||
EU|Europe
|
||||
FI|Finland
|
||||
FR|France
|
||||
GB|United Kingdom
|
||||
GR|Greece
|
||||
HK|Hong Kong
|
||||
HR|Croatia
|
||||
HU|Hungary
|
||||
ID|Indonesia
|
||||
IE|Ireland
|
||||
IL|Israel
|
||||
IN|India
|
||||
IR|Iran
|
||||
IS|Iceland
|
||||
IT|Italy
|
||||
JO|Jordan
|
||||
JP|Japan
|
||||
KR|Korea
|
||||
KR|South Korea
|
||||
LT|Lithuania
|
||||
LU|Luxembourg
|
||||
LV|Latvia
|
||||
MN|Mongolia
|
||||
MX|Mexico
|
||||
MY|Malaysia
|
||||
NL|Netherlands
|
||||
NO|Norway
|
||||
NP|Nepal
|
||||
NZ|New Zealand
|
||||
OM|Oman
|
||||
PE|Peru
|
||||
PH|Philippines
|
||||
PL|Poland
|
||||
PT|Portugal
|
||||
QA|Qatar
|
||||
RO|Romania
|
||||
RU|Russia
|
||||
SE|Sweden
|
||||
SG|Singapore
|
||||
SI|Slovenia
|
||||
SK|Slovakia
|
||||
TH|Thailand
|
||||
TR|Turkey
|
||||
TW|Taiwan
|
||||
US|United States
|
||||
USA|United States
|
||||
VN|Vietnam
|
||||
YU|Yugoslavia
|
||||
ZA|South Africa
|
||||
World|World
|
||||
Europe|Europe
|
||||
Asia|Asia
|
40
gaseous-server/Support/Database/MySQL/gaseous-1022.sql
Normal file
40
gaseous-server/Support/Database/MySQL/gaseous-1022.sql
Normal file
@@ -0,0 +1,40 @@
|
||||
CREATE TABLE `Signatures_RomToSource` (
|
||||
`SourceId` int NOT NULL,
|
||||
`RomId` int NOT NULL,
|
||||
PRIMARY KEY (`SourceId`, `RomId`)
|
||||
);
|
||||
|
||||
CREATE TABLE `Signatures_Games_Countries` (
|
||||
`GameId` INT NOT NULL,
|
||||
`CountryId` INT NOT NULL,
|
||||
PRIMARY KEY (`GameId`, `CountryId`),
|
||||
CONSTRAINT `GameCountry` FOREIGN KEY (`GameId`) REFERENCES `Signatures_Games` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||
);
|
||||
|
||||
CREATE TABLE `Signatures_Games_Languages` (
|
||||
`GameId` INT NOT NULL,
|
||||
`LanguageId` INT NOT NULL,
|
||||
PRIMARY KEY (`GameId`, `LanguageId`),
|
||||
CONSTRAINT `GameLanguage` FOREIGN KEY (`GameId`) REFERENCES `Signatures_Games` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||
);
|
||||
|
||||
CREATE TABLE `Country` (
|
||||
`Id` INT NOT NULL AUTO_INCREMENT,
|
||||
`Code` VARCHAR(20) NULL,
|
||||
`Value` VARCHAR(255) NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
INDEX `id_Code` (`Code` ASC) VISIBLE,
|
||||
INDEX `id_Value` (`Value` ASC) VISIBLE
|
||||
);
|
||||
|
||||
CREATE TABLE `Language` (
|
||||
`Id` INT NOT NULL AUTO_INCREMENT,
|
||||
`Code` VARCHAR(20) NULL,
|
||||
`Value` VARCHAR(255) NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
INDEX `id_Code` (`Code` ASC) VISIBLE,
|
||||
INDEX `id_Value` (`Value` ASC) VISIBLE
|
||||
);
|
||||
|
||||
ALTER TABLE `Games_Roms`
|
||||
ADD COLUMN `RomDataVersion` INT DEFAULT 1;
|
47
gaseous-server/Support/Language.txt
Normal file
47
gaseous-server/Support/Language.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
ar|Arabic
|
||||
bg|Bulgarian
|
||||
bs|Bosnian
|
||||
cs|Czech
|
||||
cy|Welsh
|
||||
da|Danish
|
||||
de|German
|
||||
el|Greek
|
||||
en|English
|
||||
eo|Esperanto
|
||||
es|Spanish
|
||||
et|Estonian
|
||||
fa|Persian
|
||||
fi|Finnish
|
||||
fr|French
|
||||
fr-ca|French Canadian
|
||||
ga|Irish
|
||||
gd|Gaelic
|
||||
gu|Gujarati
|
||||
he|Hebrew
|
||||
hi|Hindi
|
||||
hr|Croatian
|
||||
hu|Hungarian
|
||||
is|Icelandic
|
||||
it|Italian
|
||||
ja|Japanese
|
||||
ko|Korean
|
||||
lt|Lithuanian
|
||||
lv|Latvian
|
||||
ms|Malay
|
||||
nl|Dutch
|
||||
no|Norwegian
|
||||
pl|Polish
|
||||
pt|Portuguese
|
||||
ro|Romanian
|
||||
ru|Russian
|
||||
sk|Slovakian
|
||||
sl|Slovenian
|
||||
sq|Albanian
|
||||
sr|Serbian
|
||||
sv|Swedish
|
||||
th|Thai
|
||||
tr|Turkish
|
||||
ur|Urdu
|
||||
vi|Vietnamese
|
||||
yi|Yiddish
|
||||
zh|Chinese
|
@@ -16,20 +16,20 @@
|
||||
<DocumentationFile>bin\Release\net8.0\gaseous-server.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Asp.Versioning.Mvc" Version="8.0.0" />
|
||||
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.0.0" />
|
||||
<PackageReference Include="gaseous-signature-parser" Version="2.1.0" />
|
||||
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" />
|
||||
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
|
||||
<PackageReference Include="gaseous-signature-parser" Version="2.2.1" />
|
||||
<PackageReference Include="gaseous.IGDB" Version="1.0.2" />
|
||||
<PackageReference Include="hasheous-client" Version="0.2.0" />
|
||||
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.5.0" />
|
||||
<PackageReference Include="sharpcompress" Version="0.36.0" />
|
||||
<PackageReference Include="Squid-Box.SevenZipSharp" Version="1.6.1.23" />
|
||||
<PackageReference Include="hasheous-client" Version="1.0.2" />
|
||||
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.7.0" />
|
||||
<PackageReference Include="sharpcompress" Version="0.37.2" />
|
||||
<PackageReference Include="Squid-Box.SevenZipSharp" Version="1.6.2.24" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="MySqlConnector" Version="2.3.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" />
|
||||
<PackageReference Include="MySqlConnector" Version="2.3.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -39,6 +39,8 @@
|
||||
<None Remove="Classes\" />
|
||||
<None Remove="Classes\SignatureIngestors\" />
|
||||
<None Remove="Support\" />
|
||||
<None Remove="Support\Country.txt" />
|
||||
<None Remove="Support\Language.txt" />
|
||||
<None Remove="Support\Database\" />
|
||||
<None Remove="Support\Database\MySQL\" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1000.sql" />
|
||||
@@ -64,6 +66,7 @@
|
||||
<None Remove="Support\Database\MySQL\gaseous-1019.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1020.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1021.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1022.sql" />
|
||||
<None Remove="Classes\Metadata\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -85,6 +88,8 @@
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Support\Country.txt" />
|
||||
<EmbeddedResource Include="Support\Language.txt" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1000.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1001.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1002.sql" />
|
||||
@@ -108,5 +113,6 @@
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1019.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1020.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1021.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1022.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@@ -74,11 +74,11 @@
|
||||
ajaxCall(
|
||||
'/api/v1.1/Library?Name=' + encodeURIComponent(libName) + '&DefaultPlatformId=' + libPlatform[0].id + '&Path=' + encodeURIComponent(libPath),
|
||||
'POST',
|
||||
function(result) {
|
||||
function (result) {
|
||||
drawLibrary();
|
||||
closeSubDialog();
|
||||
closeDialog();
|
||||
},
|
||||
function(error) {
|
||||
function (error) {
|
||||
alert('An error occurred while creating the library:\n\n' + JSON.stringify(error.responseText));
|
||||
}
|
||||
);
|
||||
|
@@ -1,7 +1,9 @@
|
||||
<div id="properties_toc">
|
||||
<div id="properties_toc_general" name="properties_toc_item" onclick="SelectTab('general');">General</div>
|
||||
<div id="properties_toc_archive" name="properties_toc_item" onclick="SelectTab('archive');" style="display: none;">Archive Contents</div>
|
||||
<div id="properties_toc_attributes" name="properties_toc_item" onclick="SelectTab('attributes');" style="display: none;">Attributes</div>
|
||||
<div id="properties_toc_archive" name="properties_toc_item" onclick="SelectTab('archive');" style="display: none;">
|
||||
Archive Contents</div>
|
||||
<div id="properties_toc_attributes" name="properties_toc_item" onclick="SelectTab('attributes');"
|
||||
style="display: none;">Attributes</div>
|
||||
<div id="properties_toc_match" name="properties_toc_item" onclick="SelectTab('match');">Title Match</div>
|
||||
<!--<div id="properties_toc_manage" name="properties_toc_item" onclick="SelectTab('manage');">Manage</div>-->
|
||||
</div>
|
||||
@@ -78,7 +80,9 @@
|
||||
<td style="width: 75%;"><select id="properties_fixgame" style="width: 100%;"></select></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="text-align: right;"><button id="properties_fixclear" value="Clear Match" onclick="ClearFixedGame();">Clear Match</button><button id="properties_fixsave" value="Save Match" onclick="SaveFixedGame();">Save Match</button></td>
|
||||
<td colspan="2" style="text-align: right;"><button id="properties_fixclear" value="Clear Match"
|
||||
onclick="ClearFixedGame();">Clear Match</button><button id="properties_fixsave"
|
||||
value="Save Match" onclick="SaveFixedGame();">Save Match</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -144,7 +148,7 @@
|
||||
document.getElementById('romDelete').style.display = 'none';
|
||||
}
|
||||
|
||||
if (result.attributes.length > 0) {
|
||||
if (result.attributes) {
|
||||
document.getElementById('properties_bodypanel_attributes').appendChild(BuildAttributesTable(result.attributes, result.source));
|
||||
document.getElementById('properties_bodypanel_archive_content').appendChild(BuildArchiveTable(result.attributes, result.source));
|
||||
}
|
||||
@@ -276,8 +280,8 @@
|
||||
var aTable = document.createElement('table');
|
||||
aTable.style.width = '100%';
|
||||
|
||||
for (var i = 0; i < attributes.length; i++) {
|
||||
if (attributes[i].key != "ZipContents") {
|
||||
for (const [key, value] of Object.entries(attributes)) {
|
||||
if (key != "ZipContents") {
|
||||
// show attributes button
|
||||
document.getElementById('properties_toc_attributes').style.display = '';
|
||||
var aRow = document.createElement('tr');
|
||||
@@ -285,15 +289,15 @@
|
||||
var aTitleCell = document.createElement('th');
|
||||
aTitleCell.width = "25%";
|
||||
if (sourceName == "TOSEC") {
|
||||
aTitleCell.innerHTML = ConvertTOSECAttributeName(attributes[i].key);
|
||||
aTitleCell.innerHTML = ConvertTOSECAttributeName(key);
|
||||
} else {
|
||||
aTitleCell.innerHTML = attributes[i].key;
|
||||
aTitleCell.innerHTML = key;
|
||||
}
|
||||
aRow.appendChild(aTitleCell);
|
||||
|
||||
var aValueCell = document.createElement('td');
|
||||
aValueCell.width = "75%";
|
||||
aValueCell.innerHTML = attributes[i].value;
|
||||
aValueCell.innerHTML = value;
|
||||
aRow.appendChild(aValueCell);
|
||||
|
||||
aTable.appendChild(aRow);
|
||||
@@ -304,9 +308,9 @@
|
||||
}
|
||||
|
||||
function BuildArchiveTable(attributes, sourceName) {
|
||||
for (var i = 0; i < attributes.length; i++) {
|
||||
if (attributes[i].key == "ZipContents") {
|
||||
var archiveContent = JSON.parse(attributes[i].value);
|
||||
for (const [key, value] of Object.entries(attributes)) {
|
||||
if (key == "ZipContents") {
|
||||
var archiveContent = JSON.parse(value);
|
||||
|
||||
// show archive button
|
||||
document.getElementById('properties_toc_archive').style.display = '';
|
||||
@@ -343,6 +347,17 @@
|
||||
hRow.appendChild(aHashCell);
|
||||
aBody.appendChild(hRow);
|
||||
|
||||
if (archiveContent[r].isSignatureSelector == true) {
|
||||
var sigRow = document.createElement('tr');
|
||||
|
||||
var sigCell = document.createElement('td');
|
||||
sigCell.setAttribute('colspan', 2);
|
||||
sigCell.style.paddingLeft = '20px';
|
||||
sigCell.innerHTML = "Hash used to identify this archive";
|
||||
sigRow.appendChild(sigCell);
|
||||
aBody.appendChild(sigRow);
|
||||
}
|
||||
|
||||
aTable.appendChild(aBody);
|
||||
}
|
||||
}
|
||||
@@ -354,18 +369,18 @@
|
||||
function ConvertTOSECAttributeName(attributeName) {
|
||||
var tosecAttributeNames = {
|
||||
"cr": "Cracked",
|
||||
"f" : "Fixed",
|
||||
"h" : "Hacked",
|
||||
"m" : "Modified",
|
||||
"p" : "Pirated",
|
||||
"t" : "Trained",
|
||||
"f": "Fixed",
|
||||
"h": "Hacked",
|
||||
"m": "Modified",
|
||||
"p": "Pirated",
|
||||
"t": "Trained",
|
||||
"tr": "Translated",
|
||||
"o" : "Over Dump",
|
||||
"u" : "Under Dump",
|
||||
"v" : "Virus",
|
||||
"b" : "Bad Dump",
|
||||
"a" : "Alternate",
|
||||
"!" : "Known Verified Dump"
|
||||
"o": "Over Dump",
|
||||
"u": "Under Dump",
|
||||
"v": "Virus",
|
||||
"b": "Bad Dump",
|
||||
"a": "Alternate",
|
||||
"!": "Known Verified Dump"
|
||||
};
|
||||
|
||||
if (attributeName in tosecAttributeNames) {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<div id="bgImage" style="background-image: url('/images/SettingsWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
|
||||
<div id="bgImage"
|
||||
style="background-image: url('/images/SettingsWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
|
||||
<div id="bgImage_Opacity"></div>
|
||||
</div>
|
||||
|
||||
@@ -6,11 +7,21 @@
|
||||
<div id="properties_toc" class="settings_toc">
|
||||
<div class="filter_header">Settings</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');" style="display: none;">Settings</div>
|
||||
<div id="properties_toc_users" name="properties_toc_item" onclick="SelectTab('users');" style="display: none;">Users</div>
|
||||
<div id="properties_toc_mapping" name="properties_toc_item" onclick="SelectTab('mapping');" style="display: none;">Platform Mapping</div>
|
||||
<div id="properties_toc_settings" name="properties_toc_item" onclick="SelectTab('settings');"
|
||||
style="display: none;">Settings</div>
|
||||
<div id="properties_toc_libraries" name="properties_toc_item" onclick="SelectTab('libraries');"
|
||||
style="display: none;">
|
||||
Libraries</div>
|
||||
<div id="properties_toc_users" name="properties_toc_item" onclick="SelectTab('users');" style="display: none;">
|
||||
Users</div>
|
||||
<div id="properties_toc_services" name="properties_toc_item" onclick="SelectTab('services');"
|
||||
style="display: none;">
|
||||
Services</div>
|
||||
<div id="properties_toc_mapping" name="properties_toc_item" onclick="SelectTab('mapping');"
|
||||
style="display: none;">Platform Mapping</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');" style="display: none;">Logs</div>
|
||||
<div id="properties_toc_logs" name="properties_toc_item" onclick="SelectTab('logs');" style="display: none;">
|
||||
Logs</div>
|
||||
<div id="properties_toc_about" name="properties_toc_item" onclick="SelectTab('about');">About</div>
|
||||
</div>
|
||||
<div id="properties_bodypanel">
|
||||
@@ -20,13 +31,16 @@
|
||||
</div>
|
||||
|
||||
<div id="settings_photocredit">
|
||||
Wallpaper by <a href="https://unsplash.com/@lorenzoherrera" class="romlink">Lorenzo Herrera</a> / <a href="https://unsplash.com/photos/p0j-mE6mGo4" class="romlink">Unsplash</a>
|
||||
Wallpaper by <a href="https://unsplash.com/@lorenzoherrera" class="romlink">Lorenzo Herrera</a> / <a
|
||||
href="https://unsplash.com/photos/p0j-mE6mGo4" class="romlink">Unsplash</a>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
if (userProfile.roles.includes("Admin")) {
|
||||
document.getElementById('properties_toc_settings').style.display = '';
|
||||
document.getElementById('properties_toc_libraries').style.display = '';
|
||||
document.getElementById('properties_toc_users').style.display = '';
|
||||
document.getElementById('properties_toc_services').style.display = '';
|
||||
document.getElementById('properties_toc_mapping').style.display = '';
|
||||
document.getElementById('properties_toc_logs').style.display = '';
|
||||
}
|
||||
|
63
gaseous-server/wwwroot/pages/settings/libraries.html
Normal file
63
gaseous-server/wwwroot/pages/settings/libraries.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<div id="gametitle">
|
||||
<h1 id="gametitle_label">Libraries</h1>
|
||||
</div>
|
||||
|
||||
<table id="settings_libraries" class="romtable" style="width: 100%;" cellspacing="0">
|
||||
|
||||
</table>
|
||||
<div style="text-align: right;"><button id="settings_newlibrary" onclick="showDialog('librarynew');">New
|
||||
Library</button></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function drawLibrary() {
|
||||
ajaxCall(
|
||||
'/api/v1.1/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>
|
290
gaseous-server/wwwroot/pages/settings/services.html
Normal file
290
gaseous-server/wwwroot/pages/settings/services.html
Normal file
@@ -0,0 +1,290 @@
|
||||
<div id="gametitle">
|
||||
<h1 id="gametitle_label">Services</h1>
|
||||
</div>
|
||||
<table id="settings_tasktimers" class="romtable" style="width: 100%;" cellspacing="0">
|
||||
|
||||
</table>
|
||||
<div style="text-align: right;"><button id="settings_tasktimers_default" onclick="defaultTaskTimers();">Reset to
|
||||
Default</button><button id="settings_tasktimers_new" onclick="saveTaskTimers();">Save</button></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function getBackgroundTaskTimers() {
|
||||
ajaxCall(
|
||||
'/api/v1/System/Settings/BackgroundTasks/Configuration',
|
||||
'GET',
|
||||
function (result) {
|
||||
var targetTable = document.getElementById('settings_tasktimers');
|
||||
targetTable.innerHTML = '';
|
||||
|
||||
for (const [key, value] of Object.entries(result)) {
|
||||
var newTableRowBody = document.createElement('tbody');
|
||||
newTableRowBody.className = 'romrow';
|
||||
|
||||
var enabledString = "";
|
||||
if (value.enabled == true) {
|
||||
enabledString = 'checked="checked"';
|
||||
}
|
||||
|
||||
var newTableIntervalRow = createTableRow(
|
||||
false,
|
||||
[
|
||||
GetTaskFriendlyName(value.task),
|
||||
'Enabled',
|
||||
'<input id="settings_enabled_' + value.task + '" name="settings_tasktimers_enabled" type="checkbox" ' + enabledString + '/>',
|
||||
],
|
||||
'',
|
||||
'romcell'
|
||||
);
|
||||
newTableRowBody.appendChild(newTableIntervalRow);
|
||||
|
||||
var newTableRow = createTableRow(
|
||||
false,
|
||||
[
|
||||
'',
|
||||
'Minimum Interval (Minutes):',
|
||||
'<input id="settings_tasktimers_' + value.task + '" name="settings_tasktimers_values" data-name="' + value.task + '" data-default="' + value.defaultInterval + '" type="number" placeholder="' + value.defaultInterval + '" min="' + value.minimumAllowedInterval + '" value="' + value.interval + '" />'
|
||||
],
|
||||
'',
|
||||
'romcell'
|
||||
);
|
||||
newTableRowBody.appendChild(newTableRow);
|
||||
|
||||
// allowed time periods row
|
||||
var newTableRowTime = document.createElement('tr');
|
||||
var rowTimeSpace = document.createElement('td');
|
||||
newTableRowTime.appendChild(rowTimeSpace);
|
||||
|
||||
var rowTimeContentTitle = document.createElement('td');
|
||||
rowTimeContentTitle.className = 'romcell';
|
||||
rowTimeContentTitle.innerHTML = "Allowed Days:";
|
||||
newTableRowTime.appendChild(rowTimeContentTitle);
|
||||
|
||||
var rowTimeContent = document.createElement('td');
|
||||
// rowTimeContent.setAttribute('colspan', 2);
|
||||
rowTimeContent.className = 'romcell';
|
||||
var daySelector = document.createElement('select');
|
||||
daySelector.id = 'settings_alloweddays_' + value.task;
|
||||
daySelector.name = 'settings_alloweddays';
|
||||
daySelector.multiple = 'multiple';
|
||||
daySelector.setAttribute('data-default', value.defaultAllowedDays.join(","));
|
||||
daySelector.style.width = '95%';
|
||||
var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
||||
for (var d = 0; d < days.length; d++) {
|
||||
var dayOpt = document.createElement('option');
|
||||
dayOpt.value = days[d];
|
||||
dayOpt.innerHTML = days[d];
|
||||
if (value.allowedDays.includes(days[d])) {
|
||||
dayOpt.selected = 'selected';
|
||||
}
|
||||
daySelector.appendChild(dayOpt);
|
||||
}
|
||||
rowTimeContent.appendChild(daySelector);
|
||||
$(daySelector).select2({
|
||||
tags: false
|
||||
});
|
||||
newTableRowTime.appendChild(rowTimeContent);
|
||||
|
||||
newTableRowBody.appendChild(newTableRowTime);
|
||||
|
||||
// add start and end times
|
||||
var newTableRowClock = document.createElement('tr');
|
||||
var rowClockSpace = document.createElement('td');
|
||||
newTableRowClock.appendChild(rowClockSpace);
|
||||
|
||||
var rowClockContentTitle = document.createElement('td');
|
||||
rowClockContentTitle.className = 'romcell';
|
||||
rowClockContentTitle.innerHTML = "Time Range:";
|
||||
newTableRowClock.appendChild(rowClockContentTitle);
|
||||
|
||||
var rowClockContent = document.createElement('td');
|
||||
rowClockContent.className = 'romcell';
|
||||
// rowClockContent.setAttribute('colspan', 2);
|
||||
|
||||
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'Start', value.defaultAllowedStartHours, value.defaultAllowedStartMinutes, value.allowedStartHours, value.allowedStartMinutes));
|
||||
|
||||
rowClockContentSeparator = document.createElement('span');
|
||||
rowClockContentSeparator.innerHTML = ' - ';
|
||||
rowClockContent.appendChild(rowClockContentSeparator);
|
||||
|
||||
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'End', value.defaultAllowedEndHours, value.defaultAllowedEndMinutes, value.allowedEndHours, value.allowedEndMinutes));
|
||||
|
||||
newTableRowClock.appendChild(rowClockContent);
|
||||
|
||||
newTableRowBody.appendChild(newTableRowClock);
|
||||
|
||||
// blocks tasks
|
||||
var newTableRowBlocks = document.createElement('tr');
|
||||
var rowBlocksSpace = document.createElement('td');
|
||||
newTableRowBlocks.appendChild(rowBlocksSpace);
|
||||
|
||||
var rowBlocksContentTitle = document.createElement('td');
|
||||
rowBlocksContentTitle.className = 'romcell';
|
||||
rowBlocksContentTitle.innerHTML = "Blocks:";
|
||||
newTableRowBlocks.appendChild(rowBlocksContentTitle);
|
||||
|
||||
var rowBlocksContent = document.createElement('td');
|
||||
rowBlocksContent.className = 'romcell';
|
||||
// rowBlocksContent.setAttribute('colspan', 2);
|
||||
var blocksString = "";
|
||||
for (var i = 0; i < value.blocks.length; i++) {
|
||||
if (blocksString.length > 0) { blocksString += ", "; }
|
||||
blocksString += GetTaskFriendlyName(value.blocks[i]);
|
||||
}
|
||||
if (blocksString.length == 0) { blocksString = 'None'; }
|
||||
rowBlocksContent.innerHTML = blocksString;
|
||||
newTableRowBlocks.appendChild(rowBlocksContent);
|
||||
|
||||
newTableRowBody.appendChild(newTableRowBlocks);
|
||||
|
||||
// blocked by tasks
|
||||
var newTableRowBlockedBy = document.createElement('tr');
|
||||
var rowBlockedBySpace = document.createElement('td');
|
||||
newTableRowBlockedBy.appendChild(rowBlockedBySpace);
|
||||
|
||||
var rowBlockedByContentTitle = document.createElement('td');
|
||||
rowBlockedByContentTitle.className = 'romcell';
|
||||
rowBlockedByContentTitle.innerHTML = "Blocked By:";
|
||||
newTableRowBlockedBy.appendChild(rowBlockedByContentTitle);
|
||||
|
||||
var rowBlockedByContent = document.createElement('td');
|
||||
rowBlockedByContent.className = 'romcell';
|
||||
// rowBlockedByContent.setAttribute('colspan', 2);
|
||||
var BlockedByString = "";
|
||||
for (var i = 0; i < value.blockedBy.length; i++) {
|
||||
if (BlockedByString.length > 0) { BlockedByString += ", "; }
|
||||
BlockedByString += GetTaskFriendlyName(value.blockedBy[i]);
|
||||
}
|
||||
if (BlockedByString.length == 0) { BlockedByString = 'None'; }
|
||||
rowBlockedByContent.innerHTML = BlockedByString;
|
||||
newTableRowBlockedBy.appendChild(rowBlockedByContent);
|
||||
|
||||
newTableRowBody.appendChild(newTableRowBlockedBy);
|
||||
|
||||
// complete row
|
||||
targetTable.appendChild(newTableRowBody);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function generateTimeDropDowns(taskName, rangeName, defaultHour, defaultMinute, valueHour, valueMinute) {
|
||||
var container = document.createElement('div');
|
||||
container.style.display = 'inline';
|
||||
|
||||
var elementName = 'settings_tasktimers_time';
|
||||
|
||||
var hourSelector = document.createElement('input');
|
||||
hourSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Hour';
|
||||
hourSelector.name = elementName;
|
||||
hourSelector.setAttribute('data-name', taskName);
|
||||
hourSelector.setAttribute('type', 'number');
|
||||
hourSelector.setAttribute('min', '0');
|
||||
hourSelector.setAttribute('max', '23');
|
||||
hourSelector.setAttribute('placeholder', defaultHour);
|
||||
hourSelector.value = valueHour;
|
||||
container.appendChild(hourSelector);
|
||||
|
||||
var separator = document.createElement('span');
|
||||
separator.innerHTML = " : ";
|
||||
container.appendChild(separator);
|
||||
|
||||
var minSelector = document.createElement('input');
|
||||
minSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Minute';
|
||||
minSelector.name = elementName;
|
||||
minSelector.setAttribute('type', 'number');
|
||||
minSelector.setAttribute('min', '0');
|
||||
minSelector.setAttribute('max', '59');
|
||||
minSelector.setAttribute('placeholder', defaultMinute);
|
||||
minSelector.value = valueMinute;
|
||||
container.appendChild(minSelector);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
function saveTaskTimers() {
|
||||
var timerValues = document.getElementsByName('settings_tasktimers_values');
|
||||
|
||||
var model = [];
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
var taskName = timerValues[i].getAttribute('data-name');
|
||||
var taskEnabled = document.getElementById('settings_enabled_' + taskName).checked;
|
||||
var taskIntervalObj = document.getElementById('settings_tasktimers_' + taskName);
|
||||
var taskInterval = function () { if (taskIntervalObj.value) { return taskIntervalObj.value; } else { return taskIntervalObj.getAttribute('placeholder'); } };
|
||||
var taskDaysRaw = $('#settings_alloweddays_' + taskName).select2('data');
|
||||
var taskDays = [];
|
||||
if (taskDaysRaw.length > 0) {
|
||||
for (var d = 0; d < taskDaysRaw.length; d++) {
|
||||
taskDays.push(taskDaysRaw[d].id);
|
||||
}
|
||||
} else {
|
||||
taskDays.push("Monday");
|
||||
}
|
||||
var taskStartHourObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Hour');
|
||||
var taskStartMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Minute');
|
||||
var taskEndHourObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Hour');
|
||||
var taskEndMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Minute');
|
||||
|
||||
var taskStartHour = function () { if (taskStartHourObj.value) { return taskStartHourObj.value; } else { return taskStartHourObj.getAttribute('placeholder'); } };
|
||||
var taskStartMinute = function () { if (taskStartMinuteObj.value) { return taskStartMinuteObj.value; } else { return taskStartMinuteObj.getAttribute('placeholder'); } };
|
||||
var taskEndHour = function () { if (taskEndHourObj.value) { return taskEndHourObj.value; } else { return taskEndHourObj.getAttribute('placeholder'); } };
|
||||
var taskEndMinute = function () { if (taskEndMinuteObj.value) { return taskEndMinuteObj.value; } else { return taskEndMinuteObj.getAttribute('placeholder'); } };
|
||||
|
||||
model.push(
|
||||
{
|
||||
"task": taskName,
|
||||
"enabled": taskEnabled,
|
||||
"interval": taskInterval(),
|
||||
"allowedDays": taskDays,
|
||||
"allowedStartHours": taskStartHour(),
|
||||
"allowedStartMinutes": taskStartMinute(),
|
||||
"allowedEndHours": taskEndHour(),
|
||||
"allowedEndMinutes": taskEndMinute()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ajaxCall(
|
||||
'/api/v1/System/Settings/BackgroundTasks/Configuration',
|
||||
'POST',
|
||||
function (result) {
|
||||
getBackgroundTaskTimers();
|
||||
},
|
||||
function (error) {
|
||||
getBackgroundTaskTimers();
|
||||
},
|
||||
JSON.stringify(model)
|
||||
);
|
||||
}
|
||||
|
||||
function defaultTaskTimers() {
|
||||
var timerValues = document.getElementsByName('settings_tasktimers_enabled');
|
||||
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
timerValues[i].checked = true;
|
||||
}
|
||||
|
||||
var timerValues = document.getElementsByName('settings_tasktimers_values');
|
||||
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
timerValues[i].value = timerValues[i].getAttribute('data-default');
|
||||
}
|
||||
|
||||
var timerValues = document.getElementsByName('settings_alloweddays');
|
||||
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
var defaultSelections = timerValues[i].getAttribute('data-default').split(',');
|
||||
$(timerValues[i]).val(defaultSelections);
|
||||
$(timerValues[i]).trigger('change');
|
||||
}
|
||||
|
||||
var timerValues = document.getElementsByName('settings_tasktimers_time');
|
||||
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
timerValues[i].value = timerValues[i].getAttribute('placeholder');
|
||||
}
|
||||
|
||||
saveTaskTimers();
|
||||
}
|
||||
|
||||
getBackgroundTaskTimers();
|
||||
</script>
|
@@ -2,37 +2,74 @@
|
||||
<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="showDialog('librarynew');">New Library</button></div>
|
||||
|
||||
<h2>Advanced Settings</h2>
|
||||
<p><strong>Warning</strong> Do not modify the below settings unless you know what you're doing.</p>
|
||||
<h3>Background Task Timers</h3>
|
||||
<table id="settings_tasktimers" class="romtable" style="width: 100%;" cellspacing="0">
|
||||
|
||||
</table>
|
||||
<div style="text-align: right;"><button id="settings_tasktimers_default" onclick="defaultTaskTimers();">Reset to Default</button><button id="settings_tasktimers_new" onclick="saveTaskTimers();">Save</button></div>
|
||||
|
||||
<h3>System Settings</h3>
|
||||
<table cellspacing="0" style="width: 100%;">
|
||||
<table cellspacing="0" style="width: 100%; vertical-align: top;">
|
||||
<tr>
|
||||
<th colspan="2">Logging</th>
|
||||
<th colspan="2">
|
||||
<h3>Metadata Sources</h3>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="width: 25%;">
|
||||
Signature Source
|
||||
</th>
|
||||
<td>
|
||||
<input type="radio" name="settings_signaturesource" id="settings_signaturesource_local" value="LocalOnly"
|
||||
onclick="document.getElementById('settings_hasheoushost_row').style.display = 'none';">
|
||||
<label for="settings_signaturesource_local">Local Only</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<input type="radio" name="settings_signaturesource" id="settings_signaturesource_hasheous" value="Hasheous"
|
||||
onclick="document.getElementById('settings_hasheoushost_row').style.display = '';">
|
||||
<label for="settings_signaturesource_hasheous">Hasheous</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="settings_hasheoushost_row" style="display: none;">
|
||||
<th>
|
||||
Hasheous Host
|
||||
</th>
|
||||
<td>
|
||||
<input type="url" id="settings_signaturesource_hasheoushost" style="width: 90%;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for="settings_hasheoussubmit">Submit updates to Hasheous when fixing ROM matches</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" id="settings_hasheoussubmit" onchange="toggleHasheousAPIKey(this);">
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="settings_hasheousapikey_row" style="display: none;">
|
||||
<th>
|
||||
Hasheous API key
|
||||
</th>
|
||||
<td>
|
||||
<textarea id="settings_hasheousapikey" rows="2" style="width: 90%;"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="2">
|
||||
<h3>Logging</h3>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Write logs
|
||||
</th>
|
||||
<td>
|
||||
<input type="radio" name="settings_logs_write" id="settings_logs_write_db" value="false" checked="checked"><label for="settings_logs_write_db"> To database only (default)</label>
|
||||
<input type="radio" name="settings_logs_write" id="settings_logs_write_db" value="false"
|
||||
checked="checked"><label for="settings_logs_write_db"> To database only
|
||||
(default)</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<input type="radio" name="settings_logs_write" id="settings_logs_write_fs" value="true"><label for="settings_logs_write_fs"> To database and disk</label>
|
||||
<input type="radio" name="settings_logs_write" id="settings_logs_write_fs" value="true"><label
|
||||
for="settings_logs_write_fs"> To database and disk</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -47,10 +84,12 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="2">Emulator</th>
|
||||
<th colspan="2">
|
||||
<h3>Emulator</h3>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Enable debug mode</th>
|
||||
<th><label for="settings_emulator_debug">Enable debug mode</label></th>
|
||||
<td><input type="checkbox" name="settings_emulator" id="settings_emulator_debug" checked="checked" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -61,339 +100,11 @@
|
||||
</table>
|
||||
|
||||
<script type="text/javascript">
|
||||
function drawLibrary() {
|
||||
ajaxCall(
|
||||
'/api/v1.1/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'
|
||||
));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getBackgroundTaskTimers() {
|
||||
ajaxCall(
|
||||
'/api/v1/System/Settings/BackgroundTasks/Configuration',
|
||||
'GET',
|
||||
function(result) {
|
||||
var targetTable = document.getElementById('settings_tasktimers');
|
||||
targetTable.innerHTML = '';
|
||||
|
||||
for (const [key, value] of Object.entries(result)) {
|
||||
var newTableRowBody = document.createElement('tbody');
|
||||
newTableRowBody.className = 'romrow';
|
||||
|
||||
var enabledString = "";
|
||||
if (value.enabled == true) {
|
||||
enabledString = 'checked="checked"';
|
||||
}
|
||||
|
||||
var newTableIntervalRow = createTableRow(
|
||||
false,
|
||||
[
|
||||
GetTaskFriendlyName(value.task),
|
||||
'Enabled',
|
||||
'<input id="settings_enabled_' + value.task + '" name="settings_tasktimers_enabled" type="checkbox" ' + enabledString + '/>',
|
||||
],
|
||||
'',
|
||||
'romcell'
|
||||
);
|
||||
newTableRowBody.appendChild(newTableIntervalRow);
|
||||
|
||||
var newTableRow = createTableRow(
|
||||
false,
|
||||
[
|
||||
'',
|
||||
'Minimum Interval (Minutes):',
|
||||
'<input id="settings_tasktimers_' + value.task + '" name="settings_tasktimers_values" data-name="' + value.task + '" data-default="' + value.defaultInterval + '" type="number" placeholder="' + value.defaultInterval + '" min="' + value.minimumAllowedInterval + '" value="' + value.interval + '" />'
|
||||
],
|
||||
'',
|
||||
'romcell'
|
||||
);
|
||||
newTableRowBody.appendChild(newTableRow);
|
||||
|
||||
// allowed time periods row
|
||||
var newTableRowTime = document.createElement('tr');
|
||||
var rowTimeSpace = document.createElement('td');
|
||||
newTableRowTime.appendChild(rowTimeSpace);
|
||||
|
||||
var rowTimeContentTitle = document.createElement('td');
|
||||
rowTimeContentTitle.className = 'romcell';
|
||||
rowTimeContentTitle.innerHTML = "Allowed Days:";
|
||||
newTableRowTime.appendChild(rowTimeContentTitle);
|
||||
|
||||
var rowTimeContent = document.createElement('td');
|
||||
// rowTimeContent.setAttribute('colspan', 2);
|
||||
rowTimeContent.className = 'romcell';
|
||||
var daySelector = document.createElement('select');
|
||||
daySelector.id = 'settings_alloweddays_' + value.task;
|
||||
daySelector.name = 'settings_alloweddays';
|
||||
daySelector.multiple = 'multiple';
|
||||
daySelector.setAttribute('data-default', value.defaultAllowedDays.join(","));
|
||||
daySelector.style.width = '95%';
|
||||
var days = [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ];
|
||||
for (var d = 0; d < days.length; d++) {
|
||||
var dayOpt = document.createElement('option');
|
||||
dayOpt.value = days[d];
|
||||
dayOpt.innerHTML = days[d];
|
||||
if (value.allowedDays.includes(days[d])) {
|
||||
dayOpt.selected = 'selected';
|
||||
}
|
||||
daySelector.appendChild(dayOpt);
|
||||
}
|
||||
rowTimeContent.appendChild(daySelector);
|
||||
$(daySelector).select2({
|
||||
tags: false
|
||||
});
|
||||
newTableRowTime.appendChild(rowTimeContent);
|
||||
|
||||
newTableRowBody.appendChild(newTableRowTime);
|
||||
|
||||
// add start and end times
|
||||
var newTableRowClock = document.createElement('tr');
|
||||
var rowClockSpace = document.createElement('td');
|
||||
newTableRowClock.appendChild(rowClockSpace);
|
||||
|
||||
var rowClockContentTitle = document.createElement('td');
|
||||
rowClockContentTitle.className = 'romcell';
|
||||
rowClockContentTitle.innerHTML = "Time Range:";
|
||||
newTableRowClock.appendChild(rowClockContentTitle);
|
||||
|
||||
var rowClockContent = document.createElement('td');
|
||||
rowClockContent.className = 'romcell';
|
||||
// rowClockContent.setAttribute('colspan', 2);
|
||||
|
||||
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'Start', value.defaultAllowedStartHours, value.defaultAllowedStartMinutes, value.allowedStartHours, value.allowedStartMinutes));
|
||||
|
||||
rowClockContentSeparator = document.createElement('span');
|
||||
rowClockContentSeparator.innerHTML = ' - ';
|
||||
rowClockContent.appendChild(rowClockContentSeparator);
|
||||
|
||||
rowClockContent.appendChild(generateTimeDropDowns(value.task, 'End', value.defaultAllowedEndHours, value.defaultAllowedEndMinutes, value.allowedEndHours, value.allowedEndMinutes));
|
||||
|
||||
newTableRowClock.appendChild(rowClockContent);
|
||||
|
||||
newTableRowBody.appendChild(newTableRowClock);
|
||||
|
||||
// blocks tasks
|
||||
var newTableRowBlocks = document.createElement('tr');
|
||||
var rowBlocksSpace = document.createElement('td');
|
||||
newTableRowBlocks.appendChild(rowBlocksSpace);
|
||||
|
||||
var rowBlocksContentTitle = document.createElement('td');
|
||||
rowBlocksContentTitle.className = 'romcell';
|
||||
rowBlocksContentTitle.innerHTML = "Blocks:";
|
||||
newTableRowBlocks.appendChild(rowBlocksContentTitle);
|
||||
|
||||
var rowBlocksContent = document.createElement('td');
|
||||
rowBlocksContent.className = 'romcell';
|
||||
// rowBlocksContent.setAttribute('colspan', 2);
|
||||
var blocksString = "";
|
||||
for (var i = 0; i < value.blocks.length; i++) {
|
||||
if (blocksString.length > 0) { blocksString += ", "; }
|
||||
blocksString += GetTaskFriendlyName(value.blocks[i]);
|
||||
}
|
||||
if (blocksString.length == 0) { blocksString = 'None'; }
|
||||
rowBlocksContent.innerHTML = blocksString;
|
||||
newTableRowBlocks.appendChild(rowBlocksContent);
|
||||
|
||||
newTableRowBody.appendChild(newTableRowBlocks);
|
||||
|
||||
// blocked by tasks
|
||||
var newTableRowBlockedBy = document.createElement('tr');
|
||||
var rowBlockedBySpace = document.createElement('td');
|
||||
newTableRowBlockedBy.appendChild(rowBlockedBySpace);
|
||||
|
||||
var rowBlockedByContentTitle = document.createElement('td');
|
||||
rowBlockedByContentTitle.className = 'romcell';
|
||||
rowBlockedByContentTitle.innerHTML = "Blocked By:";
|
||||
newTableRowBlockedBy.appendChild(rowBlockedByContentTitle);
|
||||
|
||||
var rowBlockedByContent = document.createElement('td');
|
||||
rowBlockedByContent.className = 'romcell';
|
||||
// rowBlockedByContent.setAttribute('colspan', 2);
|
||||
var BlockedByString = "";
|
||||
for (var i = 0; i < value.blockedBy.length; i++) {
|
||||
if (BlockedByString.length > 0) { BlockedByString += ", "; }
|
||||
BlockedByString += GetTaskFriendlyName(value.blockedBy[i]);
|
||||
}
|
||||
if (BlockedByString.length == 0) { BlockedByString = 'None'; }
|
||||
rowBlockedByContent.innerHTML = BlockedByString;
|
||||
newTableRowBlockedBy.appendChild(rowBlockedByContent);
|
||||
|
||||
newTableRowBody.appendChild(newTableRowBlockedBy);
|
||||
|
||||
// complete row
|
||||
targetTable.appendChild(newTableRowBody);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function generateTimeDropDowns(taskName, rangeName, defaultHour, defaultMinute, valueHour, valueMinute) {
|
||||
var container = document.createElement('div');
|
||||
container.style.display = 'inline';
|
||||
|
||||
var elementName = 'settings_tasktimers_time';
|
||||
|
||||
var hourSelector = document.createElement('input');
|
||||
hourSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Hour';
|
||||
hourSelector.name = elementName;
|
||||
hourSelector.setAttribute('data-name', taskName);
|
||||
hourSelector.setAttribute('type', 'number');
|
||||
hourSelector.setAttribute('min', '0');
|
||||
hourSelector.setAttribute('max', '23');
|
||||
hourSelector.setAttribute('placeholder', defaultHour);
|
||||
hourSelector.value = valueHour;
|
||||
container.appendChild(hourSelector);
|
||||
|
||||
var separator = document.createElement('span');
|
||||
separator.innerHTML = " : ";
|
||||
container.appendChild(separator);
|
||||
|
||||
var minSelector = document.createElement('input');
|
||||
minSelector.id = 'settings_tasktimers_' + taskName + '_' + rangeName + '_Minute';
|
||||
minSelector.name = elementName;
|
||||
minSelector.setAttribute('type', 'number');
|
||||
minSelector.setAttribute('min', '0');
|
||||
minSelector.setAttribute('max', '59');
|
||||
minSelector.setAttribute('placeholder', defaultMinute);
|
||||
minSelector.value = valueMinute;
|
||||
container.appendChild(minSelector);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
function saveTaskTimers() {
|
||||
var timerValues = document.getElementsByName('settings_tasktimers_values');
|
||||
|
||||
var model = [];
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
var taskName = timerValues[i].getAttribute('data-name');
|
||||
var taskEnabled = document.getElementById('settings_enabled_' + taskName).checked;
|
||||
var taskIntervalObj = document.getElementById('settings_tasktimers_' + taskName);
|
||||
var taskInterval = function() { if (taskIntervalObj.value) { return taskIntervalObj.value; } else { return taskIntervalObj.getAttribute('placeholder'); } };
|
||||
var taskDaysRaw = $('#settings_alloweddays_' + taskName).select2('data');
|
||||
var taskDays = [];
|
||||
if (taskDaysRaw.length > 0) {
|
||||
for (var d = 0; d < taskDaysRaw.length; d++) {
|
||||
taskDays.push(taskDaysRaw[d].id);
|
||||
}
|
||||
} else {
|
||||
taskDays.push("Monday");
|
||||
}
|
||||
var taskStartHourObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Hour');
|
||||
var taskStartMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_Start_Minute');
|
||||
var taskEndHourObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Hour');
|
||||
var taskEndMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Minute');
|
||||
|
||||
var taskStartHour = function() { if (taskStartHourObj.value) { return taskStartHourObj.value; } else { return taskStartHourObj.getAttribute('placeholder'); } };
|
||||
var taskStartMinute = function() { if (taskStartMinuteObj.value) { return taskStartMinuteObj.value; } else { return taskStartMinuteObj.getAttribute('placeholder'); } };
|
||||
var taskEndHour = function() { if (taskEndHourObj.value) { return taskEndHourObj.value; } else { return taskEndHourObj.getAttribute('placeholder'); } };
|
||||
var taskEndMinute = function() { if (taskEndMinuteObj.value) { return taskEndMinuteObj.value; } else { return taskEndMinuteObj.getAttribute('placeholder'); } };
|
||||
|
||||
model.push(
|
||||
{
|
||||
"task": taskName,
|
||||
"enabled": taskEnabled,
|
||||
"interval": taskInterval(),
|
||||
"allowedDays": taskDays,
|
||||
"allowedStartHours": taskStartHour(),
|
||||
"allowedStartMinutes": taskStartMinute(),
|
||||
"allowedEndHours": taskEndHour(),
|
||||
"allowedEndMinutes": taskEndMinute()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ajaxCall(
|
||||
'/api/v1/System/Settings/BackgroundTasks/Configuration',
|
||||
'POST',
|
||||
function(result) {
|
||||
getBackgroundTaskTimers();
|
||||
},
|
||||
function(error) {
|
||||
getBackgroundTaskTimers();
|
||||
},
|
||||
JSON.stringify(model)
|
||||
);
|
||||
}
|
||||
|
||||
function defaultTaskTimers() {
|
||||
var timerValues = document.getElementsByName('settings_tasktimers_enabled');
|
||||
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
timerValues[i].checked = true;
|
||||
}
|
||||
|
||||
var timerValues = document.getElementsByName('settings_tasktimers_values');
|
||||
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
timerValues[i].value = timerValues[i].getAttribute('data-default');
|
||||
}
|
||||
|
||||
var timerValues = document.getElementsByName('settings_alloweddays');
|
||||
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
var defaultSelections = timerValues[i].getAttribute('data-default').split(',');
|
||||
$(timerValues[i]).val(defaultSelections);
|
||||
$(timerValues[i]).trigger('change');
|
||||
}
|
||||
|
||||
var timerValues = document.getElementsByName('settings_tasktimers_time');
|
||||
|
||||
for (var i = 0; i < timerValues.length; i++) {
|
||||
timerValues[i].value = timerValues[i].getAttribute('placeholder');
|
||||
}
|
||||
|
||||
saveTaskTimers();
|
||||
}
|
||||
|
||||
function getSystemSettings() {
|
||||
ajaxCall(
|
||||
'/api/v1/System/Settings/System',
|
||||
'GET',
|
||||
function(result) {
|
||||
function (result) {
|
||||
var optionToSelect = 'settings_logs_write_db';
|
||||
if (result.alwaysLogToDisk == true) {
|
||||
optionToSelect = 'settings_logs_write_fs';
|
||||
@@ -403,6 +114,27 @@
|
||||
document.getElementById('settings_logs_retention').value = result.minimumLogRetentionPeriod;
|
||||
|
||||
document.getElementById('settings_emulator_debug').checked = result.emulatorDebugMode;
|
||||
|
||||
switch (result.signatureSource.source) {
|
||||
case "LocalOnly":
|
||||
document.getElementById('settings_signaturesource_local').checked = true;
|
||||
break;
|
||||
|
||||
case "Hasheous":
|
||||
document.getElementById('settings_signaturesource_hasheous').checked = true;
|
||||
document.getElementById('settings_hasheoushost_row').style.display = '';
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
document.getElementById('settings_signaturesource_hasheoushost').value = result.signatureSource.hasheousHost;
|
||||
|
||||
let hasheousSubmitCheck = document.getElementById('settings_hasheoussubmit');
|
||||
if (result.signatureSource.hasheousSubmitFixes == true) {
|
||||
hasheousSubmitCheck.checked = true;
|
||||
}
|
||||
document.getElementById('settings_hasheousapikey').innerHTML = result.signatureSource.hasheousAPIKey;
|
||||
toggleHasheousAPIKey(hasheousSubmitCheck);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -423,24 +155,37 @@
|
||||
|
||||
var model = {
|
||||
"alwaysLogToDisk": alwaysLogToDisk,
|
||||
"minimumLogRetentionPeriod": retentionValue,
|
||||
"emulatorDebugMode": document.getElementById('settings_emulator_debug').checked
|
||||
"minimumLogRetentionPeriod": Number(retentionValue),
|
||||
"emulatorDebugMode": document.getElementById('settings_emulator_debug').checked,
|
||||
"signatureSource": {
|
||||
"Source": $("input[type='radio'][name='settings_signaturesource']:checked").val(),
|
||||
"HasheousHost": document.getElementById('settings_signaturesource_hasheoushost').value,
|
||||
"HasheousAPIKey": document.getElementById('settings_hasheousapikey').innerHTML,
|
||||
"HasheousSubmitFixes": document.getElementById('settings_hasheoussubmit').checked
|
||||
}
|
||||
};
|
||||
|
||||
ajaxCall(
|
||||
'/api/v1/System/Settings/System',
|
||||
'POST',
|
||||
function(result) {
|
||||
function (result) {
|
||||
getSystemSettings();
|
||||
},
|
||||
function(error) {
|
||||
function (error) {
|
||||
getSystemSettings();
|
||||
},
|
||||
JSON.stringify(model)
|
||||
);
|
||||
}
|
||||
|
||||
drawLibrary();
|
||||
getBackgroundTaskTimers();
|
||||
function toggleHasheousAPIKey(checkbox) {
|
||||
let settings_hasheousapikey_row = document.getElementById('settings_hasheousapikey_row');
|
||||
if (checkbox.checked == true) {
|
||||
settings_hasheousapikey_row.style.display = '';
|
||||
} else {
|
||||
settings_hasheousapikey_row.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
getSystemSettings();
|
||||
</script>
|
@@ -22,7 +22,7 @@
|
||||
<p><strong>Database</strong></p>
|
||||
<div id="system_database"></div>
|
||||
|
||||
<h3>Signatures</h3>
|
||||
<h3>Local Database Signatures</h3>
|
||||
<div id="system_signatures"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -82,7 +82,7 @@
|
||||
var nextRunTime = moment(result[i].nextRunTime).format("YYYY-MM-DD h:mm:ss a");
|
||||
var startButton = '';
|
||||
if (userProfile.roles.includes("Admin")) {
|
||||
if (result[i].allowManualStart == true && ![ "Running"].includes(result[i].itemState) && result[i].isBlocked == false) {
|
||||
if (result[i].allowManualStart == true && !["Running"].includes(result[i].itemState) && result[i].isBlocked == false) {
|
||||
startButton = "<span id='startProcess' class='romstart' onclick='StartProcess(\"" + result[i].itemType + "\");'>Start</span>";
|
||||
}
|
||||
}
|
||||
|
@@ -23,21 +23,29 @@ h3 {
|
||||
border-bottom-width: 1px;
|
||||
/*border-image: linear-gradient(to right, blue 25%, yellow 25%, yellow 50%,red 50%, red 75%, teal 75%) 5;*/
|
||||
|
||||
border-image: linear-gradient(to right, rgba(255,0,0,1) 0%, rgba(251,255,0,1) 16%, rgba(0,255,250,1) 30%, rgba(0,16,255,1) 46%, rgba(250,0,255,1) 62%, rgba(255,0,0,1) 78%, rgba(255,237,0,1) 90%, rgba(20,255,0,1) 100%) 5;
|
||||
border-image: linear-gradient(to right, rgba(255, 0, 0, 1) 0%, rgba(251, 255, 0, 1) 16%, rgba(0, 255, 250, 1) 30%, rgba(0, 16, 255, 1) 46%, rgba(250, 0, 255, 1) 62%, rgba(255, 0, 0, 1) 78%, rgba(255, 237, 0, 1) 90%, rgba(20, 255, 0, 1) 100%) 5;
|
||||
}
|
||||
|
||||
/* The Modal (background) */
|
||||
.modal {
|
||||
display: none; /* Hidden by default */
|
||||
position: fixed; /* Stay in place */
|
||||
z-index: 100; /* Sit on top */
|
||||
display: none;
|
||||
/* Hidden by default */
|
||||
position: fixed;
|
||||
/* Stay in place */
|
||||
z-index: 100;
|
||||
/* Sit on top */
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%; /* Full width */
|
||||
height: 100%; /* Full height */
|
||||
overflow: none; /* Enable scroll if needed */
|
||||
background-color: rgb(0,0,0); /* Fallback color */
|
||||
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
|
||||
width: 100%;
|
||||
/* Full width */
|
||||
height: 100%;
|
||||
/* Full height */
|
||||
overflow: none;
|
||||
/* Enable scroll if needed */
|
||||
background-color: rgb(0, 0, 0);
|
||||
/* Fallback color */
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
/* Black w/ opacity */
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
filter: drop-shadow(5px 5px 10px #000);
|
||||
@@ -47,22 +55,28 @@ h3 {
|
||||
/* Modal Content/Box */
|
||||
.modal-content {
|
||||
background-color: #383838;
|
||||
margin: 10% auto; /* 15% from the top and centered */
|
||||
margin: 10% auto;
|
||||
/* 15% from the top and centered */
|
||||
padding: 10px;
|
||||
border: 1px solid #888;
|
||||
border-radius: 10px;
|
||||
width: 700px; /* Could be more or less, depending on screen size */
|
||||
width: 700px;
|
||||
/* Could be more or less, depending on screen size */
|
||||
min-height: 358px;
|
||||
}
|
||||
|
||||
.modal-content-sub {
|
||||
background-color: #383838;
|
||||
margin: 20% auto; /* 20% from the top and centered */
|
||||
margin: 20% auto;
|
||||
/* 20% from the top and centered */
|
||||
padding: 10px;
|
||||
border: 1px solid #888;
|
||||
border-radius: 10px;
|
||||
width: 300px; /* Could be more or less, depending on screen size */
|
||||
width: 300px;
|
||||
/* Could be more or less, depending on screen size */
|
||||
min-height: 110px;
|
||||
}
|
||||
|
||||
#modal-heading {
|
||||
margin-block: 5px;
|
||||
border-bottom-style: solid;
|
||||
@@ -70,8 +84,9 @@ h3 {
|
||||
border-bottom-width: 3px;
|
||||
/*border-image: linear-gradient(to right, blue 25%, yellow 25%, yellow 50%,red 50%, red 75%, teal 75%) 5;*/
|
||||
|
||||
border-image: linear-gradient(to right, rgba(255,0,0,1) 0%, rgba(251,255,0,1) 16%, rgba(0,255,250,1) 30%, rgba(0,16,255,1) 46%, rgba(250,0,255,1) 62%, rgba(255,0,0,1) 78%, rgba(255,237,0,1) 90%, rgba(20,255,0,1) 100%) 5;
|
||||
border-image: linear-gradient(to right, rgba(255, 0, 0, 1) 0%, rgba(251, 255, 0, 1) 16%, rgba(0, 255, 250, 1) 30%, rgba(0, 16, 255, 1) 46%, rgba(250, 0, 255, 1) 62%, rgba(255, 0, 0, 1) 78%, rgba(255, 237, 0, 1) 90%, rgba(20, 255, 0, 1) 100%) 5;
|
||||
}
|
||||
|
||||
#modal-content {
|
||||
height: 100%;
|
||||
}
|
||||
@@ -296,7 +311,13 @@ h3 {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
input[type='text'], input[type='number'], input[type="email"], input[type="password"], input[type="datetime-local"] {
|
||||
input[type='text'],
|
||||
input[type='number'],
|
||||
input[type="email"],
|
||||
input[type="password"],
|
||||
input[type="datetime-local"],
|
||||
input[type="url"],
|
||||
textarea {
|
||||
background-color: #2b2b2b;
|
||||
color: white;
|
||||
padding: 4px;
|
||||
@@ -313,10 +334,21 @@ input[type='text'], input[type='number'], input[type="email"], input[type="passw
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
input[type='text']:hover, input[type='number']:hover, input[type="email"]:hover, input[type="password"]:hover, input[type="datetime-local"]:hover {
|
||||
input[type='text']:hover,
|
||||
input[type='number']:hover,
|
||||
input[type="email"]:hover,
|
||||
input[type="password"]:hover,
|
||||
input[type="datetime-local"]:hover,
|
||||
input[type="url"]:hover,
|
||||
textarea:hover {
|
||||
border-color: #939393;
|
||||
}
|
||||
|
||||
textarea {
|
||||
height: unset;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
input[id='filter_panel_search'] {
|
||||
width: 160px;
|
||||
}
|
||||
@@ -351,9 +383,7 @@ input[name='filter_panel_range_max'] {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
.text_link {
|
||||
|
||||
}
|
||||
.text_link {}
|
||||
|
||||
.text_link:hover {
|
||||
cursor: pointer;
|
||||
@@ -390,9 +420,9 @@ input[name='filter_panel_range_max'] {
|
||||
background-color: rgba(0, 22, 56, 0.8);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
}
|
||||
|
||||
.games_pager_number {
|
||||
@@ -586,22 +616,22 @@ input[name='filter_panel_range_max'] {
|
||||
|
||||
.game_tile:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
/* text-decoration: underline;
|
||||
background-color: #2b2b2b;
|
||||
border-radius: 10px 10px 10px 10px;
|
||||
-webkit-border-radius: 10px 10px 10px 10px;
|
||||
-moz-border-radius: 10px 10px 10px 10px;
|
||||
border: 1px solid #2b2b2b;
|
||||
border: 1px solid #2b2b2b; */
|
||||
}
|
||||
|
||||
.game_tile_small:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
/* text-decoration: underline;
|
||||
background-color: #2b2b2b;
|
||||
border-radius: 10px 10px 10px 10px;
|
||||
-webkit-border-radius: 10px 10px 10px 10px;
|
||||
-moz-border-radius: 10px 10px 10px 10px;
|
||||
border: 1px solid #2b2b2b;
|
||||
border: 1px solid #2b2b2b; */
|
||||
}
|
||||
|
||||
.game_tile_row {
|
||||
@@ -625,6 +655,19 @@ input[name='filter_panel_range_max'] {
|
||||
display: inline-block;
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
border-radius: 7px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.game_tile:hover .game_tile_box {
|
||||
border-color: yellow;
|
||||
outline-width: 2px;
|
||||
outline-style: solid;
|
||||
outline-offset: -3px;
|
||||
outline-color: black;
|
||||
}
|
||||
|
||||
.game_tile_box_row {
|
||||
@@ -706,9 +749,9 @@ input[name='filter_panel_range_max'] {
|
||||
}
|
||||
|
||||
.game_tile_image_shadow {
|
||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
}
|
||||
|
||||
.game_tile_image_row {
|
||||
@@ -720,11 +763,13 @@ input[name='filter_panel_range_max'] {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.game_tile_image, .unknown {
|
||||
.game_tile_image,
|
||||
.unknown {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.game_tile_image_row, .unknown {
|
||||
.game_tile_image_row,
|
||||
.unknown {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
@@ -790,9 +835,9 @@ input[name='filter_panel_range_max'] {
|
||||
max-width: 250px;
|
||||
max-height: 350px;
|
||||
width: 100%;
|
||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
}
|
||||
|
||||
.gamegenrelabel {
|
||||
@@ -842,9 +887,9 @@ input[name='filter_panel_range_max'] {
|
||||
padding: 10px;
|
||||
/*height: 350px;*/
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
}
|
||||
|
||||
#gamescreenshots_main {
|
||||
@@ -903,11 +948,16 @@ iframe {
|
||||
background-color: #383838;
|
||||
color: black;
|
||||
text-align: center;
|
||||
user-select: none; /* standard syntax */
|
||||
-webkit-user-select: none; /* webkit (safari, chrome) browsers */
|
||||
-moz-user-select: none; /* mozilla browsers */
|
||||
-khtml-user-select: none; /* webkit (konqueror) browsers */
|
||||
-ms-user-select: none; /* IE10+ */
|
||||
user-select: none;
|
||||
/* standard syntax */
|
||||
-webkit-user-select: none;
|
||||
/* webkit (safari, chrome) browsers */
|
||||
-moz-user-select: none;
|
||||
/* mozilla browsers */
|
||||
-khtml-user-select: none;
|
||||
/* webkit (konqueror) browsers */
|
||||
-ms-user-select: none;
|
||||
/* IE10+ */
|
||||
}
|
||||
|
||||
.gamescreenshots_arrows:hover {
|
||||
@@ -981,9 +1031,7 @@ iframe {
|
||||
background-color: rgba(56, 56, 56, 0.9);
|
||||
}
|
||||
|
||||
#gamesummarytext_label {
|
||||
|
||||
}
|
||||
#gamesummarytext_label {}
|
||||
|
||||
.line-clamp-4 {
|
||||
overflow: hidden;
|
||||
@@ -1057,9 +1105,9 @@ th {
|
||||
-webkit-border-radius: 5px 5px 5px 5px;
|
||||
-moz-border-radius: 5px 5px 5px 5px;
|
||||
border: 1px solid #19d348;
|
||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
}
|
||||
|
||||
.romstart:hover {
|
||||
@@ -1084,9 +1132,9 @@ th {
|
||||
border-color: white;
|
||||
background-color: blue;
|
||||
outline-color: blue;
|
||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
}
|
||||
|
||||
.properties_button:hover {
|
||||
@@ -1115,14 +1163,18 @@ th {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
div[name="properties_toc_item"],div[name="properties_user_toc_item"],div[name="properties_profile_toc_item"] {
|
||||
div[name="properties_toc_item"],
|
||||
div[name="properties_user_toc_item"],
|
||||
div[name="properties_profile_toc_item"] {
|
||||
padding: 10px;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: #2b2b2b;
|
||||
}
|
||||
|
||||
div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover,div[name="properties_profile_toc_item"]:hover {
|
||||
div[name="properties_toc_item"]:hover,
|
||||
div[name="properties_user_toc_item"]:hover,
|
||||
div[name="properties_profile_toc_item"]:hover {
|
||||
background-color: #2b2b2b;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1150,7 +1202,8 @@ div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.select2-container--default:hover, .select2-selection--multiple:hover {
|
||||
.select2-container--default:hover,
|
||||
.select2-selection--multiple:hover {
|
||||
border-color: #939393;
|
||||
}
|
||||
|
||||
@@ -1197,7 +1250,8 @@ div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.select2-selection--single:hover, .select2-selection__rendered:hover {
|
||||
.select2-selection--single:hover,
|
||||
.select2-selection__rendered:hover {
|
||||
border-color: #939393;
|
||||
}
|
||||
|
||||
@@ -1302,9 +1356,7 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
#emulator {
|
||||
|
||||
}
|
||||
#emulator {}
|
||||
|
||||
.emulator_partscreen {
|
||||
margin: 0 auto;
|
||||
@@ -1377,15 +1429,14 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.rom_checkbox_box {
|
||||
|
||||
}
|
||||
.rom_checkbox_box {}
|
||||
|
||||
.rom_checkbox_box_hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#rom_edit, #rom_edit_delete {
|
||||
#rom_edit,
|
||||
#rom_edit_delete {
|
||||
float: right;
|
||||
}
|
||||
|
||||
@@ -1398,9 +1449,9 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
}
|
||||
|
||||
#game {
|
||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||
}
|
||||
|
||||
#gametitle_criticrating {
|
||||
@@ -1440,7 +1491,7 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
width: 1000px;
|
||||
height: 90%;
|
||||
margin: 25px auto;
|
||||
/* overflow-x: scroll;*/
|
||||
/* overflow-x: scroll;*/
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -1468,7 +1519,8 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
}
|
||||
|
||||
.bgalt1 {
|
||||
background-color: transparent;;
|
||||
background-color: transparent;
|
||||
;
|
||||
}
|
||||
|
||||
.logs_table_cell_150px {
|
||||
@@ -1520,13 +1572,33 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
background-color: #383838;
|
||||
}
|
||||
|
||||
.string { color: lightblue; }
|
||||
.number { color: lightblue; }
|
||||
.boolean { color: lightblue; }
|
||||
.null { color: magenta; }
|
||||
.key { color: greenyellow; }
|
||||
.brace { color: #888; }
|
||||
.square { color: #fff000; }
|
||||
.string {
|
||||
color: lightblue;
|
||||
}
|
||||
|
||||
.number {
|
||||
color: lightblue;
|
||||
}
|
||||
|
||||
.boolean {
|
||||
color: lightblue;
|
||||
}
|
||||
|
||||
.null {
|
||||
color: magenta;
|
||||
}
|
||||
|
||||
.key {
|
||||
color: greenyellow;
|
||||
}
|
||||
|
||||
.brace {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.square {
|
||||
color: #fff000;
|
||||
}
|
||||
|
||||
.tagBox {
|
||||
position: absolute;
|
||||
@@ -1557,12 +1629,16 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
}
|
||||
|
||||
.loginwindow {
|
||||
position: fixed; /* Stay in place */
|
||||
position: fixed;
|
||||
/* Stay in place */
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%; /* Full width */
|
||||
height: 100%; /* Full height */
|
||||
overflow: auto; /* Enable scroll if needed */
|
||||
width: 100%;
|
||||
/* Full width */
|
||||
height: 100%;
|
||||
/* Full height */
|
||||
overflow: auto;
|
||||
/* Enable scroll if needed */
|
||||
/*background-color: rgb(0,0,0); /* Fallback color */
|
||||
/*background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
|
||||
/*backdrop-filter: blur(8px);
|
||||
@@ -1575,11 +1651,13 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
.loginwindow-content {
|
||||
position: relative;
|
||||
background-color: #383838;
|
||||
margin: 15% auto; /* 15% from the top and centered */
|
||||
margin: 15% auto;
|
||||
/* 15% from the top and centered */
|
||||
padding: 10px;
|
||||
border: 1px solid #888;
|
||||
border-radius: 10px;
|
||||
width: 350px; /* Could be more or less, depending on screen size */
|
||||
width: 350px;
|
||||
/* Could be more or less, depending on screen size */
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
@@ -1615,7 +1693,8 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
}
|
||||
|
||||
/* Links inside the dropdown */
|
||||
.dropdown-content a, .dropdown-content span {
|
||||
.dropdown-content a,
|
||||
.dropdown-content span {
|
||||
color: black;
|
||||
padding: 12px 16px;
|
||||
text-decoration: none;
|
||||
@@ -1627,10 +1706,14 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
}
|
||||
|
||||
/* Change color of dropdown links on hover */
|
||||
.dropdown-content a:hover {background-color: #ddd;}
|
||||
.dropdown-content a:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
|
||||
.show {display:block;}
|
||||
.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdownroleitem {
|
||||
text-transform: capitalize;
|
||||
|
Reference in New Issue
Block a user