Compare commits
11 Commits
v1.7.0-pre
...
v1.7.0-pre
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7f2e186d06 | ||
![]() |
7d5419d33c | ||
![]() |
ce9ab91e5b | ||
![]() |
eac35ee8a3 | ||
![]() |
49f36a2b99 | ||
![]() |
47c2fc8069 | ||
![]() |
9a215123f6 | ||
![]() |
40597b4386 | ||
![]() |
eb9c1ce1a4 | ||
![]() |
7be1ec7080 | ||
![]() |
311c7733fa |
1
.gitignore
vendored
@@ -403,3 +403,4 @@ ASALocalRun/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
gaseous-server/.DS_Store
|
||||
|
BIN
gaseous-server/Assets/.DS_Store
vendored
BIN
gaseous-server/Assets/Ratings/.DS_Store
vendored
@@ -12,6 +12,7 @@ using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Newtonsoft.Json;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
@@ -66,7 +67,7 @@ namespace gaseous_server.Classes
|
||||
public static CollectionItem NewCollection(CollectionItem item)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "INSERT INTO RomCollections (`Name`, Description, Platforms, Genres, Players, PlayerPerspectives, Themes, MinimumRating, MaximumRating, MaximumRomsPerPlatform, MaximumBytesPerPlatform, MaximumCollectionSizeInBytes, FolderStructure, IncludeBIOSFiles, AlwaysInclude, BuiltStatus) VALUES (@name, @description, @platforms, @genres, @players, @playerperspectives, @themes, @minimumrating, @maximumrating, @maximumromsperplatform, @maximumbytesperplatform, @maximumcollectionsizeinbytes, @folderstructure, @includebiosfiles, @alwaysinclude, @builtstatus); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
string sql = "INSERT INTO RomCollections (`Name`, Description, Platforms, Genres, Players, PlayerPerspectives, Themes, MinimumRating, MaximumRating, MaximumRomsPerPlatform, MaximumBytesPerPlatform, MaximumCollectionSizeInBytes, FolderStructure, IncludeBIOSFiles, ArchiveType, AlwaysInclude, BuiltStatus) VALUES (@name, @description, @platforms, @genres, @players, @playerperspectives, @themes, @minimumrating, @maximumrating, @maximumromsperplatform, @maximumbytesperplatform, @maximumcollectionsizeinbytes, @folderstructure, @includebiosfiles, @archivetype, @alwaysinclude, @builtstatus); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("name", item.Name);
|
||||
dbDict.Add("description", item.Description);
|
||||
@@ -82,6 +83,7 @@ namespace gaseous_server.Classes
|
||||
dbDict.Add("maximumcollectionsizeinbytes", Common.ReturnValueIfNull(item.MaximumCollectionSizeInBytes, -1));
|
||||
dbDict.Add("folderstructure", Common.ReturnValueIfNull(item.FolderStructure, CollectionItem.FolderStructures.Gaseous));
|
||||
dbDict.Add("includebiosfiles", Common.ReturnValueIfNull(item.IncludeBIOSFiles, 0));
|
||||
dbDict.Add("archivetype", Common.ReturnValueIfNull(item.ArchiveType, CollectionItem.ArchiveTypes.Zip));
|
||||
dbDict.Add("alwaysinclude", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.AlwaysInclude, new List<CollectionItem.AlwaysIncludeItem>())));
|
||||
dbDict.Add("builtstatus", CollectionItem.CollectionBuildStatus.WaitingForBuild);
|
||||
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||
@@ -97,7 +99,7 @@ namespace gaseous_server.Classes
|
||||
public static CollectionItem EditCollection(long Id, CollectionItem item, bool ForceRebuild = true)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "UPDATE RomCollections SET `Name`=@name, Description=@description, Platforms=@platforms, Genres=@genres, Players=@players, PlayerPerspectives=@playerperspectives, Themes=@themes, MinimumRating=@minimumrating, MaximumRating=@maximumrating, MaximumRomsPerPlatform=@maximumromsperplatform, MaximumBytesPerPlatform=@maximumbytesperplatform, MaximumCollectionSizeInBytes=@maximumcollectionsizeinbytes, FolderStructure=@folderstructure, IncludeBIOSFiles=@includebiosfiles, AlwaysInclude=@alwaysinclude, BuiltStatus=@builtstatus WHERE Id=@id";
|
||||
string sql = "UPDATE RomCollections SET `Name`=@name, Description=@description, Platforms=@platforms, Genres=@genres, Players=@players, PlayerPerspectives=@playerperspectives, Themes=@themes, MinimumRating=@minimumrating, MaximumRating=@maximumrating, MaximumRomsPerPlatform=@maximumromsperplatform, MaximumBytesPerPlatform=@maximumbytesperplatform, MaximumCollectionSizeInBytes=@maximumcollectionsizeinbytes, FolderStructure=@folderstructure, IncludeBIOSFiles=@includebiosfiles, ArchiveType=@archivetype, AlwaysInclude=@alwaysinclude, BuiltStatus=@builtstatus WHERE Id=@id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", Id);
|
||||
dbDict.Add("name", item.Name);
|
||||
@@ -115,8 +117,9 @@ namespace gaseous_server.Classes
|
||||
dbDict.Add("folderstructure", Common.ReturnValueIfNull(item.FolderStructure, CollectionItem.FolderStructures.Gaseous));
|
||||
dbDict.Add("includebiosfiles", Common.ReturnValueIfNull(item.IncludeBIOSFiles, 0));
|
||||
dbDict.Add("alwaysinclude", Newtonsoft.Json.JsonConvert.SerializeObject(Common.ReturnValueIfNull(item.AlwaysInclude, new List<CollectionItem.AlwaysIncludeItem>())));
|
||||
dbDict.Add("archivetype", Common.ReturnValueIfNull(item.ArchiveType, CollectionItem.ArchiveTypes.Zip));
|
||||
|
||||
string CollectionZipFile = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ".zip");
|
||||
string CollectionZipFile = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + item.ArchiveExtension);
|
||||
if (ForceRebuild == true)
|
||||
{
|
||||
dbDict.Add("builtstatus", CollectionItem.CollectionBuildStatus.WaitingForBuild);
|
||||
@@ -304,7 +307,7 @@ namespace gaseous_server.Classes
|
||||
// calculate total rom size for the game
|
||||
long GameRomSize = 0;
|
||||
foreach (Roms.GameRomItem gameRom in gameRoms) {
|
||||
GameRomSize += gameRom.Size;
|
||||
GameRomSize += (long)gameRom.Size;
|
||||
}
|
||||
if (collectionItem.MaximumBytesPerPlatform > 0) {
|
||||
if ((TotalRomSize + GameRomSize) < collectionItem.MaximumBytesPerPlatform) {
|
||||
@@ -389,7 +392,7 @@ namespace gaseous_server.Classes
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<CollectionContents.CollectionPlatformItem> collectionPlatformItems = GetCollectionContent(collectionItem).Collection;
|
||||
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, collectionItem.Id + ".zip");
|
||||
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, collectionItem.Id + collectionItem.ArchiveExtension);
|
||||
string ZipFileTempPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, collectionItem.Id.ToString());
|
||||
|
||||
try
|
||||
@@ -508,7 +511,21 @@ namespace gaseous_server.Classes
|
||||
|
||||
// compress to zip
|
||||
Logging.Log(Logging.LogType.Information, "Collections", "Compressing collection");
|
||||
switch(collectionItem.ArchiveType)
|
||||
{
|
||||
case CollectionItem.ArchiveTypes.Zip:
|
||||
ZipFile.CreateFromDirectory(ZipFileTempPath, ZipFilePath, CompressionLevel.SmallestSize, false);
|
||||
break;
|
||||
|
||||
case CollectionItem.ArchiveTypes.RAR:
|
||||
|
||||
break;
|
||||
|
||||
case CollectionItem.ArchiveTypes.SevenZip:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// clean up
|
||||
if (Directory.Exists(ZipFileTempPath))
|
||||
@@ -567,6 +584,7 @@ namespace gaseous_server.Classes
|
||||
item.MaximumCollectionSizeInBytes = (long)Common.ReturnValueIfNull(row["MaximumCollectionSizeInBytes"], (long)-1);
|
||||
item.FolderStructure = (CollectionItem.FolderStructures)(int)Common.ReturnValueIfNull(row["FolderStructure"], 0);
|
||||
item.IncludeBIOSFiles = (bool)row["IncludeBIOSFiles"];
|
||||
item.ArchiveType = (CollectionItem.ArchiveTypes)(int)Common.ReturnValueIfNull(row["ArchiveType"], 0);
|
||||
item.AlwaysInclude = Newtonsoft.Json.JsonConvert.DeserializeObject<List<CollectionItem.AlwaysIncludeItem>>(strAlwaysInclude);
|
||||
item.BuildStatus = (CollectionItem.CollectionBuildStatus)(int)Common.ReturnValueIfNull(row["BuiltStatus"], 0);
|
||||
|
||||
@@ -595,6 +613,32 @@ namespace gaseous_server.Classes
|
||||
public long? MaximumCollectionSizeInBytes { get; set; }
|
||||
public FolderStructures FolderStructure { get; set; } = FolderStructures.Gaseous;
|
||||
public bool IncludeBIOSFiles { get; set; } = true;
|
||||
public ArchiveTypes ArchiveType { get; set; } = CollectionItem.ArchiveTypes.Zip;
|
||||
public string ArchiveExtension
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ArchiveType != null)
|
||||
{
|
||||
switch (ArchiveType)
|
||||
{
|
||||
case ArchiveTypes.Zip:
|
||||
default:
|
||||
return ".zip";
|
||||
|
||||
case ArchiveTypes.RAR:
|
||||
return ".rar";
|
||||
|
||||
case ArchiveTypes.SevenZip:
|
||||
return ".7z";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ".zip";
|
||||
}
|
||||
}
|
||||
}
|
||||
public List<AlwaysIncludeItem> AlwaysInclude { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
@@ -604,7 +648,7 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
if (_BuildStatus == CollectionBuildStatus.Completed)
|
||||
{
|
||||
if (File.Exists(Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ".zip")))
|
||||
if (File.Exists(Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ArchiveExtension)))
|
||||
{
|
||||
return CollectionBuildStatus.Completed;
|
||||
}
|
||||
@@ -632,7 +676,7 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
if (BuildStatus == CollectionBuildStatus.Completed)
|
||||
{
|
||||
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ".zip");
|
||||
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, Id + ArchiveExtension);
|
||||
if (File.Exists(ZipFilePath))
|
||||
{
|
||||
FileInfo fi = new FileInfo(ZipFilePath);
|
||||
@@ -665,6 +709,13 @@ namespace gaseous_server.Classes
|
||||
RetroPie = 1
|
||||
}
|
||||
|
||||
public enum ArchiveTypes
|
||||
{
|
||||
Zip = 0,
|
||||
RAR = 1,
|
||||
SevenZip = 2
|
||||
}
|
||||
|
||||
public class AlwaysIncludeItem
|
||||
{
|
||||
public long PlatformId { get; set; }
|
||||
@@ -749,7 +800,7 @@ namespace gaseous_server.Classes
|
||||
long Size = 0;
|
||||
foreach (CollectionGameItem Game in Games) {
|
||||
foreach (Roms.GameRomItem Rom in Game.Roms) {
|
||||
Size += Rom.Size;
|
||||
Size += (long)Rom.Size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -792,6 +843,15 @@ namespace gaseous_server.Classes
|
||||
public string Name { get; set; }
|
||||
public string Slug { get; set; }
|
||||
public long Cover { get; set;}
|
||||
public IGDB.Models.Cover CoverItem
|
||||
{
|
||||
get
|
||||
{
|
||||
IGDB.Models.Cover cover = Covers.GetCover(Cover, Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory, "Games", Slug), false);
|
||||
|
||||
return cover;
|
||||
}
|
||||
}
|
||||
|
||||
public CollectionItem.AlwaysIncludeItem InclusionStatus { get; set; }
|
||||
|
||||
@@ -801,7 +861,7 @@ namespace gaseous_server.Classes
|
||||
get {
|
||||
long Size = 0;
|
||||
foreach (Roms.GameRomItem Rom in Roms) {
|
||||
Size += Rom.Size;
|
||||
Size += (long)Rom.Size;
|
||||
}
|
||||
|
||||
return Size;
|
||||
|
@@ -1,9 +1,11 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class Common
|
||||
public static class Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns IfNullValue if the ObjectToCheck is null
|
||||
@@ -110,6 +112,14 @@ namespace gaseous_server.Classes
|
||||
return Path.GetFullPath(new Uri(path).LocalPath)
|
||||
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
}
|
||||
|
||||
public static string GetDescription(this Enum value)
|
||||
{
|
||||
return ((DescriptionAttribute)Attribute.GetCustomAttribute(
|
||||
value.GetType().GetFields(BindingFlags.Public | BindingFlags.Static)
|
||||
.Single(x => x.GetValue(null).Equals(value)),
|
||||
typeof(DescriptionAttribute)))?.Description ?? value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -473,22 +473,66 @@ namespace gaseous_server.Classes
|
||||
|
||||
public class MetadataAPI
|
||||
{
|
||||
private static Communications.MetadataSources _Source
|
||||
private static HasheousClient.Models.MetadataModel.MetadataSources _MetadataSource
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("metadatasource")))
|
||||
{
|
||||
return (Communications.MetadataSources)Enum.Parse(typeof(Communications.MetadataSources), Environment.GetEnvironmentVariable("metadatasource"));
|
||||
return (HasheousClient.Models.MetadataModel.MetadataSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.MetadataSources), Environment.GetEnvironmentVariable("metadatasource"));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Communications.MetadataSources.IGDB;
|
||||
return HasheousClient.Models.MetadataModel.MetadataSources.IGDB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Communications.MetadataSources Source = _Source;
|
||||
private static HasheousClient.Models.MetadataModel.SignatureSources _SignatureSource
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("signaturesource")))
|
||||
{
|
||||
return (HasheousClient.Models.MetadataModel.SignatureSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.SignatureSources), Environment.GetEnvironmentVariable("signaturesource"));
|
||||
}
|
||||
else
|
||||
{
|
||||
return HasheousClient.Models.MetadataModel.SignatureSources.LocalOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int _MaxLibraryScanWorkers
|
||||
{
|
||||
get
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
private static string _HasheousHost
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("hasheoushoust")))
|
||||
{
|
||||
return Environment.GetEnvironmentVariable("hasheoushoust");
|
||||
}
|
||||
else
|
||||
{
|
||||
return "https://hasheous.org/";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HasheousClient.Models.MetadataModel.MetadataSources MetadataSource = _MetadataSource;
|
||||
|
||||
public HasheousClient.Models.MetadataModel.SignatureSources SignatureSource = _SignatureSource;
|
||||
|
||||
public int MaxLibraryScanWorkers = _MaxLibraryScanWorkers;
|
||||
|
||||
public string HasheousHost = _HasheousHost;
|
||||
}
|
||||
|
||||
public class IGDB
|
||||
|
@@ -235,7 +235,8 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
case databaseType.MySql:
|
||||
MySQLServerConnector conn = new MySQLServerConnector(ConnectionString);
|
||||
return (int)conn.ExecNonQuery(Command, Parameters, Timeout);
|
||||
int retVal = conn.ExecNonQuery(Command, Parameters, Timeout);
|
||||
return retVal;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -329,7 +330,8 @@ namespace gaseous_server.Classes
|
||||
DataTable RetTable = new DataTable();
|
||||
|
||||
Logging.Log(Logging.LogType.Debug, "Database", "Connecting to database", null, true);
|
||||
MySqlConnection conn = new MySqlConnection(DBConn);
|
||||
using (MySqlConnection conn = new MySqlConnection(DBConn))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
MySqlCommand cmd = new MySqlCommand
|
||||
@@ -361,6 +363,7 @@ namespace gaseous_server.Classes
|
||||
|
||||
Logging.Log(Logging.LogType.Debug, "Database", "Closing database connection", null, true);
|
||||
conn.Close();
|
||||
}
|
||||
|
||||
return RetTable;
|
||||
}
|
||||
@@ -370,7 +373,8 @@ namespace gaseous_server.Classes
|
||||
int result = 0;
|
||||
|
||||
Logging.Log(Logging.LogType.Debug, "Database", "Connecting to database", null, true);
|
||||
MySqlConnection conn = new MySqlConnection(DBConn);
|
||||
using (MySqlConnection conn = new MySqlConnection(DBConn))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
MySqlCommand cmd = new MySqlCommand
|
||||
@@ -402,13 +406,15 @@ namespace gaseous_server.Classes
|
||||
|
||||
Logging.Log(Logging.LogType.Debug, "Database", "Closing database connection", null, true);
|
||||
conn.Close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void TransactionExecCMD(List<Dictionary<string, object>> Parameters, int Timeout)
|
||||
{
|
||||
var conn = new MySqlConnection(DBConn);
|
||||
using (MySqlConnection conn = new MySqlConnection(DBConn))
|
||||
{
|
||||
conn.Open();
|
||||
var command = conn.CreateCommand();
|
||||
MySqlTransaction transaction;
|
||||
@@ -425,6 +431,7 @@ namespace gaseous_server.Classes
|
||||
transaction.Commit();
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private MySqlCommand buildcommand(MySqlConnection Conn, string SQL, Dictionary<string, object> Parameters, int Timeout)
|
||||
{
|
||||
@@ -449,7 +456,8 @@ namespace gaseous_server.Classes
|
||||
|
||||
public bool TestConnection()
|
||||
{
|
||||
MySqlConnection conn = new MySqlConnection(DBConn);
|
||||
using (MySqlConnection conn = new MySqlConnection(DBConn))
|
||||
{
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
@@ -463,5 +471,6 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
373
gaseous-server/Classes/FileSignature.cs
Normal file
@@ -0,0 +1,373 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO.Compression;
|
||||
using HasheousClient.Models;
|
||||
using NuGet.Common;
|
||||
using SevenZip;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class FileSignature
|
||||
{
|
||||
public gaseous_server.Models.Signatures_Games GetFileSignature(GameLibrary.LibraryItem library, Common.hashObject hash, FileInfo fi, string GameFileImportPath)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Getting signature for file: " + GameFileImportPath);
|
||||
gaseous_server.Models.Signatures_Games discoveredSignature = new gaseous_server.Models.Signatures_Games();
|
||||
discoveredSignature = _GetFileSignature(hash, fi.Name, fi.Extension, fi.Length, GameFileImportPath, false);
|
||||
|
||||
string[] CompressionExts = { ".zip", ".rar", ".7z" };
|
||||
string ImportedFileExtension = Path.GetExtension(GameFileImportPath);
|
||||
|
||||
if (CompressionExts.Contains(ImportedFileExtension) && (fi.Length < 1073741824))
|
||||
{
|
||||
// file is a zip and less than 1 GiB
|
||||
// extract the zip file and search the contents
|
||||
|
||||
string ExtractPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, library.Id.ToString(), Path.GetRandomFileName());
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Decompressing " + GameFileImportPath + " to " + ExtractPath + " examine contents");
|
||||
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
|
||||
try
|
||||
{
|
||||
switch(ImportedFileExtension)
|
||||
{
|
||||
case ".zip":
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Decompressing using zip");
|
||||
try
|
||||
{
|
||||
using (var archive = SharpCompress.Archives.Zip.ZipArchive.Open(GameFileImportPath))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Extracting file: " + entry.Key);
|
||||
entry.WriteToDirectory(ExtractPath, new ExtractionOptions()
|
||||
{
|
||||
ExtractFullPath = true,
|
||||
Overwrite = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception zipEx)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Get Signature", "Unzip error", zipEx);
|
||||
throw;
|
||||
}
|
||||
break;
|
||||
|
||||
case ".rar":
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Decompressing using rar");
|
||||
try
|
||||
{
|
||||
using (var archive = RarArchive.Open(GameFileImportPath))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Extracting file: " + entry.Key);
|
||||
entry.WriteToDirectory(ExtractPath, new ExtractionOptions()
|
||||
{
|
||||
ExtractFullPath = true,
|
||||
Overwrite = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception zipEx)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Get Signature", "Unrar error", zipEx);
|
||||
throw;
|
||||
}
|
||||
break;
|
||||
|
||||
case ".7z":
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Decompressing using 7z");
|
||||
try
|
||||
{
|
||||
using (var archive = SharpCompress.Archives.SevenZip.SevenZipArchive.Open(GameFileImportPath))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Extracting file: " + entry.Key);
|
||||
entry.WriteToDirectory(ExtractPath, new ExtractionOptions()
|
||||
{
|
||||
ExtractFullPath = true,
|
||||
Overwrite = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception zipEx)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Get Signature", "7z error", zipEx);
|
||||
throw;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Processing decompressed files for signature matches");
|
||||
// loop through contents until we find the first signature match
|
||||
List<ArchiveData> archiveFiles = new List<ArchiveData>();
|
||||
bool signatureFound = false;
|
||||
foreach (string file in Directory.GetFiles(ExtractPath, "*.*", SearchOption.AllDirectories))
|
||||
{
|
||||
if (File.Exists(file))
|
||||
{
|
||||
FileInfo zfi = new FileInfo(file);
|
||||
Common.hashObject zhash = new Common.hashObject(file);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Checking signature of decompressed file " + file);
|
||||
|
||||
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);
|
||||
zDiscoveredSignature.Rom.Name = Path.ChangeExtension(zDiscoveredSignature.Rom.Name, ImportedFileExtension);
|
||||
|
||||
if (zDiscoveredSignature.Score > discoveredSignature.Score)
|
||||
{
|
||||
if (
|
||||
zDiscoveredSignature.Rom.SignatureSource == gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType.MAMEArcade ||
|
||||
zDiscoveredSignature.Rom.SignatureSource == gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType.MAMEMess
|
||||
)
|
||||
{
|
||||
zDiscoveredSignature.Rom.Name = zDiscoveredSignature.Game.Description + ImportedFileExtension;
|
||||
}
|
||||
zDiscoveredSignature.Rom.Crc = discoveredSignature.Rom.Crc;
|
||||
zDiscoveredSignature.Rom.Md5 = discoveredSignature.Rom.Md5;
|
||||
zDiscoveredSignature.Rom.Sha1 = discoveredSignature.Rom.Sha1;
|
||||
zDiscoveredSignature.Rom.Size = discoveredSignature.Rom.Size;
|
||||
discoveredSignature = zDiscoveredSignature;
|
||||
|
||||
signatureFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
discoveredSignature.Rom.Attributes.Add(new KeyValuePair<string, object>(
|
||||
"ZipContents", Newtonsoft.Json.JsonConvert.SerializeObject(archiveFiles)
|
||||
));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Get Signature", "Error processing compressed file: " + GameFileImportPath, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return discoveredSignature;
|
||||
}
|
||||
|
||||
private gaseous_server.Models.Signatures_Games _GetFileSignature(Common.hashObject hash, string ImageName, string ImageExtension, long ImageSize, string GameFileImportPath, bool IsInZip)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", "Checking signature for file: " + GameFileImportPath + "\nMD5 hash: " + hash.md5hash + "\nSHA1 hash: " + hash.sha1hash);
|
||||
|
||||
|
||||
gaseous_server.Models.Signatures_Games discoveredSignature = new gaseous_server.Models.Signatures_Games();
|
||||
|
||||
// do database search first
|
||||
gaseous_server.Models.Signatures_Games? dbSignature = _GetFileSignatureFromDatabase(hash, ImageName, ImageExtension, ImageSize, GameFileImportPath);
|
||||
|
||||
if (dbSignature != null)
|
||||
{
|
||||
// local signature found
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", "Signature found in local database for game: " + dbSignature.Game.Name);
|
||||
discoveredSignature = dbSignature;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no local signature attempt to pull from Hasheous
|
||||
dbSignature = _GetFileSignatureFromHasheous(hash, ImageName, ImageExtension, ImageSize, GameFileImportPath);
|
||||
|
||||
if (dbSignature != null)
|
||||
{
|
||||
// signature retrieved from Hasheous
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", "Signature retrieved from Hasheous for game: " + dbSignature.Game.Name);
|
||||
|
||||
discoveredSignature = dbSignature;
|
||||
}
|
||||
else
|
||||
{
|
||||
// construct a signature from file data
|
||||
dbSignature = _GetFileSignatureFromFileData(hash, ImageName, ImageExtension, ImageSize, GameFileImportPath);
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", "Signature generated from provided file for game: " + dbSignature.Game.Name);
|
||||
|
||||
discoveredSignature = dbSignature;
|
||||
}
|
||||
}
|
||||
|
||||
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, ImageExtension, false);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", " Determined import file as: " + discoveredSignature.Game.Name + " (" + discoveredSignature.Game.Year + ") " + discoveredSignature.Game.System);
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", " Platform determined to be: " + discoveredSignature.Flags.IGDBPlatformName + " (" + discoveredSignature.Flags.IGDBPlatformId + ")");
|
||||
|
||||
return discoveredSignature;
|
||||
}
|
||||
|
||||
private gaseous_server.Models.Signatures_Games? _GetFileSignatureFromDatabase(Common.hashObject hash, string ImageName, string ImageExtension, long ImageSize, string GameFileImportPath)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Checking local database for MD5: " + hash.md5hash);
|
||||
|
||||
// check 1: do we have a signature for it?
|
||||
gaseous_server.Classes.SignatureManagement sc = new SignatureManagement();
|
||||
List<gaseous_server.Models.Signatures_Games> signatures = sc.GetSignature(hash.md5hash);
|
||||
if (signatures == null || signatures.Count == 0)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Checking local database for SHA1: " + hash.sha1hash);
|
||||
|
||||
// no md5 signature found - try sha1
|
||||
signatures = sc.GetSignature("", hash.sha1hash);
|
||||
}
|
||||
|
||||
gaseous_server.Models.Signatures_Games? discoveredSignature = null;
|
||||
if (signatures.Count == 1)
|
||||
{
|
||||
// only 1 signature found!
|
||||
discoveredSignature = signatures.ElementAt(0);
|
||||
|
||||
return discoveredSignature;
|
||||
}
|
||||
else if (signatures.Count > 1)
|
||||
{
|
||||
// more than one signature found - find one with highest score
|
||||
// start with first returned element
|
||||
discoveredSignature = signatures.First();
|
||||
foreach (gaseous_server.Models.Signatures_Games Sig in signatures)
|
||||
{
|
||||
if (Sig.Score > discoveredSignature.Score)
|
||||
{
|
||||
discoveredSignature = Sig;
|
||||
}
|
||||
}
|
||||
|
||||
return discoveredSignature;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private gaseous_server.Models.Signatures_Games? _GetFileSignatureFromHasheous(Common.hashObject hash, string ImageName, string ImageExtension, long ImageSize, string GameFileImportPath)
|
||||
{
|
||||
// check if hasheous is enabled, and if so use it's signature database
|
||||
if (Config.MetadataConfiguration.SignatureSource == HasheousClient.Models.MetadataModel.SignatureSources.Hasheous)
|
||||
{
|
||||
HasheousClient.Hasheous hasheous = new HasheousClient.Hasheous();
|
||||
SignatureLookupItem? HasheousResult = hasheous.RetrieveFromHasheousAsync(new HashLookupModel{
|
||||
MD5 = hash.md5hash,
|
||||
SHA1 = hash.sha1hash
|
||||
});
|
||||
|
||||
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;
|
||||
|
||||
if (HasheousResult.MetadataResults != null)
|
||||
{
|
||||
if (HasheousResult.MetadataResults.Count > 0)
|
||||
{
|
||||
foreach (SignatureLookupItem.MetadataResult metadataResult in HasheousResult.MetadataResults)
|
||||
{
|
||||
if (metadataResult.Source == MetadataModel.MetadataSources.IGDB)
|
||||
{
|
||||
signature.Flags.IGDBPlatformId = (long)metadataResult.PlatformId;
|
||||
signature.Flags.IGDBGameId = (long)metadataResult.GameId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private gaseous_server.Models.Signatures_Games _GetFileSignatureFromFileData(Common.hashObject hash, string ImageName, string ImageExtension, long ImageSize, string GameFileImportPath)
|
||||
{
|
||||
SignatureManagement signatureManagement = new SignatureManagement();
|
||||
|
||||
gaseous_server.Models.Signatures_Games discoveredSignature = new gaseous_server.Models.Signatures_Games();
|
||||
|
||||
// no signature match found - try name search
|
||||
List<gaseous_server.Models.Signatures_Games> signatures = signatureManagement.GetByTosecName(ImageName);
|
||||
|
||||
if (signatures.Count == 1)
|
||||
{
|
||||
// only 1 signature found!
|
||||
discoveredSignature = signatures.ElementAt(0);
|
||||
|
||||
return discoveredSignature;
|
||||
}
|
||||
else if (signatures.Count > 1)
|
||||
{
|
||||
// more than one signature found - find one with highest score
|
||||
foreach (gaseous_server.Models.Signatures_Games Sig in signatures)
|
||||
{
|
||||
if (Sig.Score > discoveredSignature.Score)
|
||||
{
|
||||
discoveredSignature = Sig;
|
||||
}
|
||||
}
|
||||
|
||||
return discoveredSignature;
|
||||
}
|
||||
else
|
||||
{
|
||||
// still no search - try alternate method
|
||||
gaseous_server.Models.Signatures_Games.GameItem gi = new gaseous_server.Models.Signatures_Games.GameItem();
|
||||
gaseous_server.Models.Signatures_Games.RomItem ri = new gaseous_server.Models.Signatures_Games.RomItem();
|
||||
|
||||
discoveredSignature.Game = gi;
|
||||
discoveredSignature.Rom = ri;
|
||||
|
||||
// game title is the file name without the extension or path
|
||||
gi.Name = Path.GetFileNameWithoutExtension(GameFileImportPath);
|
||||
|
||||
// remove everything after brackets - leaving (hopefully) only the name
|
||||
if (gi.Name.Contains("("))
|
||||
{
|
||||
gi.Name = gi.Name.Substring(0, gi.Name.IndexOf("(")).Trim();
|
||||
}
|
||||
|
||||
// remove special characters like dashes
|
||||
gi.Name = gi.Name.Replace("-", "").Trim();
|
||||
|
||||
// get rom data
|
||||
ri.Name = Path.GetFileName(GameFileImportPath);
|
||||
ri.Md5 = hash.md5hash;
|
||||
ri.Sha1 = hash.sha1hash;
|
||||
ri.Size = ImageSize;
|
||||
ri.SignatureSource = gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType.None;
|
||||
|
||||
return discoveredSignature;
|
||||
}
|
||||
}
|
||||
|
||||
public class ArchiveData
|
||||
{
|
||||
public string FileName { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public long Size { get; set; }
|
||||
public string MD5 { get; set; }
|
||||
public string SHA1 { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -34,6 +34,12 @@ namespace gaseous_server
|
||||
{}
|
||||
}
|
||||
|
||||
public class CannotDeleteLibraryWhileScanIsActive : Exception
|
||||
{
|
||||
public CannotDeleteLibraryWhileScanIsActive() : base("Unable to delete library while a library scan is active. Wait for all scans to complete and try again")
|
||||
{}
|
||||
}
|
||||
|
||||
// code
|
||||
public static LibraryItem GetDefaultLibrary
|
||||
{
|
||||
@@ -110,21 +116,42 @@ namespace gaseous_server
|
||||
|
||||
int newLibraryId = (int)(long)data.Rows[0][0];
|
||||
|
||||
return GetLibrary(newLibraryId);
|
||||
Logging.Log(Logging.LogType.Information, "Library Management", "Created library " + Name + " at directory " + PathName);
|
||||
|
||||
LibraryItem library = GetLibrary(newLibraryId);
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
public static void DeleteLibrary(int LibraryId)
|
||||
{
|
||||
if (GetLibrary(LibraryId).IsDefaultLibrary == false)
|
||||
LibraryItem library = GetLibrary(LibraryId);
|
||||
if (library.IsDefaultLibrary == false)
|
||||
{
|
||||
// check for active library scans
|
||||
foreach(ProcessQueue.QueueItem item in ProcessQueue.QueueItems)
|
||||
{
|
||||
if (
|
||||
(item.ItemType == ProcessQueue.QueueItemType.LibraryScan && item.ItemState == ProcessQueue.QueueItemState.Running) ||
|
||||
(item.ItemType == ProcessQueue.QueueItemType.LibraryScanWorker && item.ItemState == ProcessQueue.QueueItemState.Running)
|
||||
)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Library Management", "Unable to delete libraries while a library scan is running. Wait until the the library scan is completed and try again.");
|
||||
throw new CannotDeleteLibraryWhileScanIsActive();
|
||||
}
|
||||
}
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "DELETE FROM Games_Roms WHERE LibraryId=@id; DELETE FROM GameLibraries WHERE Id=@id;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", LibraryId);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Library Management", "Deleted library " + library.Name + " at path " + library.Path);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Library Management", "Unable to delete the default library.");
|
||||
throw new CannotDeleteDefaultLibrary();
|
||||
}
|
||||
}
|
||||
|
@@ -6,37 +6,38 @@ using System.Security.Policy;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Models;
|
||||
using IGDB.Models;
|
||||
using NuGet.Common;
|
||||
using NuGet.LibraryModel;
|
||||
using static gaseous_server.Classes.Metadata.Games;
|
||||
using static gaseous_server.Classes.FileSignature;
|
||||
using HasheousClient.Models;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class ImportGames : QueueItemStatus
|
||||
public class ImportGame : QueueItemStatus
|
||||
{
|
||||
public ImportGames(string ImportPath)
|
||||
public void ProcessDirectory(string ImportPath)
|
||||
{
|
||||
if (Directory.Exists(ImportPath))
|
||||
{
|
||||
string[] importContents_Files = Directory.GetFiles(ImportPath);
|
||||
string[] importContents_Directories = Directory.GetDirectories(ImportPath);
|
||||
string[] importContents = Directory.GetFiles(ImportPath, "*.*", SearchOption.AllDirectories);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Import Games", "Found " + importContents.Length + " files to process in import directory: " + ImportPath);
|
||||
|
||||
// import files first
|
||||
int importCount = 1;
|
||||
foreach (string importContent in importContents_Files) {
|
||||
SetStatus(importCount, importContents_Files.Length, "Importing file: " + importContent);
|
||||
foreach (string importContent in importContents) {
|
||||
SetStatus(importCount, importContents.Length, "Importing file: " + importContent);
|
||||
|
||||
ImportGame.ImportGameFile(importContent, null);
|
||||
ImportGameFile(importContent, null);
|
||||
|
||||
importCount += 1;
|
||||
}
|
||||
ClearStatus();
|
||||
|
||||
// import sub directories
|
||||
foreach (string importDir in importContents_Directories) {
|
||||
Classes.ImportGames importGames = new Classes.ImportGames(importDir);
|
||||
}
|
||||
DeleteOrphanedDirectories(ImportPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -45,12 +46,7 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class ImportGame : QueueItemStatus
|
||||
{
|
||||
public static void ImportGameFile(string GameFileImportPath, IGDB.Models.Platform? OverridePlatform)
|
||||
public void ImportGameFile(string GameFileImportPath, IGDB.Models.Platform? OverridePlatform)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
@@ -102,7 +98,8 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", " " + GameFileImportPath + " not in database - processing");
|
||||
|
||||
Models.Signatures_Games discoveredSignature = GetFileSignature(hash, fi, GameFileImportPath);
|
||||
FileSignature fileSignature = new FileSignature();
|
||||
gaseous_server.Models.Signatures_Games discoveredSignature = fileSignature.GetFileSignature(GameLibrary.GetDefaultLibrary, hash, fi, GameFileImportPath);
|
||||
|
||||
// get discovered platform
|
||||
IGDB.Models.Platform? determinedPlatform = null;
|
||||
@@ -121,7 +118,7 @@ namespace gaseous_server.Classes
|
||||
discoveredSignature.Flags.IGDBPlatformName = determinedPlatform.Name;
|
||||
}
|
||||
|
||||
IGDB.Models.Game determinedGame = SearchForGame(discoveredSignature.Game.Name, discoveredSignature.Flags.IGDBPlatformId);
|
||||
IGDB.Models.Game determinedGame = SearchForGame(discoveredSignature, discoveredSignature.Flags.IGDBPlatformId, true);
|
||||
|
||||
// add to database
|
||||
StoreROM(GameLibrary.GetDefaultLibrary, hash, determinedGame, determinedPlatform, discoveredSignature, GameFileImportPath);
|
||||
@@ -152,155 +149,29 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
|
||||
public static Models.Signatures_Games GetFileSignature(Common.hashObject hash, FileInfo fi, string GameFileImportPath)
|
||||
public static IGDB.Models.Game SearchForGame(gaseous_server.Models.Signatures_Games Signature, long PlatformId, bool FullDownload)
|
||||
{
|
||||
Models.Signatures_Games discoveredSignature = _GetFileSignature(hash, fi, GameFileImportPath);
|
||||
|
||||
if ((Path.GetExtension(GameFileImportPath) == ".zip") && (fi.Length < 1073741824))
|
||||
if (Signature.Flags != null)
|
||||
{
|
||||
// file is a zip and less than 1 GiB
|
||||
// extract the zip file and search the contents
|
||||
string ExtractPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, Path.GetRandomFileName());
|
||||
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
|
||||
if (Signature.Flags.IGDBGameId != null && Signature.Flags.IGDBGameId != 0)
|
||||
{
|
||||
// game was determined elsewhere - probably a Hasheous server
|
||||
try
|
||||
{
|
||||
ZipFile.ExtractToDirectory(GameFileImportPath, ExtractPath);
|
||||
|
||||
// loop through contents until we find the first signature match
|
||||
foreach (string file in Directory.GetFiles(ExtractPath))
|
||||
{
|
||||
FileInfo zfi = new FileInfo(file);
|
||||
Common.hashObject zhash = new Common.hashObject(file);
|
||||
|
||||
Models.Signatures_Games zDiscoveredSignature = _GetFileSignature(zhash, zfi, file);
|
||||
zDiscoveredSignature.Rom.Name = Path.ChangeExtension(zDiscoveredSignature.Rom.Name, ".zip");
|
||||
|
||||
if (zDiscoveredSignature.Score > discoveredSignature.Score)
|
||||
{
|
||||
if (
|
||||
zDiscoveredSignature.Rom.SignatureSource == gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType.MAMEArcade ||
|
||||
zDiscoveredSignature.Rom.SignatureSource == gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType.MAMEMess
|
||||
)
|
||||
{
|
||||
zDiscoveredSignature.Rom.Name = zDiscoveredSignature.Game.Description + ".zip";
|
||||
}
|
||||
zDiscoveredSignature.Rom.Crc = discoveredSignature.Rom.Crc;
|
||||
zDiscoveredSignature.Rom.Md5 = discoveredSignature.Rom.Md5;
|
||||
zDiscoveredSignature.Rom.Sha1 = discoveredSignature.Rom.Sha1;
|
||||
zDiscoveredSignature.Rom.Size = discoveredSignature.Rom.Size;
|
||||
discoveredSignature = zDiscoveredSignature;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Games.GetGame(Signature.Flags.IGDBGameId, false, false, FullDownload);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Get Signature", "Error processing zip file: " + GameFileImportPath, ex);
|
||||
Logging.Log(Logging.LogType.Warning, "Import Game", "Provided game id resulted in a failed game lookup", ex);
|
||||
}
|
||||
|
||||
if (Directory.Exists(ExtractPath)) { Directory.Delete(ExtractPath, true); }
|
||||
}
|
||||
|
||||
return discoveredSignature;
|
||||
}
|
||||
|
||||
private static Models.Signatures_Games _GetFileSignature(Common.hashObject hash, FileInfo fi, string GameFileImportPath)
|
||||
{
|
||||
// check 1: do we have a signature for it?
|
||||
gaseous_server.Controllers.SignaturesController sc = new Controllers.SignaturesController();
|
||||
List<Models.Signatures_Games> signatures = sc.GetSignature(hash.md5hash);
|
||||
if (signatures.Count == 0)
|
||||
{
|
||||
// no md5 signature found - try sha1
|
||||
signatures = sc.GetSignature("", hash.sha1hash);
|
||||
}
|
||||
|
||||
Models.Signatures_Games discoveredSignature = new Models.Signatures_Games();
|
||||
if (signatures.Count == 1)
|
||||
{
|
||||
// only 1 signature found!
|
||||
discoveredSignature = signatures.ElementAt(0);
|
||||
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, fi, false);
|
||||
}
|
||||
else if (signatures.Count > 1)
|
||||
{
|
||||
// more than one signature found - find one with highest score
|
||||
foreach (Models.Signatures_Games Sig in signatures)
|
||||
{
|
||||
if (Sig.Score > discoveredSignature.Score)
|
||||
{
|
||||
discoveredSignature = Sig;
|
||||
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, fi, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no signature match found - try name search
|
||||
signatures = sc.GetByTosecName(fi.Name);
|
||||
|
||||
if (signatures.Count == 1)
|
||||
{
|
||||
// only 1 signature found!
|
||||
discoveredSignature = signatures.ElementAt(0);
|
||||
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, fi, false);
|
||||
}
|
||||
else if (signatures.Count > 1)
|
||||
{
|
||||
// more than one signature found - find one with highest score
|
||||
foreach (Models.Signatures_Games Sig in signatures)
|
||||
{
|
||||
if (Sig.Score > discoveredSignature.Score)
|
||||
{
|
||||
discoveredSignature = Sig;
|
||||
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, fi, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// still no search - try alternate method
|
||||
Models.Signatures_Games.GameItem gi = new Models.Signatures_Games.GameItem();
|
||||
Models.Signatures_Games.RomItem ri = new Models.Signatures_Games.RomItem();
|
||||
|
||||
discoveredSignature.Game = gi;
|
||||
discoveredSignature.Rom = ri;
|
||||
|
||||
// game title is the file name without the extension or path
|
||||
gi.Name = Path.GetFileNameWithoutExtension(GameFileImportPath);
|
||||
|
||||
// remove everything after brackets - leaving (hopefully) only the name
|
||||
if (gi.Name.Contains("("))
|
||||
{
|
||||
gi.Name = gi.Name.Substring(0, gi.Name.IndexOf("("));
|
||||
}
|
||||
|
||||
// remove special characters like dashes
|
||||
gi.Name = gi.Name.Replace("-", "");
|
||||
|
||||
// guess platform
|
||||
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, fi, true);
|
||||
|
||||
// get rom data
|
||||
ri.Name = Path.GetFileName(GameFileImportPath);
|
||||
ri.Md5 = hash.md5hash;
|
||||
ri.Sha1 = hash.sha1hash;
|
||||
ri.Size = fi.Length;
|
||||
ri.SignatureSource = gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType.None;
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Import Game", " Determined import file as: " + discoveredSignature.Game.Name + " (" + discoveredSignature.Game.Year + ") " + discoveredSignature.Game.System);
|
||||
|
||||
return discoveredSignature;
|
||||
}
|
||||
|
||||
public static IGDB.Models.Game SearchForGame(string GameName, long PlatformId)
|
||||
{
|
||||
// search discovered game - case insensitive exact match first
|
||||
IGDB.Models.Game determinedGame = new IGDB.Models.Game();
|
||||
|
||||
string GameName = Signature.Game.Name;
|
||||
|
||||
List<string> SearchCandidates = GetSearchCandidates(GameName);
|
||||
|
||||
foreach (string SearchCandidate in SearchCandidates)
|
||||
@@ -423,7 +294,7 @@ namespace gaseous_server.Classes
|
||||
return SearchCandidates;
|
||||
}
|
||||
|
||||
public static long StoreROM(GameLibrary.LibraryItem library, Common.hashObject hash, IGDB.Models.Game determinedGame, IGDB.Models.Platform determinedPlatform, Models.Signatures_Games discoveredSignature, string GameFileImportPath, long UpdateId = 0)
|
||||
public static long StoreROM(GameLibrary.LibraryItem library, Common.hashObject hash, IGDB.Models.Game determinedGame, IGDB.Models.Platform determinedPlatform, gaseous_server.Models.Signatures_Games discoveredSignature, string GameFileImportPath, long UpdateId = 0)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
@@ -566,7 +437,7 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
|
||||
public static void OrganiseLibrary()
|
||||
public void OrganiseLibrary()
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Organise Library", "Starting default library organisation");
|
||||
|
||||
@@ -600,19 +471,98 @@ namespace gaseous_server.Classes
|
||||
foreach (var directory in Directory.GetDirectories(startLocation))
|
||||
{
|
||||
DeleteOrphanedDirectories(directory);
|
||||
if (Directory.GetFiles(directory).Length == 0 &&
|
||||
Directory.GetDirectories(directory).Length == 0)
|
||||
|
||||
string[] files = Directory.GetFiles(directory);
|
||||
string[] directories = Directory.GetDirectories(directory);
|
||||
|
||||
if (files.Length == 0 &&
|
||||
directories.Length == 0)
|
||||
{
|
||||
Directory.Delete(directory, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LibraryScan()
|
||||
public void LibraryScan(GameLibrary.LibraryItem? singleLibrary = null)
|
||||
{
|
||||
foreach (GameLibrary.LibraryItem library in GameLibrary.GetLibraries)
|
||||
int maxWorkers = Config.MetadataConfiguration.MaxLibraryScanWorkers;
|
||||
|
||||
List<GameLibrary.LibraryItem> libraries = new List<GameLibrary.LibraryItem>();
|
||||
if (singleLibrary == null)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Starting library scan. Library " + library.Name);
|
||||
libraries.AddRange(GameLibrary.GetLibraries);
|
||||
}
|
||||
else
|
||||
{
|
||||
libraries.Add(singleLibrary);
|
||||
}
|
||||
|
||||
// setup background tasks for each library
|
||||
foreach (GameLibrary.LibraryItem library in libraries)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Starting worker process for library " + library.Name);
|
||||
ProcessQueue.QueueItem queue = new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.LibraryScanWorker,
|
||||
1,
|
||||
new List<ProcessQueue.QueueItemType>
|
||||
{
|
||||
ProcessQueue.QueueItemType.OrganiseLibrary,
|
||||
ProcessQueue.QueueItemType.Rematcher
|
||||
},
|
||||
false,
|
||||
true);
|
||||
queue.Options = library;
|
||||
queue.ForceExecute();
|
||||
|
||||
ProcessQueue.QueueItems.Add(queue);
|
||||
|
||||
// check number of running tasks is less than maxWorkers
|
||||
bool allowContinue;
|
||||
do
|
||||
{
|
||||
allowContinue = true;
|
||||
int currentWorkerCount = 0;
|
||||
List<ProcessQueue.QueueItem> queueItems = new List<ProcessQueue.QueueItem>();
|
||||
queueItems.AddRange(ProcessQueue.QueueItems);
|
||||
foreach (ProcessQueue.QueueItem item in queueItems)
|
||||
{
|
||||
if (item.ItemType == ProcessQueue.QueueItemType.LibraryScanWorker)
|
||||
{
|
||||
currentWorkerCount += 1;
|
||||
}
|
||||
}
|
||||
if (currentWorkerCount >= maxWorkers)
|
||||
{
|
||||
allowContinue = false;
|
||||
Thread.Sleep(60000);
|
||||
}
|
||||
} while (allowContinue == false);
|
||||
}
|
||||
|
||||
bool WorkersStillWorking;
|
||||
do
|
||||
{
|
||||
WorkersStillWorking = false;
|
||||
List<ProcessQueue.QueueItem> queueItems = new List<ProcessQueue.QueueItem>();
|
||||
queueItems.AddRange(ProcessQueue.QueueItems);
|
||||
foreach (ProcessQueue.QueueItem item in queueItems)
|
||||
{
|
||||
if (item.ItemType == ProcessQueue.QueueItemType.LibraryScanWorker)
|
||||
{
|
||||
// workers are still running - sleep and keep looping
|
||||
WorkersStillWorking = true;
|
||||
Thread.Sleep(30000);
|
||||
}
|
||||
}
|
||||
} while (WorkersStillWorking == true);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Library scan complete. All workers stopped");
|
||||
}
|
||||
|
||||
public void LibrarySpecificScan(GameLibrary.LibraryItem library)
|
||||
{
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Starting scan of library: " + library.Name);
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
@@ -637,7 +587,7 @@ namespace gaseous_server.Classes
|
||||
|
||||
if (!romPath.StartsWith(library.Path))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Deleting database entry for files with incorrect directory " + romPath);
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Deleting database entry for files with incorrect directory " + romPath);
|
||||
string deleteSql = "DELETE FROM Games_Roms WHERE Id=@id AND LibraryId=@libraryid";
|
||||
Dictionary<string, object> deleteDict = new Dictionary<string, object>();
|
||||
deleteDict.Add("Id", romId);
|
||||
@@ -647,7 +597,7 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
|
||||
sql = "SELECT * FROM Games_Roms ORDER BY `name`";
|
||||
sql = "SELECT * FROM Games_Roms WHERE LibraryId=@libraryid ORDER BY `name`";
|
||||
dtRoms = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
// search for files in the library that aren't in the database
|
||||
@@ -679,42 +629,39 @@ namespace gaseous_server.Classes
|
||||
if (romFound == false)
|
||||
{
|
||||
// file is not in database - process it
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Orphaned file found in library: " + LibraryFile);
|
||||
|
||||
Common.hashObject hash = new Common.hashObject(LibraryFile);
|
||||
FileInfo fi = new FileInfo(LibraryFile);
|
||||
|
||||
Models.Signatures_Games sig = GetFileSignature(hash, fi, LibraryFile);
|
||||
FileSignature fileSignature = new FileSignature();
|
||||
gaseous_server.Models.Signatures_Games sig = fileSignature.GetFileSignature(library, hash, fi, LibraryFile);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Orphaned file found in library: " + LibraryFile);
|
||||
|
||||
// get discovered platform
|
||||
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
|
||||
|
||||
IGDB.Models.Game determinedGame = new Game();
|
||||
try
|
||||
{
|
||||
if (determinedPlatform == null)
|
||||
// get discovered platform
|
||||
long PlatformId;
|
||||
IGDB.Models.Platform determinedPlatform;
|
||||
|
||||
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0 )
|
||||
{
|
||||
if (library.DefaultPlatformId == 0)
|
||||
{
|
||||
determinedPlatform = new IGDB.Models.Platform();
|
||||
determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
|
||||
// no platform discovered in the signature
|
||||
PlatformId = library.DefaultPlatformId;
|
||||
}
|
||||
else
|
||||
{
|
||||
determinedPlatform = Platforms.GetPlatform(library.DefaultPlatformId);
|
||||
determinedGame = SearchForGame(sig.Game.Name, library.DefaultPlatformId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
determinedGame = SearchForGame(sig.Game.Name, (long)determinedPlatform.Id);
|
||||
// use the platform discovered in the signature
|
||||
PlatformId = sig.Flags.IGDBPlatformId;
|
||||
}
|
||||
determinedPlatform = Platforms.GetPlatform(PlatformId);
|
||||
|
||||
IGDB.Models.Game determinedGame = SearchForGame(sig, PlatformId, true);
|
||||
|
||||
StoreROM(library, hash, determinedGame, determinedPlatform, sig, LibraryFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Library Scan", " An error occurred while matching orphaned file: " + LibraryFile + ". Skipping.", ex);
|
||||
Logging.Log(Logging.LogType.Warning, "Library Scan", "An error occurred while matching orphaned file: " + LibraryFile + ". Skipping.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -734,10 +681,10 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
long romId = (long)dtRoms.Rows[i]["Id"];
|
||||
string romPath = (string)dtRoms.Rows[i]["Path"];
|
||||
gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType romMetadataSource = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(int)dtRoms.Rows[i]["MetadataSource"];
|
||||
gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType romMetadataSource = (gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType)(int)dtRoms.Rows[i]["MetadataSource"];
|
||||
|
||||
SetStatus(StatusCount, dtRoms.Rows.Count, "Processing file " + romPath);
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Processing ROM at path " + romPath);
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Processing ROM at path " + romPath);
|
||||
|
||||
if (File.Exists(romPath))
|
||||
{
|
||||
@@ -745,14 +692,19 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
if (romPath != ComputeROMPath(romId))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "ROM at path " + romPath + " found, but needs to be moved");
|
||||
MoveGameFile(romId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "ROM at path " + romPath + " found");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// file doesn't exist where it's supposed to be! delete it from the db
|
||||
Logging.Log(Logging.LogType.Warning, "Library Scan", " Deleting orphaned database entry for " + romPath);
|
||||
Logging.Log(Logging.LogType.Warning, "Library Scan", "Deleting orphaned database entry for " + romPath);
|
||||
|
||||
string deleteSql = "DELETE FROM Games_Roms WHERE Id = @id AND LibraryId = @libraryid";
|
||||
Dictionary<string, object> deleteDict = new Dictionary<string, object>();
|
||||
@@ -767,7 +719,6 @@ namespace gaseous_server.Classes
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Library scan completed");
|
||||
}
|
||||
}
|
||||
|
||||
public void Rematcher(bool ForceExecute = false)
|
||||
{
|
||||
@@ -775,26 +726,29 @@ namespace gaseous_server.Classes
|
||||
Logging.Log(Logging.LogType.Information, "Rematch Scan", "Rematch scan starting");
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
foreach (GameLibrary.LibraryItem library in GameLibrary.GetLibraries)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Rematch Scan", "Rematch on library " + library.Name);
|
||||
|
||||
string sql = "";
|
||||
if (ForceExecute == false)
|
||||
{
|
||||
sql = "SELECT * FROM Games_Roms WHERE ((PlatformId = 0 OR GameId = 0) AND MetadataSource = 0) AND (LastMatchAttemptDate IS NULL OR LastMatchAttemptDate < @lastmatchattemptdate) LIMIT 100;";
|
||||
sql = "SELECT * FROM Games_Roms WHERE (PlatformId = 0 AND GameId <> 0) OR (((PlatformId = 0 OR GameId = 0) AND MetadataSource = 0) OR (PlatformId = 0 AND GameId = 0)) AND (LastMatchAttemptDate IS NULL OR LastMatchAttemptDate < @lastmatchattemptdate) AND LibraryId = @libraryid LIMIT 100;";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql = "SELECT * FROM Games_Roms WHERE ((PlatformId = 0 OR GameId = 0) AND MetadataSource = 0);";
|
||||
sql = "SELECT * FROM Games_Roms WHERE (PlatformId = 0 AND GameId <> 0) OR (((PlatformId = 0 OR GameId = 0) AND MetadataSource = 0) OR (PlatformId = 0 AND GameId = 0)) AND LibraryId = @libraryid;";
|
||||
}
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("lastmatchattemptdate", DateTime.UtcNow.AddDays(-7));
|
||||
dbDict.Add("libraryid", library.Id);
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
int StatusCount = -0;
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
SetStatus(StatusCount, data.Rows.Count, "Running rematcher");
|
||||
|
||||
// get library
|
||||
GameLibrary.LibraryItem library = GameLibrary.GetLibrary((int)row["LibraryId"]);
|
||||
|
||||
// get rom info
|
||||
long romId = (long)row["Id"];
|
||||
string romPath = (string)row["Path"];
|
||||
@@ -808,16 +762,26 @@ namespace gaseous_server.Classes
|
||||
Logging.Log(Logging.LogType.Information, "Rematch Scan", "Running rematch against " + romPath);
|
||||
|
||||
// determine rom signature
|
||||
Models.Signatures_Games sig = GetFileSignature(hash, fi, romPath);
|
||||
FileSignature fileSignature = new FileSignature();
|
||||
gaseous_server.Models.Signatures_Games sig = fileSignature.GetFileSignature(library, hash, fi, romPath);
|
||||
|
||||
// determine rom platform
|
||||
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
|
||||
if (determinedPlatform == null)
|
||||
// get discovered platform
|
||||
long PlatformId;
|
||||
IGDB.Models.Platform determinedPlatform;
|
||||
|
||||
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0 )
|
||||
{
|
||||
determinedPlatform = new IGDB.Models.Platform();
|
||||
// no platform discovered in the signature
|
||||
PlatformId = library.DefaultPlatformId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// use the platform discovered in the signature
|
||||
PlatformId = sig.Flags.IGDBPlatformId;
|
||||
}
|
||||
determinedPlatform = Platforms.GetPlatform(PlatformId);
|
||||
|
||||
IGDB.Models.Game determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
|
||||
IGDB.Models.Game determinedGame = SearchForGame(sig, PlatformId, true);
|
||||
|
||||
StoreROM(library, hash, determinedGame, determinedPlatform, sig, romPath, romId);
|
||||
|
||||
@@ -835,5 +799,6 @@ namespace gaseous_server.Classes
|
||||
ClearStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -127,9 +127,8 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRententionDate; INSERT INTO ServerLogs (EventTime, EventType, Process, Message, Exception, CorrelationId, CallingProcess, CallingUser) VALUES (@EventTime, @EventType, @Process, @Message, @Exception, @correlationid, @callingprocess, @callinguser);";
|
||||
string sql = "INSERT INTO ServerLogs (EventTime, EventType, Process, Message, Exception, CorrelationId, CallingProcess, CallingUser) VALUES (@EventTime, @EventType, @Process, @Message, @Exception, @correlationid, @callingprocess, @callinguser);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("EventRententionDate", DateTime.UtcNow.AddDays(Config.LoggingConfiguration.LogRetention * -1));
|
||||
dbDict.Add("EventTime", logItem.EventTime);
|
||||
dbDict.Add("EventType", logItem.EventType);
|
||||
dbDict.Add("Process", logItem.Process);
|
||||
|
@@ -11,6 +11,32 @@ namespace gaseous_server.Classes
|
||||
|
||||
public void RunMaintenance()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
|
||||
// remove any entries from the library that have an invalid id
|
||||
string LibraryWhereClause = "";
|
||||
foreach (GameLibrary.LibraryItem library in GameLibrary.GetLibraries)
|
||||
{
|
||||
if (LibraryWhereClause.Length > 0)
|
||||
{
|
||||
LibraryWhereClause += ", ";
|
||||
}
|
||||
LibraryWhereClause += library.Id;
|
||||
}
|
||||
string sqlLibraryWhereClause = "";
|
||||
if (LibraryWhereClause.Length > 0)
|
||||
{
|
||||
sqlLibraryWhereClause = "DELETE FROM Games_Roms WHERE LibraryId NOT IN ( " + LibraryWhereClause + " );";
|
||||
db.ExecuteCMD(sqlLibraryWhereClause);
|
||||
}
|
||||
|
||||
// delete old logs
|
||||
sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRententionDate;";
|
||||
dbDict.Add("EventRententionDate", DateTime.UtcNow.AddDays(Config.LoggingConfiguration.LogRetention * -1));
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
// delete files and directories older than 7 days in PathsToClean
|
||||
List<string> PathsToClean = new List<string>();
|
||||
PathsToClean.Add(Config.LibraryConfiguration.LibraryUploadDirectory);
|
||||
@@ -45,8 +71,7 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Maintenance", "Optimising database tables");
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SHOW TABLES;";
|
||||
sql = "SHOW FULL TABLES WHERE Table_Type = 'BASE TABLE';";
|
||||
DataTable tables = db.ExecuteCMD(sql);
|
||||
|
||||
int StatusCounter = 1;
|
||||
|
@@ -13,7 +13,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
public static Artwork? GetArtwork(long? Id, string LogoPath)
|
||||
public static Artwork? GetArtwork(long? Id, string ImagePath, bool GetImages)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
@@ -21,18 +21,18 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<Artwork> RetVal = _GetArtwork(SearchUsing.id, Id, LogoPath);
|
||||
Task<Artwork> RetVal = _GetArtwork(SearchUsing.id, Id, ImagePath, GetImages);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static Artwork GetArtwork(string Slug, string LogoPath)
|
||||
public static Artwork GetArtwork(string Slug, string ImagePath, bool GetImages)
|
||||
{
|
||||
Task<Artwork> RetVal = _GetArtwork(SearchUsing.slug, Slug, LogoPath);
|
||||
Task<Artwork> RetVal = _GetArtwork(SearchUsing.slug, Slug, ImagePath, GetImages);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<Artwork> _GetArtwork(SearchUsing searchUsing, object searchValue, string LogoPath)
|
||||
private static async Task<Artwork> _GetArtwork(SearchUsing searchUsing, object searchValue, string ImagePath, bool GetImages = true)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
@@ -61,19 +61,20 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
Artwork returnValue = new Artwork();
|
||||
bool forceImageDownload = false;
|
||||
LogoPath = Path.Combine(LogoPath, "Artwork");
|
||||
ImagePath = Path.Combine(ImagePath, "Artwork");
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Expired:
|
||||
try
|
||||
{
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
forceImageDownload = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -88,11 +89,17 @@ namespace gaseous_server.Classes.Metadata
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
if ((!File.Exists(Path.Combine(LogoPath, returnValue.ImageId + ".jpg"))) || forceImageDownload == true)
|
||||
// check for presence of "original" quality file - download if absent or force download is true
|
||||
string localFile = Path.Combine(ImagePath, Communications.IGDBAPI_ImageSize.original.ToString(), returnValue.ImageId + ".jpg");
|
||||
if (GetImages == true)
|
||||
{
|
||||
//GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_thumb, returnValue.ImageId);
|
||||
//GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_logo_med, returnValue.ImageId);
|
||||
GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_original, returnValue.ImageId);
|
||||
if ((!File.Exists(localFile)) || forceImageDownload == true)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Metadata: " + returnValue.GetType().Name, "Artwork download forced.");
|
||||
|
||||
Communications comms = new Communications();
|
||||
comms.GetSpecificImageFromServer(ImagePath, returnValue.ImageId, Communications.IGDBAPI_ImageSize.original, null);
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
@@ -104,65 +111,15 @@ namespace gaseous_server.Classes.Metadata
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<Artwork> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
private static async Task<Artwork> GetObjectFromServer(string WhereClause, string ImagePath)
|
||||
{
|
||||
// get Artwork metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Artwork>(IGDBClient.Endpoints.Artworks, fieldList, WhereClause);
|
||||
var result = results.First();
|
||||
|
||||
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb, result.ImageId);
|
||||
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_logo_med, result.ImageId);
|
||||
GetImageFromServer(result.Url, LogoPath, LogoSize.t_original, result.ImageId);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void GetImageFromServer(string Url, string LogoPath, LogoSize logoSize, string ImageId)
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
string fileName = "Artwork.jpg";
|
||||
string extension = "jpg";
|
||||
switch (logoSize)
|
||||
{
|
||||
case LogoSize.t_thumb:
|
||||
fileName = "_Thumb";
|
||||
extension = "jpg";
|
||||
break;
|
||||
case LogoSize.t_logo_med:
|
||||
fileName = "_Medium";
|
||||
extension = "png";
|
||||
break;
|
||||
case LogoSize.t_original:
|
||||
fileName = "";
|
||||
extension = "png";
|
||||
break;
|
||||
default:
|
||||
fileName = "Artwork";
|
||||
extension = "jpg";
|
||||
break;
|
||||
}
|
||||
fileName = ImageId + fileName;
|
||||
string imageUrl = Url.Replace(LogoSize.t_thumb.ToString(), logoSize.ToString()).Replace("jpg", extension);
|
||||
|
||||
using (var s = client.GetStreamAsync("https:" + imageUrl))
|
||||
{
|
||||
if (!Directory.Exists(LogoPath)) { Directory.CreateDirectory(LogoPath); }
|
||||
using (var fs = new FileStream(Path.Combine(LogoPath, fileName + "." + extension), FileMode.OpenOrCreate))
|
||||
{
|
||||
s.Result.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum LogoSize
|
||||
{
|
||||
t_thumb,
|
||||
t_logo_med,
|
||||
t_original
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,10 @@
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Net;
|
||||
using Humanizer;
|
||||
using IGDB;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using RestEase;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
@@ -9,16 +14,28 @@ namespace gaseous_server.Classes.Metadata
|
||||
/// </summary>
|
||||
public class Communications
|
||||
{
|
||||
static Communications()
|
||||
{
|
||||
var handler = new HttpClientHandler();
|
||||
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
client = new HttpClient(handler);
|
||||
|
||||
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
|
||||
client.DefaultRequestHeaders.Add("Accept-Encoding", "deflate");
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
private static HttpClient client = new HttpClient();
|
||||
|
||||
/// <summary>
|
||||
/// Configure metadata API communications
|
||||
/// </summary>
|
||||
public static MetadataSources MetadataSource
|
||||
public static HasheousClient.Models.MetadataModel.MetadataSources MetadataSource
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -30,7 +47,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case MetadataSources.IGDB:
|
||||
case HasheousClient.Models.MetadataModel.MetadataSources.IGDB:
|
||||
// set rate limiter avoidance values
|
||||
RateLimitAvoidanceWait = 1500;
|
||||
RateLimitAvoidanceThreshold = 3;
|
||||
@@ -46,7 +63,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
}
|
||||
private static MetadataSources _MetadataSource = MetadataSources.None;
|
||||
private static HasheousClient.Models.MetadataModel.MetadataSources _MetadataSource = HasheousClient.Models.MetadataModel.MetadataSources.None;
|
||||
|
||||
// rate limit avoidance - what can we do to ensure that rate limiting is avoided?
|
||||
// these values affect all communications
|
||||
@@ -142,22 +159,6 @@ namespace gaseous_server.Classes.Metadata
|
||||
private int RetryAttempts = 0;
|
||||
private int RetryAttemptsMax = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Supported metadata sources
|
||||
/// </summary>
|
||||
public enum MetadataSources
|
||||
{
|
||||
/// <summary>
|
||||
/// None - always returns null for metadata requests - should not really be using this source
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// IGDB - queries the IGDB service for metadata
|
||||
/// </summary>
|
||||
IGDB
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request data from the metadata API
|
||||
/// </summary>
|
||||
@@ -170,9 +171,9 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
switch (_MetadataSource)
|
||||
{
|
||||
case MetadataSources.None:
|
||||
case HasheousClient.Models.MetadataModel.MetadataSources.None:
|
||||
return null;
|
||||
case MetadataSources.IGDB:
|
||||
case HasheousClient.Models.MetadataModel.MetadataSources.IGDB:
|
||||
return await IGDBAPI<T>(Endpoint, Fields, Query);
|
||||
default:
|
||||
return null;
|
||||
@@ -234,5 +235,343 @@ namespace gaseous_server.Classes.Metadata
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download from the specified uri
|
||||
/// </summary>
|
||||
/// <param name="uri">The uri to download from</param>
|
||||
/// <param name="DestinationFile">The file name and path the download should be stored as</param>
|
||||
public Task<bool?> DownloadFile(Uri uri, string DestinationFile)
|
||||
{
|
||||
var result = _DownloadFile(uri, DestinationFile);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<bool?> _DownloadFile(Uri uri, string DestinationFile)
|
||||
{
|
||||
string DestinationDirectory = new FileInfo(DestinationFile).Directory.FullName;
|
||||
if (!Directory.Exists(DestinationDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(DestinationDirectory);
|
||||
}
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Communications", "Downloading from " + uri.ToString() + " to " + DestinationFile);
|
||||
|
||||
try
|
||||
{
|
||||
using (HttpResponseMessage response = client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).Result)
|
||||
{
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
using (Stream contentStream = await response.Content.ReadAsStreamAsync(), fileStream = new FileStream(DestinationFile, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
|
||||
{
|
||||
var totalRead = 0L;
|
||||
var totalReads = 0L;
|
||||
var buffer = new byte[8192];
|
||||
var isMoreToRead = true;
|
||||
|
||||
do
|
||||
{
|
||||
var read = await contentStream.ReadAsync(buffer, 0, buffer.Length);
|
||||
if (read == 0)
|
||||
{
|
||||
isMoreToRead = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
await fileStream.WriteAsync(buffer, 0, read);
|
||||
|
||||
totalRead += read;
|
||||
totalReads += 1;
|
||||
|
||||
if (totalReads % 2000 == 0)
|
||||
{
|
||||
Console.WriteLine(string.Format("total bytes downloaded so far: {0:n0}", totalRead));
|
||||
}
|
||||
}
|
||||
}
|
||||
while (isMoreToRead);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
if (ex.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
if (File.Exists(DestinationFile))
|
||||
{
|
||||
FileInfo fi = new FileInfo(DestinationFile);
|
||||
if (fi.Length == 0)
|
||||
{
|
||||
File.Delete(DestinationFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Log(Logging.LogType.Warning, "Download Images", "Error downloading file: ", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<string> GetSpecificImageFromServer(string ImagePath, string ImageId, IGDBAPI_ImageSize size, List<IGDBAPI_ImageSize>? FallbackSizes = null)
|
||||
{
|
||||
string returnPath = "";
|
||||
|
||||
// check for artificial sizes first
|
||||
switch (size)
|
||||
{
|
||||
case IGDBAPI_ImageSize.screenshot_small:
|
||||
case IGDBAPI_ImageSize.screenshot_thumb:
|
||||
string BasePath = Path.Combine(ImagePath, size.ToString());
|
||||
if (!Directory.Exists(BasePath))
|
||||
{
|
||||
Directory.CreateDirectory(BasePath);
|
||||
}
|
||||
returnPath = Path.Combine(BasePath, ImageId + ".jpg");
|
||||
if (!File.Exists(returnPath))
|
||||
{
|
||||
// get original size image and resize
|
||||
string originalSizePath = await GetSpecificImageFromServer(ImagePath, ImageId, IGDBAPI_ImageSize.original, null);
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case IGDBAPI_ImageSize.screenshot_small:
|
||||
// 235x128
|
||||
width = 235;
|
||||
height = 128;
|
||||
break;
|
||||
|
||||
case IGDBAPI_ImageSize.screenshot_thumb:
|
||||
// 165x90
|
||||
width = 165;
|
||||
height = 90;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
using (var image = new ImageMagick.MagickImage(originalSizePath))
|
||||
{
|
||||
image.Resize(width, height);
|
||||
image.Strip();
|
||||
image.Write(returnPath);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// these sizes are IGDB native
|
||||
if (RateLimitResumeTime > DateTime.UtcNow)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "API Connection", "IGDB rate limit hit. Pausing API communications until " + RateLimitResumeTime.ToString() + ". Attempt " + RetryAttempts + " of " + RetryAttemptsMax + " retries.");
|
||||
Thread.Sleep(RateLimitRecoveryWaitTime);
|
||||
}
|
||||
|
||||
if (InRateLimitAvoidanceMode == true)
|
||||
{
|
||||
// sleep for a moment to help avoid hitting the rate limiter
|
||||
Thread.Sleep(RateLimitAvoidanceWait);
|
||||
}
|
||||
|
||||
Communications comms = new Communications();
|
||||
List<IGDBAPI_ImageSize> imageSizes = new List<IGDBAPI_ImageSize>
|
||||
{
|
||||
size
|
||||
};
|
||||
|
||||
// get the image
|
||||
try
|
||||
{
|
||||
returnPath = Path.Combine(ImagePath, size.ToString(), ImageId + ".jpg");
|
||||
|
||||
// fail early if the file is already downloaded
|
||||
if (!File.Exists(returnPath))
|
||||
{
|
||||
await comms.IGDBAPI_GetImage(imageSizes, ImageId, ImagePath);
|
||||
}
|
||||
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
if (ex.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Image Download", "Image not found, trying a different size.");
|
||||
|
||||
if (FallbackSizes != null)
|
||||
{
|
||||
foreach (Communications.IGDBAPI_ImageSize imageSize in FallbackSizes)
|
||||
{
|
||||
returnPath = await GetSpecificImageFromServer(ImagePath, ImageId, imageSize, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// increment rate limiter avoidance call count
|
||||
RateLimitAvoidanceCallCount += 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return returnPath;
|
||||
}
|
||||
|
||||
public static T? GetSearchCache<T>(string SearchFields, string SearchString)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM SearchCache WHERE SearchFields = @searchfields AND SearchString = @searchstring;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||
{
|
||||
{ "searchfields", SearchFields },
|
||||
{ "searchstring", SearchString }
|
||||
};
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
if (data.Rows.Count > 0)
|
||||
{
|
||||
// cache hit
|
||||
string rawString = data.Rows[0]["Content"].ToString();
|
||||
T ReturnValue = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(rawString);
|
||||
if (ReturnValue != null)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Search Cache", "Found search result in cache. Search string: " + SearchString);
|
||||
return ReturnValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Search Cache", "Search result not found in cache.");
|
||||
return default;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// cache miss
|
||||
Logging.Log(Logging.LogType.Information, "Search Cache", "Search result not found in cache.");
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetSearchCache<T>(string SearchFields, string SearchString, T SearchResult)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Search Cache", "Storing search results in cache. Search string: " + SearchString);
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "INSERT INTO SearchCache (SearchFields, SearchString, Content, LastSearch) VALUES (@searchfields, @searchstring, @content, @lastsearch);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||
{
|
||||
{ "searchfields", SearchFields },
|
||||
{ "searchstring", SearchString },
|
||||
{ "content", Newtonsoft.Json.JsonConvert.SerializeObject(SearchResult) },
|
||||
{ "lastsearch", DateTime.UtcNow }
|
||||
};
|
||||
db.ExecuteNonQuery(sql, dbDict);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See https://api-docs.igdb.com/?javascript#images for more information about the image url structure
|
||||
/// </summary>
|
||||
/// <param name="ImageId"></param>
|
||||
/// <param name="outputPath">The path to save the downloaded files to
|
||||
public async Task IGDBAPI_GetImage(List<IGDBAPI_ImageSize> ImageSizes, string ImageId, string OutputPath)
|
||||
{
|
||||
string urlTemplate = "https://images.igdb.com/igdb/image/upload/t_{size}/{hash}.jpg";
|
||||
|
||||
foreach (IGDBAPI_ImageSize ImageSize in ImageSizes)
|
||||
{
|
||||
string url = urlTemplate.Replace("{size}", Common.GetDescription(ImageSize)).Replace("{hash}", ImageId);
|
||||
string newOutputPath = Path.Combine(OutputPath, Common.GetDescription(ImageSize));
|
||||
string OutputFile = ImageId + ".jpg";
|
||||
string fullPath = Path.Combine(newOutputPath, OutputFile);
|
||||
|
||||
await _DownloadFile(new Uri(url), fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
public enum IGDBAPI_ImageSize
|
||||
{
|
||||
/// <summary>
|
||||
/// 90x128 Fit
|
||||
/// </summary>
|
||||
[Description("cover_small")]
|
||||
cover_small,
|
||||
|
||||
/// <summary>
|
||||
/// 264x374 Fit
|
||||
/// </summary>
|
||||
[Description("cover_big")]
|
||||
cover_big,
|
||||
|
||||
/// <summary>
|
||||
/// 165x90 Lfill, Centre gravity - resized by Gaseous and is not a real IGDB size
|
||||
/// </summary>
|
||||
[Description("screenshot_thumb")]
|
||||
screenshot_thumb,
|
||||
|
||||
/// <summary>
|
||||
/// 235x128 Lfill, Centre gravity - resized by Gaseous and is not a real IGDB size
|
||||
/// </summary>
|
||||
[Description("screenshot_small")]
|
||||
screenshot_small,
|
||||
|
||||
/// <summary>
|
||||
/// 589x320 Lfill, Centre gravity
|
||||
/// </summary>
|
||||
[Description("screenshot_med")]
|
||||
screenshot_med,
|
||||
|
||||
/// <summary>
|
||||
/// 889x500 Lfill, Centre gravity
|
||||
/// </summary>
|
||||
[Description("screenshot_big")]
|
||||
screenshot_big,
|
||||
|
||||
/// <summary>
|
||||
/// 1280x720 Lfill, Centre gravity
|
||||
/// </summary>
|
||||
[Description("screenshot_huge")]
|
||||
screenshot_huge,
|
||||
|
||||
/// <summary>
|
||||
/// 284x160 Fit
|
||||
/// </summary>
|
||||
[Description("logo_med")]
|
||||
logo_med,
|
||||
|
||||
/// <summary>
|
||||
/// 90x90 Thumb, Centre gravity
|
||||
/// </summary>
|
||||
[Description("thumb")]
|
||||
thumb,
|
||||
|
||||
/// <summary>
|
||||
/// 35x35 Thumb, Centre gravity
|
||||
/// </summary>
|
||||
[Description("micro")]
|
||||
micro,
|
||||
|
||||
/// <summary>
|
||||
/// 1280x720 Fit, Centre gravity
|
||||
/// </summary>
|
||||
[Description("720p")]
|
||||
r720p,
|
||||
|
||||
/// <summary>
|
||||
/// 1920x1080 Fit, Centre gravity
|
||||
/// </summary>
|
||||
[Description("1080p")]
|
||||
r1080p,
|
||||
|
||||
/// <summary>
|
||||
/// The originally uploaded image
|
||||
/// </summary>
|
||||
[Description("original")]
|
||||
original
|
||||
}
|
||||
}
|
||||
}
|
@@ -13,7 +13,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
public static CompanyLogo? GetCompanyLogo(long? Id, string LogoPath)
|
||||
public static CompanyLogo? GetCompanyLogo(long? Id, string ImagePath)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
@@ -21,18 +21,18 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<CompanyLogo> RetVal = _GetCompanyLogo(SearchUsing.id, Id, LogoPath);
|
||||
Task<CompanyLogo> RetVal = _GetCompanyLogo(SearchUsing.id, Id, ImagePath);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static CompanyLogo GetCompanyLogo(string Slug, string LogoPath)
|
||||
public static CompanyLogo GetCompanyLogo(string Slug, string ImagePath)
|
||||
{
|
||||
Task<CompanyLogo> RetVal = _GetCompanyLogo(SearchUsing.slug, Slug, LogoPath);
|
||||
Task<CompanyLogo> RetVal = _GetCompanyLogo(SearchUsing.slug, Slug, ImagePath);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<CompanyLogo> _GetCompanyLogo(SearchUsing searchUsing, object searchValue, string LogoPath)
|
||||
private static async Task<CompanyLogo> _GetCompanyLogo(SearchUsing searchUsing, object searchValue, string ImagePath)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
@@ -64,7 +64,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
if (returnValue != null)
|
||||
{
|
||||
Storage.NewCacheValue(returnValue);
|
||||
@@ -74,7 +74,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
case Storage.CacheStatus.Expired:
|
||||
try
|
||||
{
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
forceImageDownload = true;
|
||||
}
|
||||
@@ -91,13 +91,14 @@ namespace gaseous_server.Classes.Metadata
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
if (returnValue != null)
|
||||
// check for presence of "original" quality file - download if absent or force download is true
|
||||
string localFile = Path.Combine(ImagePath, Communications.IGDBAPI_ImageSize.original.ToString(), returnValue.ImageId + ".jpg");
|
||||
if ((!File.Exists(localFile)) || forceImageDownload == true)
|
||||
{
|
||||
if ((!File.Exists(Path.Combine(LogoPath, "Logo.jpg"))) || forceImageDownload == true)
|
||||
{
|
||||
GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_thumb);
|
||||
GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_logo_med);
|
||||
}
|
||||
Logging.Log(Logging.LogType.Information, "Metadata: " + returnValue.GetType().Name, "Company logo download forced.");
|
||||
|
||||
Communications comms = new Communications();
|
||||
comms.GetSpecificImageFromServer(ImagePath, returnValue.ImageId, Communications.IGDBAPI_ImageSize.original, null);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
@@ -109,65 +110,15 @@ namespace gaseous_server.Classes.Metadata
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<CompanyLogo?> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
private static async Task<CompanyLogo> GetObjectFromServer(string WhereClause, string ImagePath)
|
||||
{
|
||||
// get CompanyLogo metadata
|
||||
// get Artwork metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<CompanyLogo>(IGDBClient.Endpoints.CompanyLogos, fieldList, WhereClause);
|
||||
if (results.Length > 0)
|
||||
{
|
||||
var result = results.First();
|
||||
|
||||
GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb);
|
||||
GetImageFromServer(result.Url, LogoPath, LogoSize.t_logo_med);
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetImageFromServer(string Url, string LogoPath, LogoSize logoSize)
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
string fileName = "Logo.jpg";
|
||||
string extension = "jpg";
|
||||
switch (logoSize)
|
||||
{
|
||||
case LogoSize.t_thumb:
|
||||
fileName = "Logo_Thumb";
|
||||
extension = "jpg";
|
||||
break;
|
||||
case LogoSize.t_logo_med:
|
||||
fileName = "Logo_Medium";
|
||||
extension = "png";
|
||||
break;
|
||||
default:
|
||||
fileName = "Logo";
|
||||
extension = "jpg";
|
||||
break;
|
||||
}
|
||||
string imageUrl = Url.Replace(LogoSize.t_thumb.ToString(), logoSize.ToString()).Replace("jpg", extension);
|
||||
|
||||
using (var s = client.GetStreamAsync("https:" + imageUrl))
|
||||
{
|
||||
if (!Directory.Exists(LogoPath)) { Directory.CreateDirectory(LogoPath); }
|
||||
using (var fs = new FileStream(Path.Combine(LogoPath, fileName + "." + extension), FileMode.OpenOrCreate))
|
||||
{
|
||||
s.Result.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum LogoSize
|
||||
{
|
||||
t_thumb,
|
||||
t_logo_med
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using Microsoft.CodeAnalysis.Elfie.Model.Strings;
|
||||
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
@@ -13,7 +15,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
public static Cover? GetCover(long? Id, string LogoPath)
|
||||
public static Cover? GetCover(long? Id, string ImagePath, bool GetImages)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
@@ -21,18 +23,18 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<Cover> RetVal = _GetCover(SearchUsing.id, Id, LogoPath);
|
||||
Task<Cover> RetVal = _GetCover(SearchUsing.id, Id, ImagePath, GetImages);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static Cover GetCover(string Slug, string LogoPath)
|
||||
public static Cover GetCover(string Slug, string ImagePath, bool GetImages)
|
||||
{
|
||||
Task<Cover> RetVal = _GetCover(SearchUsing.slug, Slug, LogoPath);
|
||||
Task<Cover> RetVal = _GetCover(SearchUsing.slug, Slug, ImagePath, GetImages);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<Cover> _GetCover(SearchUsing searchUsing, object searchValue, string LogoPath)
|
||||
private static async Task<Cover> _GetCover(SearchUsing searchUsing, object searchValue, string ImagePath, bool GetImages = true)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
@@ -61,17 +63,18 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
Cover returnValue = new Cover();
|
||||
bool forceImageDownload = false;
|
||||
ImagePath = Path.Combine(ImagePath, "Covers");
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Expired:
|
||||
try
|
||||
{
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
forceImageDownload = true;
|
||||
}
|
||||
@@ -88,11 +91,30 @@ namespace gaseous_server.Classes.Metadata
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
if ((!File.Exists(Path.Combine(LogoPath, "Cover.jpg"))) || forceImageDownload == true)
|
||||
string localFile = Path.Combine(ImagePath, Communications.IGDBAPI_ImageSize.original.ToString(), returnValue.ImageId + ".jpg");
|
||||
if (GetImages == true)
|
||||
{
|
||||
//GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_thumb, returnValue.ImageId);
|
||||
//GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_logo_med, returnValue.ImageId);
|
||||
GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_original, returnValue.ImageId);
|
||||
if ((!File.Exists(localFile)) || forceImageDownload == true)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Metadata: " + returnValue.GetType().Name, "Cover download forced.");
|
||||
|
||||
// check for presence of image file - download if absent or force download is true
|
||||
List<Communications.IGDBAPI_ImageSize> imageSizes = new List<Communications.IGDBAPI_ImageSize>{
|
||||
Communications.IGDBAPI_ImageSize.cover_big,
|
||||
Communications.IGDBAPI_ImageSize.cover_small,
|
||||
Communications.IGDBAPI_ImageSize.original
|
||||
};
|
||||
|
||||
Communications comms = new Communications();
|
||||
foreach (Communications.IGDBAPI_ImageSize size in imageSizes)
|
||||
{
|
||||
localFile = Path.Combine(ImagePath, size.ToString(), returnValue.ImageId + ".jpg");
|
||||
if ((!File.Exists(localFile)) || forceImageDownload == true)
|
||||
{
|
||||
comms.GetSpecificImageFromServer(ImagePath, returnValue.ImageId, size, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
@@ -104,64 +126,15 @@ namespace gaseous_server.Classes.Metadata
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<Cover> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
private static async Task<Cover> GetObjectFromServer(string WhereClause, string ImagePath)
|
||||
{
|
||||
// get Cover metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Cover>(IGDBClient.Endpoints.Covers, fieldList, WhereClause);
|
||||
var result = results.First();
|
||||
|
||||
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb, result.ImageId);
|
||||
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_logo_med, result.ImageId);
|
||||
GetImageFromServer(result.Url, LogoPath, LogoSize.t_original, result.ImageId);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void GetImageFromServer(string Url, string LogoPath, LogoSize logoSize, string ImageId)
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
string fileName = "Cover.jpg";
|
||||
string extension = "jpg";
|
||||
switch (logoSize)
|
||||
{
|
||||
case LogoSize.t_thumb:
|
||||
fileName = "Cover_Thumb";
|
||||
extension = "jpg";
|
||||
break;
|
||||
case LogoSize.t_logo_med:
|
||||
fileName = "Cover_Medium";
|
||||
extension = "png";
|
||||
break;
|
||||
case LogoSize.t_original:
|
||||
fileName = "Cover";
|
||||
extension = "png";
|
||||
break;
|
||||
default:
|
||||
fileName = "Cover";
|
||||
extension = "jpg";
|
||||
break;
|
||||
}
|
||||
string imageUrl = Url.Replace(LogoSize.t_thumb.ToString(), logoSize.ToString()).Replace("jpg", extension);
|
||||
|
||||
using (var s = client.GetStreamAsync("https:" + imageUrl))
|
||||
{
|
||||
if (!Directory.Exists(LogoPath)) { Directory.CreateDirectory(LogoPath); }
|
||||
using (var fs = new FileStream(Path.Combine(LogoPath, fileName + "." + extension), FileMode.OpenOrCreate))
|
||||
{
|
||||
s.Result.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum LogoSize
|
||||
{
|
||||
t_thumb,
|
||||
t_logo_med,
|
||||
t_original
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -98,14 +98,14 @@ namespace gaseous_server.Classes.Metadata
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
UpdateSubClasses(returnValue, getAllMetadata, followSubGames);
|
||||
UpdateSubClasses(returnValue, getAllMetadata, followSubGames, forceRefresh);
|
||||
return returnValue;
|
||||
case Storage.CacheStatus.Expired:
|
||||
try
|
||||
{
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
UpdateSubClasses(returnValue, getAllMetadata, followSubGames);
|
||||
UpdateSubClasses(returnValue, getAllMetadata, followSubGames, forceRefresh);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -115,21 +115,21 @@ namespace gaseous_server.Classes.Metadata
|
||||
return returnValue;
|
||||
case Storage.CacheStatus.Current:
|
||||
returnValue = Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);
|
||||
UpdateSubClasses(returnValue, false, false);
|
||||
UpdateSubClasses(returnValue, false, false, false);
|
||||
return returnValue;
|
||||
default:
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateSubClasses(Game Game, bool getAllMetadata, bool followSubGames)
|
||||
private static void UpdateSubClasses(Game Game, bool getAllMetadata, bool followSubGames, bool forceRefresh)
|
||||
{
|
||||
// required metadata
|
||||
if (Game.Cover != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Cover GameCover = Covers.GetCover(Game.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
|
||||
Cover GameCover = Covers.GetCover(Game.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game), forceRefresh);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -211,7 +211,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
try
|
||||
{
|
||||
Artwork GameArtwork = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
|
||||
Artwork GameArtwork = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game), forceRefresh);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -285,7 +285,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
try
|
||||
{
|
||||
Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
|
||||
Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game), forceRefresh);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -441,9 +441,9 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
Game game = new Game{
|
||||
Id = (long)row["Id"],
|
||||
Name = (string)row["Name"],
|
||||
Slug = (string)row["Slug"],
|
||||
Summary = (string)row["Summary"]
|
||||
Name = (string)Common.ReturnValueIfNull(row["Name"], ""),
|
||||
Slug = (string)Common.ReturnValueIfNull(row["Slug"], ""),
|
||||
Summary = (string)Common.ReturnValueIfNull(row["Summary"], "")
|
||||
};
|
||||
searchResults.Add(game);
|
||||
}
|
||||
@@ -477,17 +477,47 @@ namespace gaseous_server.Classes.Metadata
|
||||
break;
|
||||
}
|
||||
|
||||
// check search cache
|
||||
Game[]? games = Communications.GetSearchCache<Game[]?>(searchFields, searchBody);
|
||||
|
||||
if (games == null)
|
||||
{
|
||||
// cache miss
|
||||
// get Game metadata
|
||||
Communications comms = new Communications();
|
||||
Game[]? results = new Game[0];
|
||||
if (allowSearch == true)
|
||||
{
|
||||
results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody);
|
||||
|
||||
Communications.SetSearchCache<Game[]?>(searchFields, searchBody, results);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
else
|
||||
{
|
||||
return games.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<KeyValuePair<long, string>> GetAvailablePlatforms(long GameId)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT DISTINCT Games_Roms.PlatformId, Platform.`Name` FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @gameid ORDER BY Platform.`Name`;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("gameid", GameId);
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<KeyValuePair<long, string>> platforms = new List<KeyValuePair<long, string>>();
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
KeyValuePair<long, string> valuePair = new KeyValuePair<long, string>((long)row["PlatformId"], (string)row["Name"]);
|
||||
platforms.Add(valuePair);
|
||||
}
|
||||
|
||||
return platforms;
|
||||
}
|
||||
|
||||
public enum SearchType
|
||||
{
|
||||
|
@@ -13,7 +13,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
public static PlatformLogo? GetPlatformLogo(long? Id, string LogoPath)
|
||||
public static PlatformLogo? GetPlatformLogo(long? Id, string ImagePath)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
@@ -21,18 +21,18 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<PlatformLogo> RetVal = _GetPlatformLogo(SearchUsing.id, Id, LogoPath);
|
||||
Task<PlatformLogo> RetVal = _GetPlatformLogo(SearchUsing.id, Id, ImagePath);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static PlatformLogo GetPlatformLogo(string Slug, string LogoPath)
|
||||
public static PlatformLogo GetPlatformLogo(string Slug, string ImagePath)
|
||||
{
|
||||
Task<PlatformLogo> RetVal = _GetPlatformLogo(SearchUsing.slug, Slug, LogoPath);
|
||||
Task<PlatformLogo> RetVal = _GetPlatformLogo(SearchUsing.slug, Slug, ImagePath);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<PlatformLogo> _GetPlatformLogo(SearchUsing searchUsing, object searchValue, string LogoPath)
|
||||
private static async Task<PlatformLogo> _GetPlatformLogo(SearchUsing searchUsing, object searchValue, string ImagePath)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
@@ -64,7 +64,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
if (returnValue != null)
|
||||
{
|
||||
Storage.NewCacheValue(returnValue);
|
||||
@@ -74,7 +74,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
case Storage.CacheStatus.Expired:
|
||||
try
|
||||
{
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
forceImageDownload = true;
|
||||
}
|
||||
@@ -93,10 +93,14 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
if (returnValue != null)
|
||||
{
|
||||
if ((!File.Exists(Path.Combine(LogoPath, "Logo.jpg"))) || forceImageDownload == true)
|
||||
// check for presence of "original" quality file - download if absent or force download is true
|
||||
string localFile = Path.Combine(ImagePath, Communications.IGDBAPI_ImageSize.original.ToString(), returnValue.ImageId + ".jpg");
|
||||
if ((!File.Exists(localFile)) || forceImageDownload == true)
|
||||
{
|
||||
GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_thumb);
|
||||
GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_logo_med);
|
||||
Logging.Log(Logging.LogType.Information, "Metadata: " + returnValue.GetType().Name, "Platform logo download forced.");
|
||||
|
||||
Communications comms = new Communications();
|
||||
comms.GetSpecificImageFromServer(ImagePath, returnValue.ImageId, Communications.IGDBAPI_ImageSize.original, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,65 +113,15 @@ namespace gaseous_server.Classes.Metadata
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<PlatformLogo?> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
private static async Task<PlatformLogo> GetObjectFromServer(string WhereClause, string ImagePath)
|
||||
{
|
||||
// get PlatformLogo metadata
|
||||
// get Artwork metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<PlatformLogo>(IGDBClient.Endpoints.PlatformLogos, fieldList, WhereClause);
|
||||
if (results.Length > 0)
|
||||
{
|
||||
var result = results.First();
|
||||
|
||||
GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb);
|
||||
GetImageFromServer(result.Url, LogoPath, LogoSize.t_logo_med);
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetImageFromServer(string Url, string LogoPath, LogoSize logoSize)
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
string fileName = "Logo.jpg";
|
||||
string extension = "jpg";
|
||||
switch (logoSize)
|
||||
{
|
||||
case LogoSize.t_thumb:
|
||||
fileName = "Logo_Thumb";
|
||||
extension = "jpg";
|
||||
break;
|
||||
case LogoSize.t_logo_med:
|
||||
fileName = "Logo_Medium";
|
||||
extension = "png";
|
||||
break;
|
||||
default:
|
||||
fileName = "Logo";
|
||||
extension = "jpg";
|
||||
break;
|
||||
}
|
||||
string imageUrl = Url.Replace(LogoSize.t_thumb.ToString(), logoSize.ToString()).Replace("jpg", extension);
|
||||
|
||||
using (var s = client.GetStreamAsync("https:" + imageUrl))
|
||||
{
|
||||
if (!Directory.Exists(LogoPath)) { Directory.CreateDirectory(LogoPath); }
|
||||
using (var fs = new FileStream(Path.Combine(LogoPath, fileName + "." + extension), FileMode.OpenOrCreate))
|
||||
{
|
||||
s.Result.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum LogoSize
|
||||
{
|
||||
t_thumb,
|
||||
t_logo_med
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -93,9 +93,16 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static void UpdateSubClasses(Platform ParentPlatform, PlatformVersion platformVersion)
|
||||
{
|
||||
if (platformVersion.PlatformLogo != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
PlatformLogo platformLogo = PlatformLogos.GetPlatformLogo(platformVersion.PlatformLogo.Id, Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(ParentPlatform), "Versions", platformVersion.Slug));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Platform Update", "Unable to fetch platform logo", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum SearchUsing
|
||||
|
@@ -38,10 +38,18 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Task<Platform> RetVal = _GetPlatform(SearchUsing.id, Id, forceRefresh);
|
||||
return RetVal.Result;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata", "An error occurred fetching Platform Id " + Id, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Platform GetPlatform(string Slug, bool forceRefresh = false)
|
||||
@@ -123,9 +131,16 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
|
||||
if (platform.PlatformLogo != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
PlatformLogo platformLogo = PlatformLogos.GetPlatformLogo(platform.PlatformLogo.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(platform));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Platform Update", "Unable to fetch platform logo", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddPlatformMapping(Platform platform)
|
||||
|
@@ -13,7 +13,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
public static Screenshot? GetScreenshot(long? Id, string LogoPath)
|
||||
public static Screenshot? GetScreenshot(long? Id, string ImagePath, bool GetImages)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
@@ -21,18 +21,18 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<Screenshot> RetVal = _GetScreenshot(SearchUsing.id, Id, LogoPath);
|
||||
Task<Screenshot> RetVal = _GetScreenshot(SearchUsing.id, Id, ImagePath, GetImages);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static Screenshot GetScreenshot(string Slug, string LogoPath)
|
||||
public static Screenshot GetScreenshot(string Slug, string ImagePath, bool GetImages)
|
||||
{
|
||||
Task<Screenshot> RetVal = _GetScreenshot(SearchUsing.slug, Slug, LogoPath);
|
||||
Task<Screenshot> RetVal = _GetScreenshot(SearchUsing.slug, Slug, ImagePath, GetImages);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<Screenshot> _GetScreenshot(SearchUsing searchUsing, object searchValue, string LogoPath)
|
||||
private static async Task<Screenshot> _GetScreenshot(SearchUsing searchUsing, object searchValue, string ImagePath, bool GetImages = true)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
@@ -61,18 +61,18 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
Screenshot returnValue = new Screenshot();
|
||||
bool forceImageDownload = false;
|
||||
LogoPath = Path.Combine(LogoPath, "Screenshots");
|
||||
ImagePath = Path.Combine(ImagePath, "Screenshots");
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Expired:
|
||||
try
|
||||
{
|
||||
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
|
||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
forceImageDownload = true;
|
||||
}
|
||||
@@ -89,11 +89,17 @@ namespace gaseous_server.Classes.Metadata
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
if ((!File.Exists(Path.Combine(LogoPath, "Screenshot.jpg"))) || forceImageDownload == true)
|
||||
// check for presence of "original" quality file - download if absent or force download is true
|
||||
string localFile = Path.Combine(ImagePath, Communications.IGDBAPI_ImageSize.original.ToString(), returnValue.ImageId + ".jpg");
|
||||
if (GetImages == true)
|
||||
{
|
||||
//GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_thumb, returnValue.ImageId);
|
||||
//GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_logo_med, returnValue.ImageId);
|
||||
GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_original, returnValue.ImageId);
|
||||
if ((!File.Exists(localFile)) || forceImageDownload == true)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Metadata: " + returnValue.GetType().Name, "Screenshot download forced.");
|
||||
|
||||
Communications comms = new Communications();
|
||||
comms.GetSpecificImageFromServer(ImagePath, returnValue.ImageId, Communications.IGDBAPI_ImageSize.original, null);
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
@@ -105,65 +111,15 @@ namespace gaseous_server.Classes.Metadata
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<Screenshot> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
private static async Task<Screenshot> GetObjectFromServer(string WhereClause, string ImagePath)
|
||||
{
|
||||
// get Screenshot metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Screenshot>(IGDBClient.Endpoints.Screenshots, fieldList, WhereClause);
|
||||
var result = results.First();
|
||||
|
||||
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb, result.ImageId);
|
||||
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_logo_med, result.ImageId);
|
||||
GetImageFromServer(result.Url, LogoPath, LogoSize.t_original, result.ImageId);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void GetImageFromServer(string Url, string LogoPath, LogoSize logoSize, string ImageId)
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
string fileName = "Artwork.jpg";
|
||||
string extension = "jpg";
|
||||
switch (logoSize)
|
||||
{
|
||||
case LogoSize.t_thumb:
|
||||
fileName = "_Thumb";
|
||||
extension = "jpg";
|
||||
break;
|
||||
case LogoSize.t_logo_med:
|
||||
fileName = "_Medium";
|
||||
extension = "png";
|
||||
break;
|
||||
case LogoSize.t_original:
|
||||
fileName = "";
|
||||
extension = "png";
|
||||
break;
|
||||
default:
|
||||
fileName = "Artwork";
|
||||
extension = "jpg";
|
||||
break;
|
||||
}
|
||||
fileName = ImageId + fileName;
|
||||
string imageUrl = Url.Replace(LogoSize.t_thumb.ToString(), logoSize.ToString()).Replace("jpg", extension);
|
||||
|
||||
using (var s = client.GetStreamAsync("https:" + imageUrl))
|
||||
{
|
||||
if (!Directory.Exists(LogoPath)) { Directory.CreateDirectory(LogoPath); }
|
||||
using (var fs = new FileStream(Path.Combine(LogoPath, fileName + "." + extension), FileMode.OpenOrCreate))
|
||||
{
|
||||
s.Result.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum LogoSize
|
||||
{
|
||||
t_thumb,
|
||||
t_logo_med,
|
||||
t_original
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -59,7 +59,7 @@ namespace gaseous_server.Classes
|
||||
try
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Metadata Refresh", "(" + StatusCounter + "/" + dt.Rows.Count + "): Refreshing metadata for game " + dr["name"] + " (" + dr["id"] + ")");
|
||||
Metadata.Games.GetGame((long)dr["id"], true, false, forceRefresh);
|
||||
Metadata.Games.GetGame((long)dr["id"], true, false, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@@ -91,7 +91,7 @@ namespace gaseous_server.Classes
|
||||
mediaGroupItems.Add(BuildMediaGroupFromRow(row));
|
||||
}
|
||||
|
||||
mediaGroupItems.Sort((x, y) => x.PlatformName.CompareTo(y.PlatformName));
|
||||
mediaGroupItems.Sort((x, y) => x.Platform.CompareTo(y.Platform));
|
||||
|
||||
return mediaGroupItems;
|
||||
}
|
||||
@@ -176,6 +176,7 @@ namespace gaseous_server.Classes
|
||||
mediaGroupItem.PlatformId = (long)row["PlatformId"];
|
||||
mediaGroupItem.GameId = (long)row["GameId"];
|
||||
mediaGroupItem.RomIds = new List<long>();
|
||||
mediaGroupItem.Roms = new List<Roms.GameRomItem>();
|
||||
|
||||
// get members
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
@@ -186,6 +187,26 @@ namespace gaseous_server.Classes
|
||||
foreach (DataRow dataRow in data.Rows)
|
||||
{
|
||||
mediaGroupItem.RomIds.Add((long)dataRow["RomId"]);
|
||||
try
|
||||
{
|
||||
mediaGroupItem.Roms.Add(Roms.GetRom((long)dataRow["RomId"]));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Rom Group", "Unable to load ROM data", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// check for a web emulator and update the romItem
|
||||
foreach (Models.PlatformMapping.PlatformMapItem platformMapping in Models.PlatformMapping.PlatformMap)
|
||||
{
|
||||
if (platformMapping.IGDBId == mediaGroupItem.PlatformId)
|
||||
{
|
||||
if (platformMapping.WebEmulator != null)
|
||||
{
|
||||
mediaGroupItem.Emulator = platformMapping.WebEmulator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mediaGroupItem;
|
||||
@@ -360,7 +381,7 @@ namespace gaseous_server.Classes
|
||||
public long Id { get; set; }
|
||||
public long GameId { get; set; }
|
||||
public long PlatformId { get; set; }
|
||||
public string PlatformName {
|
||||
public string Platform {
|
||||
get
|
||||
{
|
||||
try
|
||||
@@ -373,7 +394,9 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
}
|
||||
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
|
||||
public List<long> RomIds { get; set; }
|
||||
public List<Roms.GameRomItem> Roms { get; set; }
|
||||
private GroupBuildStatus _Status { get; set; }
|
||||
public GroupBuildStatus Status {
|
||||
get
|
||||
|
@@ -15,30 +15,50 @@ namespace gaseous_server.Classes
|
||||
{}
|
||||
}
|
||||
|
||||
public static GameRomObject GetRoms(long GameId, long PlatformId = -1, int pageNumber = 0, int pageSize = 0)
|
||||
public static GameRomObject GetRoms(long GameId, long PlatformId = -1, string NameSearch = "", int pageNumber = 0, int pageSize = 0)
|
||||
{
|
||||
GameRomObject GameRoms = new GameRomObject();
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
string sqlCount = "";
|
||||
string sqlPlatform = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", GameId);
|
||||
|
||||
string NameSearchWhere = "";
|
||||
if (NameSearch.Length > 0)
|
||||
{
|
||||
NameSearchWhere = " AND Games_Roms.`Name` LIKE @namesearch";
|
||||
dbDict.Add("namesearch", '%' + NameSearch + '%');
|
||||
}
|
||||
|
||||
// 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) {
|
||||
sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id ORDER BY Platform.`Name`, Games_Roms.`Name`";
|
||||
// data query
|
||||
sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id" + 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 {
|
||||
sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid ORDER BY Platform.`Name`, Games_Roms.`Name`";
|
||||
// data query
|
||||
sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid" + 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 AND Games_Roms.PlatformId = @platformid" + NameSearchWhere + ";";
|
||||
|
||||
dbDict.Add("platformid", PlatformId);
|
||||
}
|
||||
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||
Dictionary<string, object> rowCount = db.ExecuteCMDDict(sqlCount, dbDict)[0];
|
||||
DataTable platformDT = db.ExecuteCMD(sqlPlatform, dbDict);
|
||||
|
||||
if (romDT.Rows.Count > 0)
|
||||
{
|
||||
// set count of roms
|
||||
GameRoms.Count = romDT.Rows.Count;
|
||||
|
||||
// setup platforms list
|
||||
Dictionary<long, string> platformDict = new Dictionary<long, string>();
|
||||
GameRoms.Count = int.Parse((string)rowCount["RomCount"]);
|
||||
|
||||
int pageOffset = pageSize * (pageNumber - 1);
|
||||
for (int i = 0; i < romDT.Rows.Count; i++)
|
||||
@@ -49,18 +69,7 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
GameRoms.GameRomItems.Add(gameRomItem);
|
||||
}
|
||||
|
||||
if (!platformDict.ContainsKey(gameRomItem.PlatformId))
|
||||
{
|
||||
platformDict.Add(gameRomItem.PlatformId, gameRomItem.Platform);
|
||||
}
|
||||
}
|
||||
|
||||
// get rom media groups
|
||||
GameRoms.MediaGroups = Classes.RomMediaGroup.GetMediaGroupsFromGameId(GameId);
|
||||
|
||||
// sort the platforms
|
||||
GameRoms.Platforms = platformDict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value).ToList<KeyValuePair<long, string>>();
|
||||
|
||||
return GameRoms;
|
||||
}
|
||||
@@ -139,16 +148,16 @@ namespace gaseous_server.Classes
|
||||
GameId = (long)romDR["gameid"],
|
||||
Name = (string)romDR["name"],
|
||||
Size = (long)romDR["size"],
|
||||
CRC = ((string)romDR["crc"]).ToLower(),
|
||||
MD5 = ((string)romDR["md5"]).ToLower(),
|
||||
SHA1 = ((string)romDR["sha1"]).ToLower(),
|
||||
Crc = ((string)romDR["crc"]).ToLower(),
|
||||
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 = (int)romDR["romtype"],
|
||||
RomType = (HasheousClient.Models.LookupResponseModel.RomItem.RomTypes)(int)romDR["romtype"],
|
||||
RomTypeMedia = (string)romDR["romtypemedia"],
|
||||
MediaLabel = (string)romDR["medialabel"],
|
||||
Path = (string)romDR["path"],
|
||||
Source = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(Int32)romDR["metadatasource"],
|
||||
SignatureSource = (gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType)(Int32)romDR["metadatasource"],
|
||||
SignatureSourceGameTitle = (string)Common.ReturnValueIfNull(romDR["MetadataGameName"], ""),
|
||||
Library = GameLibrary.GetLibrary((int)romDR["LibraryId"])
|
||||
};
|
||||
@@ -170,136 +179,20 @@ namespace gaseous_server.Classes
|
||||
|
||||
public class GameRomObject
|
||||
{
|
||||
public List<GameRomMediaGroupItem> MediaGroups { get; set; } = new List<GameRomMediaGroupItem>();
|
||||
public List<GameRomItem> GameRomItems { get; set; } = new List<GameRomItem>();
|
||||
public int Count { get; set; }
|
||||
public List<KeyValuePair<long, string>> Platforms { get; set; }
|
||||
}
|
||||
|
||||
public class GameRomItem
|
||||
public class GameRomItem : HasheousClient.Models.LookupResponseModel.RomItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long PlatformId { get; set; }
|
||||
public string Platform { get; set; }
|
||||
//public Dictionary<string, object>? Emulator { get; set; }
|
||||
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
|
||||
public long GameId { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public long Size { get; set; }
|
||||
public string? CRC { get; set; }
|
||||
public string? MD5 { get; set; }
|
||||
public string? SHA1 { get; set; }
|
||||
public string? DevelopmentStatus { get; set; }
|
||||
public string[]? Flags { get; set; }
|
||||
public List<KeyValuePair<string, object>>? Attributes { get; set;}
|
||||
public int RomType { get; set; }
|
||||
public string? RomTypeMedia { get; set; }
|
||||
public MediaType? MediaDetail {
|
||||
get
|
||||
{
|
||||
if (RomTypeMedia != null)
|
||||
{
|
||||
return new MediaType(Source, RomTypeMedia);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
public string? MediaLabel { get; set; }
|
||||
public string? Path { get; set; }
|
||||
public RomSignatureObject.Game.Rom.SignatureSourceType Source { get; set; }
|
||||
public string? SignatureSourceGameTitle { get; set;}
|
||||
public GameLibrary.LibraryItem Library { get; set; }
|
||||
}
|
||||
|
||||
public class MediaType
|
||||
{
|
||||
public MediaType(RomSignatureObject.Game.Rom.SignatureSourceType Source, string MediaTypeString)
|
||||
{
|
||||
switch (Source)
|
||||
{
|
||||
case RomSignatureObject.Game.Rom.SignatureSourceType.TOSEC:
|
||||
string[] typeString = MediaTypeString.Split(" ");
|
||||
|
||||
string inType = "";
|
||||
foreach (string typeStringVal in typeString)
|
||||
{
|
||||
if (inType == "")
|
||||
{
|
||||
switch (typeStringVal.ToLower())
|
||||
{
|
||||
case "disk":
|
||||
Media = RomSignatureObject.Game.Rom.RomTypes.Disk;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "disc":
|
||||
Media = RomSignatureObject.Game.Rom.RomTypes.Disc;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "file":
|
||||
Media = RomSignatureObject.Game.Rom.RomTypes.File;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "part":
|
||||
Media = RomSignatureObject.Game.Rom.RomTypes.Part;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "tape":
|
||||
Media = RomSignatureObject.Game.Rom.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 RomSignatureObject.Game.Rom.RomTypes? Media { get; set; }
|
||||
|
||||
public int? Number { get; set; }
|
||||
|
||||
public int? Count { get; set; }
|
||||
|
||||
public string? Side { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
81
gaseous-server/Classes/SignatureManagement.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System.Data;
|
||||
using gaseous_signature_parser.models.RomSignatureObject;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class SignatureManagement
|
||||
{
|
||||
public List<gaseous_server.Models.Signatures_Games> GetSignature(string md5 = "", string sha1 = "")
|
||||
{
|
||||
if (md5.Length > 0)
|
||||
{
|
||||
return _GetSignature("Signatures_Roms.md5 = @searchstring", md5);
|
||||
} else
|
||||
{
|
||||
return _GetSignature("Signatures_Roms.sha1 = @searchstring", sha1);
|
||||
}
|
||||
}
|
||||
|
||||
public List<gaseous_server.Models.Signatures_Games> GetByTosecName(string TosecName = "")
|
||||
{
|
||||
if (TosecName.Length > 0)
|
||||
{
|
||||
return _GetSignature("Signatures_Roms.name = @searchstring", TosecName);
|
||||
} else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<gaseous_server.Models.Signatures_Games> _GetSignature(string sqlWhere, string searchString)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT view_Signatures_Games.*, Signatures_Roms.Id AS romid, Signatures_Roms.Name AS romname, Signatures_Roms.Size, Signatures_Roms.CRC, Signatures_Roms.MD5, Signatures_Roms.SHA1, Signatures_Roms.DevelopmentStatus, Signatures_Roms.Attributes, Signatures_Roms.RomType, Signatures_Roms.RomTypeMedia, Signatures_Roms.MediaLabel, Signatures_Roms.MetadataSource FROM Signatures_Roms INNER JOIN view_Signatures_Games ON Signatures_Roms.GameId = view_Signatures_Games.Id WHERE " + sqlWhere;
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("searchString", searchString);
|
||||
|
||||
DataTable sigDb = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<gaseous_server.Models.Signatures_Games> GamesList = new List<gaseous_server.Models.Signatures_Games>();
|
||||
|
||||
foreach (DataRow sigDbRow in sigDb.Rows)
|
||||
{
|
||||
gaseous_server.Models.Signatures_Games gameItem = new gaseous_server.Models.Signatures_Games
|
||||
{
|
||||
Game = new gaseous_server.Models.Signatures_Games.GameItem
|
||||
{
|
||||
Id = (Int32)sigDbRow["Id"],
|
||||
Name = (string)sigDbRow["Name"],
|
||||
Description = (string)sigDbRow["Description"],
|
||||
Year = (string)sigDbRow["Year"],
|
||||
Publisher = (string)sigDbRow["Publisher"],
|
||||
Demo = (gaseous_server.Models.Signatures_Games.GameItem.DemoTypes)(int)sigDbRow["Demo"],
|
||||
System = (string)sigDbRow["Platform"],
|
||||
SystemVariant = (string)sigDbRow["SystemVariant"],
|
||||
Video = (string)sigDbRow["Video"],
|
||||
Country = (string)sigDbRow["Country"],
|
||||
Language = (string)sigDbRow["Language"],
|
||||
Copyright = (string)sigDbRow["Copyright"]
|
||||
},
|
||||
Rom = new gaseous_server.Models.Signatures_Games.RomItem
|
||||
{
|
||||
Id = (Int32)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"], "[]")),
|
||||
RomType = (gaseous_server.Models.Signatures_Games.RomItem.RomTypes)(int)sigDbRow["RomType"],
|
||||
RomTypeMedia = (string)sigDbRow["RomTypeMedia"],
|
||||
MediaLabel = (string)sigDbRow["MediaLabel"],
|
||||
SignatureSource = (gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType)(Int32)sigDbRow["MetadataSource"]
|
||||
}
|
||||
};
|
||||
GamesList.Add(gameItem);
|
||||
}
|
||||
return GamesList;
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,6 +8,7 @@ using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Models;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@@ -287,15 +288,15 @@ namespace gaseous_server.Controllers
|
||||
[ProducesResponseType(typeof(Game), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ResponseCache(CacheProfileName = "5Minute")]
|
||||
public ActionResult Game(long GameId, bool forceRefresh = false)
|
||||
public ActionResult Game(long GameId)
|
||||
{
|
||||
try
|
||||
{
|
||||
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, forceRefresh, false, forceRefresh);
|
||||
Game game = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
if (gameObject != null)
|
||||
if (game != null)
|
||||
{
|
||||
return Ok(gameObject);
|
||||
return Ok(game);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -374,87 +375,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/agerating/{RatingId}/image")]
|
||||
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GameAgeClassification(long GameId, long RatingId)
|
||||
{
|
||||
try
|
||||
{
|
||||
GameAgeRating gameAgeRating = GetConsolidatedAgeRating(RatingId);
|
||||
|
||||
string fileExtension = "";
|
||||
string fileType = "";
|
||||
switch (gameAgeRating.RatingBoard)
|
||||
{
|
||||
case AgeRatingCategory.ESRB:
|
||||
fileExtension = "svg";
|
||||
fileType = "image/svg+xml";
|
||||
break;
|
||||
case AgeRatingCategory.PEGI:
|
||||
fileExtension = "svg";
|
||||
fileType = "image/svg+xml";
|
||||
break;
|
||||
case AgeRatingCategory.ACB:
|
||||
fileExtension = "svg";
|
||||
fileType = "image/svg+xml";
|
||||
break;
|
||||
case AgeRatingCategory.CERO:
|
||||
fileExtension = "svg";
|
||||
fileType = "image/svg+xml";
|
||||
break;
|
||||
case AgeRatingCategory.USK:
|
||||
fileExtension = "svg";
|
||||
fileType = "image/svg+xml";
|
||||
break;
|
||||
case AgeRatingCategory.GRAC:
|
||||
fileExtension = "svg";
|
||||
fileType = "image/svg+xml";
|
||||
break;
|
||||
case AgeRatingCategory.CLASS_IND:
|
||||
fileExtension = "svg";
|
||||
fileType = "image/svg+xml";
|
||||
break;
|
||||
}
|
||||
|
||||
string resourceName = "gaseous_server.Assets.Ratings." + gameAgeRating.RatingBoard.ToString() + "." + gameAgeRating.RatingTitle.ToString() + "." + fileExtension;
|
||||
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
string[] resources = assembly.GetManifestResourceNames();
|
||||
if (resources.Contains(resourceName))
|
||||
{
|
||||
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||
using (StreamReader reader = new StreamReader(stream))
|
||||
{
|
||||
byte[] filedata = new byte[stream.Length];
|
||||
stream.Read(filedata, 0, filedata.Length);
|
||||
|
||||
string filename = gameAgeRating.RatingBoard.ToString() + "-" + gameAgeRating.RatingTitle.ToString() + "." + fileExtension;
|
||||
string contentType = fileType;
|
||||
|
||||
var cd = new System.Net.Mime.ContentDisposition
|
||||
{
|
||||
FileName = filename,
|
||||
Inline = true,
|
||||
};
|
||||
|
||||
Response.Headers.Add("Content-Disposition", cd.ToString());
|
||||
Response.Headers.Add("Cache-Control", "public, max-age=604800");
|
||||
|
||||
return File(filedata, contentType);
|
||||
}
|
||||
}
|
||||
return NotFound();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
@@ -473,7 +393,7 @@ namespace gaseous_server.Controllers
|
||||
{
|
||||
foreach (long ArtworkId in gameObject.Artworks.Ids)
|
||||
{
|
||||
Artwork GameArtwork = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject));
|
||||
Artwork GameArtwork = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
||||
artworks.Add(GameArtwork);
|
||||
}
|
||||
}
|
||||
@@ -501,7 +421,7 @@ namespace gaseous_server.Controllers
|
||||
|
||||
try
|
||||
{
|
||||
IGDB.Models.Artwork artworkObject = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject));
|
||||
IGDB.Models.Artwork artworkObject = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
||||
if (artworkObject != null)
|
||||
{
|
||||
return Ok(artworkObject);
|
||||
@@ -525,10 +445,11 @@ namespace gaseous_server.Controllers
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/artwork/{ArtworkId}/image")]
|
||||
[Route("{GameId}/artwork/{ArtworkId}/image/{size}")]
|
||||
[Route("{GameId}/artwork/{ArtworkId}/image/{size}/{ImageName}")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GameCoverImage(long GameId, long ArtworkId)
|
||||
public ActionResult GameCoverImage(long GameId, long ArtworkId, Communications.IGDBAPI_ImageSize size, string ImageName)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -536,15 +457,25 @@ namespace gaseous_server.Controllers
|
||||
|
||||
try
|
||||
{
|
||||
IGDB.Models.Artwork artworkObject = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject));
|
||||
IGDB.Models.Artwork artworkObject = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), true);
|
||||
|
||||
if (artworkObject != null) {
|
||||
string coverFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Artwork", artworkObject.ImageId + ".png");
|
||||
//string coverFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Artwork", size.ToString(), artworkObject.ImageId + ".jpg");
|
||||
|
||||
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Artwork");
|
||||
|
||||
Communications comms = new Communications();
|
||||
Task<string> ImgFetch = comms.GetSpecificImageFromServer(basePath, artworkObject.ImageId, size, new List<Communications.IGDBAPI_ImageSize>{ Communications.IGDBAPI_ImageSize.original });
|
||||
|
||||
string coverFilePath = ImgFetch.Result;
|
||||
|
||||
|
||||
if (System.IO.File.Exists(coverFilePath))
|
||||
{
|
||||
string filename = artworkObject.ImageId + ".png";
|
||||
string filename = artworkObject.ImageId + ".jpg";
|
||||
string filepath = coverFilePath;
|
||||
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
|
||||
string contentType = "image/png";
|
||||
string contentType = "image/jpg";
|
||||
|
||||
var cd = new System.Net.Mime.ContentDisposition
|
||||
{
|
||||
@@ -592,7 +523,7 @@ namespace gaseous_server.Controllers
|
||||
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
if (gameObject != null)
|
||||
{
|
||||
IGDB.Models.Cover coverObject = Covers.GetCover(gameObject.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject));
|
||||
IGDB.Models.Cover coverObject = Covers.GetCover(gameObject.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
||||
if (coverObject != null)
|
||||
{
|
||||
return Ok(coverObject);
|
||||
@@ -616,21 +547,33 @@ namespace gaseous_server.Controllers
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/cover/image")]
|
||||
[Route("{GameId}/cover/image/{size}")]
|
||||
[Route("{GameId}/cover/image/{size}/{imagename}")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GameCoverImage(long GameId)
|
||||
public ActionResult GameCoverImage(long GameId, Communications.IGDBAPI_ImageSize size, string imagename = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
string coverFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Cover.png");
|
||||
if (gameObject.Cover != null)
|
||||
{
|
||||
if (gameObject.Cover.Id != null)
|
||||
{
|
||||
IGDB.Models.Cover cover = Classes.Metadata.Covers.GetCover(gameObject.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
||||
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Covers");
|
||||
|
||||
Communications comms = new Communications();
|
||||
Task<string> ImgFetch = comms.GetSpecificImageFromServer(basePath, cover.ImageId, size, new List<Communications.IGDBAPI_ImageSize>{ Communications.IGDBAPI_ImageSize.cover_big, Communications.IGDBAPI_ImageSize.original });
|
||||
|
||||
string coverFilePath = ImgFetch.Result;
|
||||
|
||||
if (System.IO.File.Exists(coverFilePath)) {
|
||||
string filename = "Cover.png";
|
||||
string filename = cover.ImageId + ".jpg";
|
||||
string filepath = coverFilePath;
|
||||
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
|
||||
string contentType = "image/png";
|
||||
string contentType = "image/jpg";
|
||||
|
||||
var cd = new System.Net.Mime.ContentDisposition
|
||||
{
|
||||
@@ -643,11 +586,10 @@ namespace gaseous_server.Controllers
|
||||
|
||||
return File(filedata, contentType);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
return NotFound();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
@@ -825,6 +767,24 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/platforms")]
|
||||
[ProducesResponseType(typeof(List<KeyValuePair<long, string>>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GamePlatforms(long GameId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(Games.GetAvailablePlatforms(GameId));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
@@ -870,13 +830,13 @@ namespace gaseous_server.Controllers
|
||||
[ProducesResponseType(typeof(Classes.Roms.GameRomObject), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||
public ActionResult GameRom(long GameId, int pageNumber = 0, int pageSize = 0, long PlatformId = -1)
|
||||
public ActionResult GameRom(long GameId, int pageNumber = 0, int pageSize = 0, long PlatformId = -1, string NameSearch = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
return Ok(Classes.Roms.GetRoms(GameId, PlatformId, pageNumber, pageSize));
|
||||
return Ok(Classes.Roms.GetRoms(GameId, PlatformId, NameSearch, pageNumber, pageSize));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -1080,6 +1040,35 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[Route("{GameId}/romgroup")]
|
||||
[ProducesResponseType(typeof(List<RomMediaGroup.GameRomMediaGroupItem>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GetGameRomGroup(long GameId)
|
||||
{
|
||||
try
|
||||
{
|
||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
try
|
||||
{
|
||||
return Ok(RomMediaGroup.GetMediaGroupsFromGameId(GameId));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Rom Group", "An error occurred", ex);
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
@@ -1232,7 +1221,8 @@ namespace gaseous_server.Controllers
|
||||
{
|
||||
Classes.Roms.GameRomItem romItem = Classes.Roms.GetRom(RomId);
|
||||
Common.hashObject hash = new Common.hashObject(romItem.Path);
|
||||
Models.Signatures_Games romSig = Classes.ImportGame.GetFileSignature(hash, new FileInfo(romItem.Path), romItem.Path);
|
||||
FileSignature fileSignature = new FileSignature();
|
||||
gaseous_server.Models.Signatures_Games romSig = fileSignature.GetFileSignature(romItem.Library, hash, new FileInfo(romItem.Path), romItem.Path);
|
||||
List<Game> searchResults = Classes.ImportGame.SearchForGame_GetAll(romSig.Game.Name, romSig.Flags.IGDBPlatformId);
|
||||
|
||||
return Ok(searchResults);
|
||||
@@ -1275,7 +1265,7 @@ namespace gaseous_server.Controllers
|
||||
{
|
||||
foreach (long ScreenshotId in gameObject.Screenshots.Ids)
|
||||
{
|
||||
Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject));
|
||||
Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
||||
screenshots.Add(GameScreenshot);
|
||||
}
|
||||
}
|
||||
@@ -1301,7 +1291,7 @@ namespace gaseous_server.Controllers
|
||||
{
|
||||
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
if (gameObject != null) {
|
||||
IGDB.Models.Screenshot screenshotObject = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject));
|
||||
IGDB.Models.Screenshot screenshotObject = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
||||
if (screenshotObject != null)
|
||||
{
|
||||
return Ok(screenshotObject);
|
||||
@@ -1325,24 +1315,31 @@ namespace gaseous_server.Controllers
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/screenshots/{ScreenshotId}/image")]
|
||||
[Route("{GameId}/screenshots/{ScreenshotId}/image/{size}")]
|
||||
[Route("{GameId}/screenshots/{ScreenshotId}/image/{size}/{ImageName}")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GameScreenshotImage(long GameId, long ScreenshotId)
|
||||
public ActionResult GameScreenshotImage(long GameId, long ScreenshotId, Communications.IGDBAPI_ImageSize Size, string ImageName)
|
||||
{
|
||||
try
|
||||
{
|
||||
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
IGDB.Models.Screenshot screenshotObject = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject));
|
||||
IGDB.Models.Screenshot screenshotObject = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), true);
|
||||
|
||||
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Screenshots");
|
||||
|
||||
Communications comms = new Communications();
|
||||
Task<string> ImgFetch = comms.GetSpecificImageFromServer(basePath, screenshotObject.ImageId, Size, new List<Communications.IGDBAPI_ImageSize>{ Communications.IGDBAPI_ImageSize.original });
|
||||
|
||||
string coverFilePath = ImgFetch.Result;
|
||||
|
||||
string coverFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Screenshots", screenshotObject.ImageId + ".png");
|
||||
if (System.IO.File.Exists(coverFilePath))
|
||||
{
|
||||
string filename = screenshotObject.ImageId + ".png";
|
||||
string filename = screenshotObject.ImageId + ".jpg";
|
||||
string filepath = coverFilePath;
|
||||
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
|
||||
string contentType = "image/png";
|
||||
string contentType = "image/jpg";
|
||||
|
||||
var cd = new System.Net.Mime.ContentDisposition
|
||||
{
|
||||
|
@@ -77,7 +77,8 @@ namespace gaseous_server.Controllers
|
||||
// Process uploaded files
|
||||
foreach (Dictionary<string, object> UploadedFile in UploadedFiles)
|
||||
{
|
||||
Classes.ImportGame.ImportGameFile((string)UploadedFile["fullpath"], OverridePlatform);
|
||||
Classes.ImportGame uploadImport = new ImportGame();
|
||||
uploadImport.ImportGameFile((string)UploadedFile["fullpath"], OverridePlatform);
|
||||
}
|
||||
|
||||
if (Directory.Exists(workPath))
|
||||
|
@@ -1,13 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Models;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NuGet.Common;
|
||||
using static gaseous_server.Classes.Metadata.Games;
|
||||
|
||||
|
||||
@@ -37,36 +40,88 @@ namespace gaseous_server.Controllers
|
||||
string searchFields = "fields abbreviation,alternative_name,category,checksum,created_at,generation,name,platform_family,platform_logo,slug,summary,updated_at,url,versions,websites; ";
|
||||
searchBody += "where name ~ *\"" + SearchString + "\"*;";
|
||||
|
||||
// get Platform metadata
|
||||
List<Platform>? searchCache = Communications.GetSearchCache<List<Platform>>(searchFields, searchBody);
|
||||
|
||||
if (searchCache == null)
|
||||
{
|
||||
// cache miss
|
||||
// get Platform metadata from data source
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Platform>(IGDBClient.Endpoints.Platforms, searchFields, searchBody);
|
||||
|
||||
Communications.SetSearchCache<List<Platform>>(searchFields, searchBody, results.ToList());
|
||||
|
||||
return results.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
return searchCache;
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("Game")]
|
||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(List<GaseousGame>), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult> SearchGame(long PlatformId, string SearchString)
|
||||
{
|
||||
List<Game> RetVal = await _SearchForGame(PlatformId, SearchString);
|
||||
List<GaseousGame> RetVal = await _SearchForGame(PlatformId, SearchString);
|
||||
return Ok(RetVal);
|
||||
}
|
||||
|
||||
private static async Task<List<Game>> _SearchForGame(long PlatformId, string SearchString)
|
||||
private static async Task<List<GaseousGame>> _SearchForGame(long PlatformId, string SearchString)
|
||||
{
|
||||
string searchBody = "";
|
||||
string searchFields = "fields cover.*,first_release_date,name,platforms,slug; ";
|
||||
string searchFields = "fields cover,first_release_date,name,platforms,slug; ";
|
||||
searchBody += "search \"" + SearchString + "\";";
|
||||
searchBody += "where platforms = (" + PlatformId + ");";
|
||||
|
||||
// get Platform metadata
|
||||
List<GaseousGame>? searchCache = Communications.GetSearchCache<List<GaseousGame>>(searchFields, searchBody);
|
||||
|
||||
if (searchCache == null)
|
||||
{
|
||||
// cache miss
|
||||
// get Game metadata from data source
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody);
|
||||
|
||||
return results.ToList();
|
||||
List<GaseousGame> games = new List<GaseousGame>();
|
||||
foreach (Game game in results.ToList())
|
||||
{
|
||||
Storage.CacheStatus cacheStatus = Storage.GetCacheStatus("Game", (long)game.Id);
|
||||
switch(cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
Storage.NewCacheValue(game, false);
|
||||
break;
|
||||
|
||||
case Storage.CacheStatus.Expired:
|
||||
Storage.NewCacheValue(game, true);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
games.Add(new GaseousGame(game));
|
||||
}
|
||||
|
||||
Communications.SetSearchCache<List<GaseousGame>>(searchFields, searchBody, games);
|
||||
|
||||
return games;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get full version of results from database
|
||||
// this is a hacky workaround due to the readonly nature of IGDB.Model.Game IdentityOrValue fields
|
||||
List<GaseousGame> gamesToReturn = new List<GaseousGame>();
|
||||
foreach (GaseousGame game in searchCache)
|
||||
{
|
||||
Game tempGame = Games.GetGame((long)game.Id, false, false, false);
|
||||
gamesToReturn.Add(new GaseousGame(tempGame));
|
||||
}
|
||||
|
||||
return gamesToReturn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -37,82 +37,27 @@ namespace gaseous_server.Controllers
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public List<Models.Signatures_Games> GetSignature(string md5 = "", string sha1 = "")
|
||||
public List<gaseous_server.Models.Signatures_Games> GetSignature(string md5 = "", string sha1 = "")
|
||||
{
|
||||
if (md5.Length > 0)
|
||||
{
|
||||
return _GetSignature("Signatures_Roms.md5 = @searchstring", md5);
|
||||
} else
|
||||
{
|
||||
return _GetSignature("Signatures_Roms.sha1 = @searchstring", sha1);
|
||||
}
|
||||
SignatureManagement signatureManagement = new SignatureManagement();
|
||||
return signatureManagement.GetSignature(md5, sha1);
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public List<Models.Signatures_Games> GetByTosecName(string TosecName = "")
|
||||
public List<gaseous_server.Models.Signatures_Games> GetByTosecName(string TosecName = "")
|
||||
{
|
||||
if (TosecName.Length > 0)
|
||||
{
|
||||
return _GetSignature("Signatures_Roms.name = @searchstring", TosecName);
|
||||
SignatureManagement signatureManagement = new SignatureManagement();
|
||||
return signatureManagement.GetByTosecName(TosecName);
|
||||
} else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<Models.Signatures_Games> _GetSignature(string sqlWhere, string searchString)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT view_Signatures_Games.*, Signatures_Roms.Id AS romid, Signatures_Roms.Name AS romname, Signatures_Roms.Size, Signatures_Roms.CRC, Signatures_Roms.MD5, Signatures_Roms.SHA1, Signatures_Roms.DevelopmentStatus, Signatures_Roms.Attributes, Signatures_Roms.RomType, Signatures_Roms.RomTypeMedia, Signatures_Roms.MediaLabel, Signatures_Roms.MetadataSource FROM Signatures_Roms INNER JOIN view_Signatures_Games ON Signatures_Roms.GameId = view_Signatures_Games.Id WHERE " + sqlWhere;
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("searchString", searchString);
|
||||
|
||||
DataTable sigDb = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<Models.Signatures_Games> GamesList = new List<Models.Signatures_Games>();
|
||||
|
||||
foreach (DataRow sigDbRow in sigDb.Rows)
|
||||
{
|
||||
Models.Signatures_Games gameItem = new Models.Signatures_Games
|
||||
{
|
||||
Game = new Models.Signatures_Games.GameItem
|
||||
{
|
||||
Id = (Int32)sigDbRow["Id"],
|
||||
Name = (string)sigDbRow["Name"],
|
||||
Description = (string)sigDbRow["Description"],
|
||||
Year = (string)sigDbRow["Year"],
|
||||
Publisher = (string)sigDbRow["Publisher"],
|
||||
Demo = (Models.Signatures_Games.GameItem.DemoTypes)(int)sigDbRow["Demo"],
|
||||
System = (string)sigDbRow["Platform"],
|
||||
SystemVariant = (string)sigDbRow["SystemVariant"],
|
||||
Video = (string)sigDbRow["Video"],
|
||||
Country = (string)sigDbRow["Country"],
|
||||
Language = (string)sigDbRow["Language"],
|
||||
Copyright = (string)sigDbRow["Copyright"]
|
||||
},
|
||||
Rom = new Models.Signatures_Games.RomItem
|
||||
{
|
||||
Id = (Int32)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"], "[]")),
|
||||
RomType = (RomSignatureObject.Game.Rom.RomTypes)(int)sigDbRow["RomType"],
|
||||
RomTypeMedia = (string)sigDbRow["RomTypeMedia"],
|
||||
MediaLabel = (string)sigDbRow["MediaLabel"],
|
||||
SignatureSource = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(Int32)sigDbRow["MetadataSource"]
|
||||
}
|
||||
};
|
||||
GamesList.Add(gameItem);
|
||||
}
|
||||
return GamesList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
94
gaseous-server/Models/GaseousGame.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
using System.Reflection;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
|
||||
namespace gaseous_server.Models
|
||||
{
|
||||
public class GaseousGame : IGDB.Models.Game
|
||||
{
|
||||
public GaseousGame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GaseousGame(IGDB.Models.Game game)
|
||||
{
|
||||
var targetType = this.GetType();
|
||||
var sourceType = game.GetType();
|
||||
foreach(var prop in targetType.GetProperties(BindingFlags.Instance | BindingFlags.Public| BindingFlags.SetProperty))
|
||||
{
|
||||
// check whether source object has the the property
|
||||
var sp = sourceType.GetProperty(prop.Name);
|
||||
if (sp != null)
|
||||
{
|
||||
// if yes, copy the value to the matching property
|
||||
var value = sp.GetValue(game, null);
|
||||
prop.SetValue(this, value, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IGDB.Models.Cover? CoverItem
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Cover != null)
|
||||
{
|
||||
if (this.Cover.Id != null)
|
||||
{
|
||||
IGDB.Models.Cover cover = Covers.GetCover(Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(this), false);
|
||||
|
||||
return cover;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// public List<IGDB.Models.Artwork>? ArtworksItem
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// if (this.Artworks != null)
|
||||
// {
|
||||
// if (this.Artworks.Ids != null)
|
||||
// {
|
||||
// List<IGDB.Models.Artwork> artworks = new List<IGDB.Models.Artwork>();
|
||||
// foreach (long id in this.Artworks.Ids)
|
||||
// {
|
||||
// artworks.Add(gaseous_server.Classes.Metadata.Artworks.GetArtwork(id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(this), false));
|
||||
// }
|
||||
|
||||
// return artworks;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// public List<IGDB.Models.Screenshot>? ScreenshotsItem
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// if (this.Screenshots != null)
|
||||
// {
|
||||
// if (this.Screenshots.Ids != null)
|
||||
// {
|
||||
// List<IGDB.Models.Screenshot> screenshots = new List<IGDB.Models.Screenshot>();
|
||||
// foreach (long id in this.Screenshots.Ids)
|
||||
// {
|
||||
// screenshots.Add(gaseous_server.Classes.Metadata.Screenshots.GetScreenshot(id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(this), false));
|
||||
// }
|
||||
|
||||
// return screenshots;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
@@ -106,11 +106,19 @@ namespace gaseous_server.Models
|
||||
long mapId = (long)row["Id"];
|
||||
if (PlatformMapCache.ContainsKey(mapId.ToString()))
|
||||
{
|
||||
platformMaps.Add(PlatformMapCache[mapId.ToString()]);
|
||||
PlatformMapItem mapItem = PlatformMapCache[mapId.ToString()];
|
||||
if (mapItem != null)
|
||||
{
|
||||
platformMaps.Add(mapItem);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
platformMaps.Add(BuildPlatformMapItem(row));
|
||||
PlatformMapItem mapItem = BuildPlatformMapItem(row);
|
||||
if (mapItem != null)
|
||||
{
|
||||
platformMaps.Add(mapItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,8 +261,10 @@ namespace gaseous_server.Models
|
||||
string sql = "";
|
||||
|
||||
// get platform data
|
||||
IGDB.Models.Platform platform = Platforms.GetPlatform(IGDBId);
|
||||
IGDB.Models.Platform? platform = Platforms.GetPlatform(IGDBId);
|
||||
|
||||
if (platform != null)
|
||||
{
|
||||
// get platform alternate names
|
||||
sql = "SELECT * FROM PlatformMap_AlternateNames WHERE Id = @Id ORDER BY Name";
|
||||
dbDict.Clear();
|
||||
@@ -358,14 +368,22 @@ namespace gaseous_server.Models
|
||||
return mapItem;
|
||||
}
|
||||
|
||||
public static void GetIGDBPlatformMapping(ref Models.Signatures_Games Signature, FileInfo RomFileInfo, bool SetSystemName)
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void GetIGDBPlatformMapping(ref gaseous_server.Models.Signatures_Games Signature, string ImageExtension, bool SetSystemName)
|
||||
{
|
||||
if (Signature.Game != null)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Platform Mapping", "Determining platform based on extension " + ImageExtension + " or \"" + Signature.Game.System + "\"");
|
||||
}
|
||||
|
||||
bool PlatformFound = false;
|
||||
foreach (Models.PlatformMapping.PlatformMapItem PlatformMapping in Models.PlatformMapping.PlatformMap)
|
||||
{
|
||||
if (PlatformMapping.Extensions != null)
|
||||
{
|
||||
if (PlatformMapping.Extensions.UniqueFileExtensions.Contains(RomFileInfo.Extension, StringComparer.OrdinalIgnoreCase))
|
||||
if (PlatformMapping.Extensions.UniqueFileExtensions.Contains(ImageExtension, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
if (SetSystemName == true)
|
||||
{
|
||||
@@ -375,6 +393,8 @@ namespace gaseous_server.Models
|
||||
Signature.Flags.IGDBPlatformName = PlatformMapping.IGDBName;
|
||||
|
||||
PlatformFound = true;
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Platform Mapping", "Platform id " + PlatformMapping.IGDBId + " determined from file extension");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -397,10 +417,17 @@ namespace gaseous_server.Models
|
||||
Signature.Flags.IGDBPlatformName = PlatformMapping.IGDBName;
|
||||
|
||||
PlatformFound = true;
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Platform Mapping", "Platform id " + PlatformMapping.IGDBId + " determined from signature system to platform map");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PlatformFound == false)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Platform Mapping", "Unable to determine platform");
|
||||
}
|
||||
}
|
||||
|
||||
public class PlatformMapItem
|
||||
|
@@ -4,197 +4,19 @@ using gaseous_signature_parser.models.RomSignatureObject;
|
||||
|
||||
namespace gaseous_server.Models
|
||||
{
|
||||
public class Signatures_Games
|
||||
public class Signatures_Games : HasheousClient.Models.LookupResponseModel
|
||||
{
|
||||
public Signatures_Games()
|
||||
{
|
||||
}
|
||||
|
||||
public GameItem? Game { get; set; }
|
||||
public RomItem? Rom { get; set; }
|
||||
|
||||
//[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 SignatureFlags Flags = new SignatureFlags();
|
||||
|
||||
public class GameItem
|
||||
{
|
||||
public Int32? Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Year { get; set; }
|
||||
public string? Publisher { get; set; }
|
||||
public DemoTypes Demo { get; set; }
|
||||
public string? System { get; set; }
|
||||
public string? SystemVariant { get; set; }
|
||||
public string? Video { get; set; }
|
||||
public string? Country { get; set; }
|
||||
public string? Language { get; set; }
|
||||
public string? Copyright { get; set; }
|
||||
|
||||
public enum DemoTypes
|
||||
{
|
||||
NotDemo = 0,
|
||||
demo = 1,
|
||||
demo_kiosk = 2,
|
||||
demo_playable = 3,
|
||||
demo_rolling = 4,
|
||||
demo_slideshow = 5
|
||||
}
|
||||
|
||||
[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
|
||||
{
|
||||
public Int32? Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public Int64? Size { get; set; }
|
||||
public string? Crc { get; set; }
|
||||
public string? Md5 { get; set; }
|
||||
public string? Sha1 { get; set; }
|
||||
|
||||
public string? DevelopmentStatus { get; set; }
|
||||
|
||||
public List<KeyValuePair<string, object>> Attributes { get; set; } = new List<KeyValuePair<string, object>>();
|
||||
|
||||
public RomSignatureObject.Game.Rom.RomTypes RomType { get; set; }
|
||||
public string? RomTypeMedia { get; set; }
|
||||
public string? MediaLabel { get; set; }
|
||||
|
||||
public RomSignatureObject.Game.Rom.SignatureSourceType SignatureSource { get; set; }
|
||||
|
||||
[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 SignatureFlags
|
||||
{
|
||||
public long IGDBPlatformId { get; set; }
|
||||
public string IGDBPlatformName { get; set; }
|
||||
public long IGDBGameId { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,8 @@
|
||||
using System.ComponentModel.Design.Serialization;
|
||||
using System.Data;
|
||||
using gaseous_server.Classes;
|
||||
using NuGet.Common;
|
||||
using NuGet.Packaging;
|
||||
|
||||
namespace gaseous_server
|
||||
{
|
||||
@@ -144,10 +146,11 @@ namespace gaseous_server
|
||||
|
||||
case QueueItemType.TitleIngestor:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Title Ingestor");
|
||||
Classes.ImportGames importGames = new Classes.ImportGames(Config.LibraryConfiguration.LibraryImportDirectory)
|
||||
Classes.ImportGame import = new ImportGame
|
||||
{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
import.ProcessDirectory(Config.LibraryConfiguration.LibraryImportDirectory);
|
||||
|
||||
// clean up
|
||||
Classes.ImportGame.DeleteOrphanedDirectories(Config.LibraryConfiguration.LibraryImportDirectory);
|
||||
@@ -170,24 +173,39 @@ namespace gaseous_server
|
||||
|
||||
case QueueItemType.OrganiseLibrary:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Library Organiser");
|
||||
Classes.ImportGame.OrganiseLibrary();
|
||||
Classes.ImportGame importLibraryOrg = new ImportGame
|
||||
{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
importLibraryOrg.OrganiseLibrary();
|
||||
|
||||
_SaveLastRunTime = true;
|
||||
|
||||
break;
|
||||
|
||||
case QueueItemType.LibraryScan:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Library Scanner");
|
||||
Classes.ImportGame import = new ImportGame
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Library Scanners");
|
||||
Classes.ImportGame libScan = new ImportGame
|
||||
{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
import.LibraryScan();
|
||||
libScan.LibraryScan();
|
||||
|
||||
_SaveLastRunTime = true;
|
||||
|
||||
break;
|
||||
|
||||
case QueueItemType.LibraryScanWorker:
|
||||
GameLibrary.LibraryItem library = (GameLibrary.LibraryItem)Options;
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Library Scanner worker for library " + library.Name);
|
||||
Classes.ImportGame importLibraryScan = new ImportGame
|
||||
{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
importLibraryScan.LibrarySpecificScan(library);
|
||||
|
||||
break;
|
||||
|
||||
case QueueItemType.Rematcher:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Rematch");
|
||||
Classes.ImportGame importRematch = new ImportGame
|
||||
@@ -223,6 +241,32 @@ namespace gaseous_server
|
||||
maintenance.RunMaintenance();
|
||||
break;
|
||||
|
||||
case QueueItemType.TempCleanup:
|
||||
try
|
||||
{
|
||||
foreach (GameLibrary.LibraryItem libraryItem in GameLibrary.GetLibraries)
|
||||
{
|
||||
string rootPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, libraryItem.Id.ToString());
|
||||
if (Directory.Exists(rootPath))
|
||||
{
|
||||
foreach (string directory in Directory.GetDirectories(rootPath))
|
||||
{
|
||||
DirectoryInfo info = new DirectoryInfo(directory);
|
||||
if (info.LastWriteTimeUtc.AddMinutes(5) < DateTime.UtcNow)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Deleting temporary decompress folder: " + directory);
|
||||
Directory.Delete(directory, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception tcEx)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Get Signature", "An error occurred while cleaning temporary files", tcEx);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -350,6 +394,11 @@ namespace gaseous_server
|
||||
/// </summary>
|
||||
LibraryScan,
|
||||
|
||||
/// <summary>
|
||||
/// Performs the work for the LibraryScan task
|
||||
/// </summary>
|
||||
LibraryScanWorker,
|
||||
|
||||
/// <summary>
|
||||
/// Looks for roms in the library that have an unknown platform or game match
|
||||
/// </summary>
|
||||
@@ -373,7 +422,12 @@ namespace gaseous_server
|
||||
/// <summary>
|
||||
/// Performs a clean up of old files, and optimises the database
|
||||
/// </summary>
|
||||
Maintainer
|
||||
Maintainer,
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up marked paths in the temporary directory
|
||||
/// </summary>
|
||||
TempCleanup
|
||||
}
|
||||
|
||||
public enum QueueItemState
|
||||
|
@@ -50,7 +50,10 @@ Config.InitSettings();
|
||||
Config.UpdateConfig();
|
||||
|
||||
// set api metadata source from config
|
||||
Communications.MetadataSource = Config.MetadataConfiguration.Source;
|
||||
Communications.MetadataSource = Config.MetadataConfiguration.MetadataSource;
|
||||
|
||||
// set up hasheous client
|
||||
HasheousClient.WebApp.HttpHelper.BaseUri = Config.MetadataConfiguration.HasheousHost;
|
||||
|
||||
// set initial values
|
||||
Guid APIKey = Guid.NewGuid();
|
||||
@@ -106,6 +109,11 @@ builder.Services.AddControllers().AddJsonOptions(x =>
|
||||
builder.Services.AddResponseCaching();
|
||||
builder.Services.AddControllers(options =>
|
||||
{
|
||||
options.CacheProfiles.Add("None",
|
||||
new CacheProfile()
|
||||
{
|
||||
Duration = 1
|
||||
});
|
||||
options.CacheProfiles.Add("Default30",
|
||||
new CacheProfile()
|
||||
{
|
||||
@@ -468,6 +476,16 @@ ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
|
||||
})
|
||||
);
|
||||
|
||||
ProcessQueue.QueueItem tempCleanup = new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.TempCleanup,
|
||||
1,
|
||||
new List<ProcessQueue.QueueItemType>(),
|
||||
false,
|
||||
false
|
||||
);
|
||||
tempCleanup.ForceExecute();
|
||||
ProcessQueue.QueueItems.Add(tempCleanup);
|
||||
|
||||
Logging.WriteToDiskOnly = false;
|
||||
|
||||
// start the app
|
||||
|
5
gaseous-server/Support/Database/MySQL/gaseous-1012.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE `Games_Roms`
|
||||
ADD INDEX `id_IdAndLibraryId` (`Id` ASC, `LibraryId` ASC) VISIBLE;
|
||||
|
||||
ALTER TABLE `ServerLogs`
|
||||
ADD INDEX `idx_EventDate` (`EventTime` ASC) VISIBLE;
|
9
gaseous-server/Support/Database/MySQL/gaseous-1013.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE `SearchCache` (
|
||||
`SearchFields` varchar(384) NOT NULL,
|
||||
`SearchString` varchar(128) NOT NULL,
|
||||
`Content` longtext DEFAULT NULL,
|
||||
`LastSearch` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`SearchFields`,`SearchString`),
|
||||
KEY `idx_SearchString` (`SearchFields`,`SearchString`),
|
||||
KEY `idx_LastSearch` (`LastSearch`)
|
||||
);
|
2
gaseous-server/Support/Database/MySQL/gaseous-1014.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `RomCollections`
|
||||
ADD COLUMN `ArchiveType` INT NULL AFTER `IncludeBIOSFiles`;
|
@@ -188,6 +188,91 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"igdbId": 114,
|
||||
"igdbName": "Amiga CD32",
|
||||
"igdbSlug": "amiga-cd32",
|
||||
"alternateNames": [
|
||||
"Amiga CD32",
|
||||
"Commodore Amiga CD32"
|
||||
],
|
||||
"extensions": {
|
||||
"supportedFileExtensions": [
|
||||
".ZIP"
|
||||
],
|
||||
"uniqueFileExtensions": [
|
||||
]
|
||||
},
|
||||
"retroPieDirectoryName": "amiga",
|
||||
"webEmulator": {
|
||||
"type": "EmulatorJS",
|
||||
"core": "amiga",
|
||||
"availableWebEmulators": [
|
||||
{
|
||||
"emulatorType": "EmulatorJS",
|
||||
"availableWebEmulatorCores": [
|
||||
{
|
||||
"core": "amiga",
|
||||
"alternateCoreName": "puae",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"bios": [
|
||||
{
|
||||
"hash": "85ad74194e87c08904327de1a9443b7a",
|
||||
"description": "Kickstart v1.2 rev 33.180",
|
||||
"filename": "kick33180.A500"
|
||||
},
|
||||
{
|
||||
"hash": "82a21c1890cae844b3df741f2762d48d",
|
||||
"description": "Kickstart v1.3 rev 34.005",
|
||||
"filename": "kick34005.A500"
|
||||
},
|
||||
{
|
||||
"hash": "89da1838a24460e4b93f4f0c5d92d48d",
|
||||
"description": "CDTV extended ROM v1.00",
|
||||
"filename": "kick34005.CDTV"
|
||||
},
|
||||
{
|
||||
"hash": "dc10d7bdd1b6f450773dfb558477c230",
|
||||
"description": "Kickstart v2.04 rev 37.175",
|
||||
"filename": "kick37175.A500"
|
||||
},
|
||||
{
|
||||
"hash": "5f8924d013dd57a89cf349f4cdedc6b1",
|
||||
"description": "CD32 Kickstart v3.1 rev 40.060",
|
||||
"filename": "kick40060.CD32"
|
||||
},
|
||||
{
|
||||
"hash": "f2f241bf094168cfb9e7805dc2856433",
|
||||
"description": "CD32 KS + extended v3.1 rev 40.060",
|
||||
"filename": "kick40060.CD32"
|
||||
},
|
||||
{
|
||||
"hash": "bb72565701b1b6faece07d68ea5da639",
|
||||
"description": "CD32 extended ROM rev 40.060",
|
||||
"filename": "kick40060.CD32.ext"
|
||||
},
|
||||
{
|
||||
"hash": "e40a5dfb3d017ba8779faba30cbd1c8e",
|
||||
"description": "Kickstart v3.1 rev 40.063",
|
||||
"filename": "kick40063.A600"
|
||||
},
|
||||
{
|
||||
"hash": "646773759326fbac3b2311fd8c8793ee",
|
||||
"description": "Kickstart v3.1 rev 40.068",
|
||||
"filename": "kick40068.A1200"
|
||||
},
|
||||
{
|
||||
"hash": "9bdedde6a4f33555b4a270c8ca53297d",
|
||||
"description": "Kickstart v3.1 rev 40.068",
|
||||
"filename": "kick40068.A4000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"igdbId": 25,
|
||||
"igdbName": "Amstrad CPC",
|
||||
@@ -543,6 +628,48 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"igdbId": 68,
|
||||
"igdbName": "ColecoVision",
|
||||
"igdbSlug": "colecovision",
|
||||
"alternateNames": [
|
||||
"ColecoVision"
|
||||
],
|
||||
"extensions": {
|
||||
"supportedFileExtensions": [
|
||||
".BIN",
|
||||
".COL",
|
||||
".ROM",
|
||||
".ZIP"
|
||||
],
|
||||
"uniqueFileExtensions": [
|
||||
]
|
||||
},
|
||||
"retroPieDirectoryName": "coleco",
|
||||
"webEmulator": {
|
||||
"type": "EmulatorJS",
|
||||
"core": "coleco",
|
||||
"availableWebEmulators": [
|
||||
{
|
||||
"emulatorType": "EmulatorJS",
|
||||
"availableWebEmulatorCores": [
|
||||
{
|
||||
"core": "coleco",
|
||||
"alternateCoreName": "coleco",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"bios": [
|
||||
{
|
||||
"hash": "2c66f5911e5b42b8ebe113403548eee7",
|
||||
"description": "ColecoVision BIOS - Mandatory",
|
||||
"filename": "colecovision.rom"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"igdbId": 15,
|
||||
"igdbName": "Commodore C64/128/MAX",
|
||||
@@ -620,6 +747,92 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"igdbId": 158,
|
||||
"igdbName": "Commodore CDTV",
|
||||
"igdbSlug": "commodore-cdtv",
|
||||
"alternateNames": [
|
||||
"Commodore CDTV",
|
||||
"Amiga CDTV",
|
||||
"Commodore Amiga CDTV"
|
||||
],
|
||||
"extensions": {
|
||||
"supportedFileExtensions": [
|
||||
".ZIP"
|
||||
],
|
||||
"uniqueFileExtensions": [
|
||||
]
|
||||
},
|
||||
"retroPieDirectoryName": "amiga",
|
||||
"webEmulator": {
|
||||
"type": "EmulatorJS",
|
||||
"core": "amiga",
|
||||
"availableWebEmulators": [
|
||||
{
|
||||
"emulatorType": "EmulatorJS",
|
||||
"availableWebEmulatorCores": [
|
||||
{
|
||||
"core": "amiga",
|
||||
"alternateCoreName": "puae",
|
||||
"default": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"bios": [
|
||||
{
|
||||
"hash": "85ad74194e87c08904327de1a9443b7a",
|
||||
"description": "Kickstart v1.2 rev 33.180",
|
||||
"filename": "kick33180.A500"
|
||||
},
|
||||
{
|
||||
"hash": "82a21c1890cae844b3df741f2762d48d",
|
||||
"description": "Kickstart v1.3 rev 34.005",
|
||||
"filename": "kick34005.A500"
|
||||
},
|
||||
{
|
||||
"hash": "89da1838a24460e4b93f4f0c5d92d48d",
|
||||
"description": "CDTV extended ROM v1.00",
|
||||
"filename": "kick34005.CDTV"
|
||||
},
|
||||
{
|
||||
"hash": "dc10d7bdd1b6f450773dfb558477c230",
|
||||
"description": "Kickstart v2.04 rev 37.175",
|
||||
"filename": "kick37175.A500"
|
||||
},
|
||||
{
|
||||
"hash": "5f8924d013dd57a89cf349f4cdedc6b1",
|
||||
"description": "CD32 Kickstart v3.1 rev 40.060",
|
||||
"filename": "kick40060.CD32"
|
||||
},
|
||||
{
|
||||
"hash": "f2f241bf094168cfb9e7805dc2856433",
|
||||
"description": "CD32 KS + extended v3.1 rev 40.060",
|
||||
"filename": "kick40060.CD32"
|
||||
},
|
||||
{
|
||||
"hash": "bb72565701b1b6faece07d68ea5da639",
|
||||
"description": "CD32 extended ROM rev 40.060",
|
||||
"filename": "kick40060.CD32.ext"
|
||||
},
|
||||
{
|
||||
"hash": "e40a5dfb3d017ba8779faba30cbd1c8e",
|
||||
"description": "Kickstart v3.1 rev 40.063",
|
||||
"filename": "kick40063.A600"
|
||||
},
|
||||
{
|
||||
"hash": "646773759326fbac3b2311fd8c8793ee",
|
||||
"description": "Kickstart v3.1 rev 40.068",
|
||||
"filename": "kick40068.A1200"
|
||||
},
|
||||
{
|
||||
"hash": "9bdedde6a4f33555b4a270c8ca53297d",
|
||||
"description": "Kickstart v3.1 rev 40.068",
|
||||
"filename": "kick40068.A4000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"igdbId": 33,
|
||||
"igdbName": "Game Boy",
|
||||
|
@@ -20,11 +20,15 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="gaseous-signature-parser" Version="2.0.0" />
|
||||
<PackageReference Include="gaseous.IGDB" Version="1.0.1" />
|
||||
<PackageReference Include="hasheous-client" Version="0.1.0" />
|
||||
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="7.0.13" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.12" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="sharpcompress" Version="0.35.0" />
|
||||
<PackageReference Include="Squid-Box.SevenZipSharp" Version="1.6.1.23" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.10" />
|
||||
<PackageReference Include="MySqlConnector" Version="2.3.1" />
|
||||
@@ -52,60 +56,10 @@
|
||||
<None Remove="Support\Database\MySQL\gaseous-1009.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1010.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1011.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1012.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1013.sql" />
|
||||
<None Remove="Support\Database\MySQL\gaseous-1014.sql" />
|
||||
<None Remove="Classes\Metadata\" />
|
||||
<None Remove="Assets\" />
|
||||
<None Remove="Assets\Ratings\" />
|
||||
<None Remove="Assets\Ratings\ESRB\" />
|
||||
<None Remove="Assets\Ratings\ACB\" />
|
||||
<None Remove="Assets\Ratings\PEGI\" />
|
||||
<None Remove="Assets\Ratings\ESRB\AO.svg" />
|
||||
<None Remove="Assets\Ratings\ESRB\E.svg" />
|
||||
<None Remove="Assets\Ratings\ESRB\E10plus.svg" />
|
||||
<None Remove="Assets\Ratings\ESRB\M.svg" />
|
||||
<None Remove="Assets\Ratings\ESRB\RP.svg" />
|
||||
<None Remove="Assets\Ratings\ESRB\RP-LM17-English.svg" />
|
||||
<None Remove="Assets\Ratings\ESRB\T.svg" />
|
||||
<None Remove="Assets\Ratings\CERO\" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_A.png" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_B.png" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_C.png" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_D.png" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_Z.png" />
|
||||
<None Remove="Assets\Ratings\USK\" />
|
||||
<None Remove="Assets\Ratings\USK\USK_0.svg" />
|
||||
<None Remove="Assets\Ratings\USK\USK_12.svg" />
|
||||
<None Remove="Assets\Ratings\USK\USK_16.svg" />
|
||||
<None Remove="Assets\Ratings\USK\USK_18.svg" />
|
||||
<None Remove="Assets\Ratings\USK\USK_6.svg" />
|
||||
<None Remove="Assets\Ratings\ACB\ACB_G.svg" />
|
||||
<None Remove="Assets\Ratings\ACB\ACB_M.svg" />
|
||||
<None Remove="Assets\Ratings\ACB\ACB_MA15.svg" />
|
||||
<None Remove="Assets\Ratings\ACB\ACB_PG.svg" />
|
||||
<None Remove="Assets\Ratings\ACB\ACB_R18.svg" />
|
||||
<None Remove="Assets\Ratings\ACB\ACB_RC.svg" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_A.svg" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_B.svg" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_C.svg" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_D.svg" />
|
||||
<None Remove="Assets\Ratings\CERO\CERO_Z.svg" />
|
||||
<None Remove="Assets\Ratings\PEGI\Eighteen.svg" />
|
||||
<None Remove="Assets\Ratings\PEGI\Seven.svg" />
|
||||
<None Remove="Assets\Ratings\PEGI\Sixteen.svg" />
|
||||
<None Remove="Assets\Ratings\PEGI\Three.svg" />
|
||||
<None Remove="Assets\Ratings\PEGI\Twelve.svg" />
|
||||
<None Remove="Assets\Ratings\GRAC\" />
|
||||
<None Remove="Assets\Ratings\GRAC\GRAC_All.svg" />
|
||||
<None Remove="Assets\Ratings\GRAC\GRAC_Eighteen.svg" />
|
||||
<None Remove="Assets\Ratings\GRAC\GRAC_Fifteen.svg" />
|
||||
<None Remove="Assets\Ratings\GRAC\GRAC_Testing.svg" />
|
||||
<None Remove="Assets\Ratings\GRAC\GRAC_Twelve.svg" />
|
||||
<None Remove="Assets\Ratings\CLASS_IND\" />
|
||||
<None Remove="Assets\Ratings\CLASS_IND\CLASS_IND_Eighteen.svg" />
|
||||
<None Remove="Assets\Ratings\CLASS_IND\CLASS_IND_Fourteen.svg" />
|
||||
<None Remove="Assets\Ratings\CLASS_IND\CLASS_IND_L.svg" />
|
||||
<None Remove="Assets\Ratings\CLASS_IND\CLASS_IND_Sixteen.svg" />
|
||||
<None Remove="Assets\Ratings\CLASS_IND\CLASS_IND_Ten.svg" />
|
||||
<None Remove="Assets\Ratings\CLASS_IND\CLASS_IND_Twelve.svg" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Controllers\" />
|
||||
@@ -114,15 +68,6 @@
|
||||
<Folder Include="Classes\SignatureIngestors\" />
|
||||
<Folder Include="Support\" />
|
||||
<Folder Include="Classes\Metadata\" />
|
||||
<Folder Include="Assets\" />
|
||||
<Folder Include="Assets\Ratings\" />
|
||||
<Folder Include="Assets\Ratings\ESRB\" />
|
||||
<Folder Include="Assets\Ratings\ACB\" />
|
||||
<Folder Include="Assets\Ratings\PEGI\" />
|
||||
<Folder Include="Assets\Ratings\CERO\" />
|
||||
<Folder Include="Assets\Ratings\USK\" />
|
||||
<Folder Include="Assets\Ratings\GRAC\" />
|
||||
<Folder Include="Assets\Ratings\CLASS_IND\" />
|
||||
<Folder Remove="Reference" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -135,45 +80,6 @@
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Assets\Ratings\ESRB\AO.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ESRB\E.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ESRB\E10.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ESRB\M.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ESRB\RP.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ESRB\RP-LM17-English.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ESRB\T.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\USK\USK_0.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\USK\USK_12.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\USK\USK_16.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\USK\USK_18.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\USK\USK_6.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ACB\ACB_G.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ACB\ACB_M.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ACB\ACB_MA15.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ACB\ACB_PG.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ACB\ACB_R18.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\ACB\ACB_RC.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CERO\CERO_A.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CERO\CERO_B.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CERO\CERO_C.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CERO\CERO_D.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CERO\CERO_Z.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\PEGI\Eighteen.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\PEGI\Seven.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\PEGI\Sixteen.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\PEGI\Three.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\PEGI\Twelve.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\GRAC\GRAC_All.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\GRAC\GRAC_Eighteen.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\GRAC\GRAC_Fifteen.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\GRAC\GRAC_Testing.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\GRAC\GRAC_Twelve.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CLASS_IND\CLASS_IND_Eighteen.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CLASS_IND\CLASS_IND_Fourteen.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CLASS_IND\CLASS_IND_L.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CLASS_IND\CLASS_IND_Sixteen.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CLASS_IND\CLASS_IND_Ten.svg" />
|
||||
<EmbeddedResource Include="Assets\Ratings\CLASS_IND\CLASS_IND_Twelve.svg" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1000.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1001.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1002.sql" />
|
||||
@@ -186,5 +92,8 @@
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1009.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1010.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1011.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1012.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1013.sql" />
|
||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1014.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -1,4 +1,5 @@
|
||||
<div style='width:640px;height:480px;max-width:100%'>
|
||||
<!-- <div style='width:640px;height:480px;max-width:100%'> -->
|
||||
<div style='width:100%;height:100%;'>
|
||||
<div id='game'></div>
|
||||
</div>
|
||||
|
||||
@@ -28,5 +29,7 @@
|
||||
EJS_backgroundBlur = true;
|
||||
|
||||
EJS_gameName = emuGameTitle;
|
||||
|
||||
EJS_threads = false;
|
||||
</script>
|
||||
<script src='/emulators/EmulatorJS/data/loader.js'></script>
|
@@ -42,15 +42,18 @@
|
||||
var statusText = result[i].buildStatus;
|
||||
var downloadLink = '';
|
||||
var packageSize = '-';
|
||||
var inProgress = false;
|
||||
switch (result[i].buildStatus) {
|
||||
case 'NoStatus':
|
||||
statusText = '-';
|
||||
break;
|
||||
case "WaitingForBuild":
|
||||
statusText = 'Build pending';
|
||||
inProgress = true;
|
||||
break;
|
||||
case "Building":
|
||||
statusText = 'Building';
|
||||
inProgress = true;
|
||||
break;
|
||||
case "Completed":
|
||||
statusText = 'Available';
|
||||
@@ -65,6 +68,10 @@
|
||||
break;
|
||||
}
|
||||
|
||||
if (inProgress == true) {
|
||||
setTimeout(GetCollections, 10000);
|
||||
}
|
||||
|
||||
var editButton = '';
|
||||
var deleteButton = '';
|
||||
|
||||
|
@@ -97,6 +97,18 @@
|
||||
BIOS files for each platform will be stored in /BIOS
|
||||
</td>
|
||||
</tr>
|
||||
<!-- <tr>
|
||||
<th>
|
||||
Archive format
|
||||
</th>
|
||||
<td>
|
||||
<select id="collection_archiveformat" style="width: 100%;">
|
||||
<option id="collection_archiveformat_zip" selected="selected" value="Zip">Zip</option>
|
||||
<option id="collection_archiveformat_rar" value="RAR">RAR</option>
|
||||
<option id="collection_archiveformat_7z" value="SevenZip">7z</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr> -->
|
||||
</table>
|
||||
</div>
|
||||
<table style="position: absolute; top: 0px; right: 0px; bottom: 0px; width: 60%;">
|
||||
@@ -480,7 +492,7 @@
|
||||
}
|
||||
|
||||
function DisplayPreview(data, targetDiv) {
|
||||
console.log(JSON.stringify(data));
|
||||
console.log(data);
|
||||
var container = document.getElementById(targetDiv);
|
||||
container.innerHTML = '';
|
||||
|
||||
@@ -579,7 +591,7 @@
|
||||
var gameImage = document.createElement('img');
|
||||
gameImage.className = 'game_tile_image game_tile_image_small';
|
||||
if (gameItem.cover) {
|
||||
gameImage.src = '/api/v1.1/Games/' + gameItem.id + '/cover/image';
|
||||
gameImage.src = '/api/v1.1/Games/' + gameItem.id + '/cover/image/cover_small/' + gameItem.coverItem.imageId + '.jpg';
|
||||
} else {
|
||||
gameImage.src = '/images/unknowngame.png';
|
||||
gameImage.className = 'game_tile_image game_tile_image_small unknown';
|
||||
|
@@ -16,10 +16,12 @@
|
||||
'DELETE',
|
||||
function (result) {
|
||||
loadRoms();
|
||||
loadMediaGroups();
|
||||
closeSubDialog();
|
||||
},
|
||||
function (error) {
|
||||
loadRoms();
|
||||
loadMediaGroups();
|
||||
closeSubDialog();
|
||||
}
|
||||
);
|
||||
|
@@ -31,7 +31,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><strong>Note</strong>: Standard directory naming uses the IGDB slug for the platform is not editable.</td>
|
||||
<td colspan="2"><strong>Note</strong>: Standard directory naming uses the IGDB slug for the platform and is not editable.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
@@ -58,7 +58,7 @@
|
||||
<h4>Engine</h4>
|
||||
</td>
|
||||
<td>
|
||||
<select id="mapping_edit_webemulatorengine" style="width: 100%;">
|
||||
<select id="mapping_edit_webemulatorengine" data-minimum-results-for-search="Infinity" style="width: 100%;">
|
||||
|
||||
</select>
|
||||
</td>
|
||||
@@ -68,7 +68,7 @@
|
||||
<h4>Core</h4>
|
||||
</td>
|
||||
<td>
|
||||
<select id="mapping_edit_webemulatorcore" style="width: 100%;">
|
||||
<select id="mapping_edit_webemulatorcore" data-minimum-results-for-search="Infinity" style="width: 100%;">
|
||||
|
||||
</select>
|
||||
</td>
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<div id="properties_toc">
|
||||
<div id="properties_toc_general" name="properties_toc_item" onclick="SelectTab('general');">General</div>
|
||||
<div id="properties_toc_attributes" name="properties_toc_item" onclick="SelectTab('attributes');">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>
|
||||
@@ -53,6 +54,10 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="properties_bodypanel_archive" name="properties_tab" style="display: none;">
|
||||
<div id="properties_bodypanel_archive_content" style="height: 315px; overflow-x: scroll;"></div>
|
||||
</div>
|
||||
|
||||
<div id="properties_bodypanel_attributes" name="properties_tab" style="display: none;">
|
||||
|
||||
</div>
|
||||
@@ -120,7 +125,6 @@
|
||||
|
||||
ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables, 'GET', function (result) {
|
||||
romData = result;
|
||||
console.log(romData);
|
||||
document.getElementById('modal-heading').innerHTML = result.name;
|
||||
document.getElementById('rominfo_library').innerHTML = result.library.name;
|
||||
document.getElementById('rominfo_platform').innerHTML = result.platform;
|
||||
@@ -128,9 +132,9 @@
|
||||
document.getElementById('rominfo_type').innerHTML = getRomType(result.romType);
|
||||
document.getElementById('rominfo_mediatype').innerHTML = result.romTypeMedia;
|
||||
document.getElementById('rominfo_medialabel').innerHTML = result.mediaLabel;
|
||||
document.getElementById('rominfo_md5').innerHTML = result.mD5;
|
||||
document.getElementById('rominfo_sha1').innerHTML = result.shA1;
|
||||
document.getElementById('rominfo_signaturematch').innerHTML = result.source;
|
||||
document.getElementById('rominfo_md5').innerHTML = result.md5;
|
||||
document.getElementById('rominfo_sha1').innerHTML = result.sha1;
|
||||
document.getElementById('rominfo_signaturematch').innerHTML = result.signatureSource;
|
||||
document.getElementById('rominfo_signaturetitle').innerHTML = result.signatureSourceGameTitle;
|
||||
|
||||
document.getElementById('properties_fixplatform').innerHTML = "<option value='" + result.platformId + "' selected='selected'>" + result.platform + "</option>";
|
||||
@@ -142,8 +146,7 @@
|
||||
|
||||
if (result.attributes.length > 0) {
|
||||
document.getElementById('properties_bodypanel_attributes').appendChild(BuildAttributesTable(result.attributes, result.source));
|
||||
} else {
|
||||
document.getElementById('properties_toc_attributes').style.display = 'none';
|
||||
document.getElementById('properties_bodypanel_archive_content').appendChild(BuildArchiveTable(result.attributes, result.source));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -199,12 +202,9 @@
|
||||
|
||||
$('#properties_fixplatform').on('select2:select', function (e) {
|
||||
var platformData = e.params.data;
|
||||
console.log(platformData);
|
||||
|
||||
var gameValue = $('#properties_fixgame').select2('data');
|
||||
if (gameValue) {
|
||||
console.log(gameValue[0]);
|
||||
|
||||
setFixGameDropDown();
|
||||
}
|
||||
});
|
||||
@@ -264,6 +264,9 @@
|
||||
aTable.style.width = '100%';
|
||||
|
||||
for (var i = 0; i < attributes.length; i++) {
|
||||
if (attributes[i].key != "ZipContents") {
|
||||
// show attributes button
|
||||
document.getElementById('properties_toc_attributes').style.display = '';
|
||||
var aRow = document.createElement('tr');
|
||||
|
||||
var aTitleCell = document.createElement('th');
|
||||
@@ -282,6 +285,55 @@
|
||||
|
||||
aTable.appendChild(aRow);
|
||||
}
|
||||
}
|
||||
|
||||
return aTable;
|
||||
}
|
||||
|
||||
function BuildArchiveTable(attributes, sourceName) {
|
||||
for (var i = 0; i < attributes.length; i++) {
|
||||
if (attributes[i].key == "ZipContents") {
|
||||
var archiveContent = JSON.parse(attributes[i].value);
|
||||
|
||||
// show archive button
|
||||
document.getElementById('properties_toc_archive').style.display = '';
|
||||
|
||||
var aTable = document.createElement('table');
|
||||
aTable.className = 'romtable';
|
||||
aTable.setAttribute('cellspacing', 0);
|
||||
aTable.style.width = '100%';
|
||||
|
||||
for (var r = 0; r < archiveContent.length; r++) {
|
||||
var aBody = document.createElement('tbody');
|
||||
aBody.className = 'romrow';
|
||||
|
||||
var aRow = document.createElement('tr');
|
||||
|
||||
var aNameCell = document.createElement('th');
|
||||
aNameCell.className = 'romcell';
|
||||
aNameCell.innerHTML = archiveContent[r].FilePath + '/' + archiveContent[r].FileName;
|
||||
aRow.appendChild(aNameCell);
|
||||
|
||||
var aSizeCell = document.createElement('td');
|
||||
aSizeCell.className = 'romcell';
|
||||
aSizeCell.innerHTML = formatBytes(archiveContent[r].Size);
|
||||
aRow.appendChild(aSizeCell);
|
||||
|
||||
aBody.appendChild(aRow);
|
||||
|
||||
var hRow = document.createElement('tr');
|
||||
|
||||
var aHashCell = document.createElement('td');
|
||||
aHashCell.setAttribute('colspan', 2);
|
||||
aHashCell.style.paddingLeft = '20px';
|
||||
aHashCell.innerHTML = "MD5: " + archiveContent[r].MD5 + "<br />SHA1: " + archiveContent[r].SHA1;
|
||||
hRow.appendChild(aHashCell);
|
||||
aBody.appendChild(hRow);
|
||||
|
||||
aTable.appendChild(aBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return aTable;
|
||||
}
|
||||
|
@@ -208,7 +208,7 @@
|
||||
|
||||
for (var classBoard in classBoards) {
|
||||
for (var rating in classBoards[classBoard]) {
|
||||
ratingsValues += "<img src='/api/v1.1/Ratings/Images/" + classBoard + "/" + classBoards[classBoard][rating] + "/image.svg' class='rating_image_mini' />";
|
||||
ratingsValues += "<img src='/images/Ratings/" + classBoard + "/" + AgeRatingStrings[classBoards[classBoard][rating]] + ".svg' class='rating_image_mini' />";
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<select id="profile_pref-LibraryPagination" data-pref="LibraryPagination" onchange="SavePrefValue_Value(this);">
|
||||
<select id="profile_pref-LibraryPagination" data-pref="LibraryPagination" data-minimum-results-for-search="Infinity">
|
||||
<option value="paged">Paged</option>
|
||||
<option value="infinite">Infinite scrolling</option>
|
||||
</select>
|
||||
@@ -34,17 +34,17 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" id="profile_pref_LibraryShowGameTitle" data-pref="LibraryShowGameTitle" onchange="SavePrefValue_Checkbox(this);"><label for="profile_pref_LibraryShowGameTitle"> Show title</label>
|
||||
<input type="checkbox" id="profile_pref_LibraryShowGameTitle" data-pref="LibraryShowGameTitle"><label for="profile_pref_LibraryShowGameTitle"> Show title</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" id="profile_pref_LibraryShowGameRating" data-pref="LibraryShowGameRating" onchange="SavePrefValue_Checkbox(this);"><label for="profile_pref_LibraryShowGameRating"> Show rating</label>
|
||||
<input type="checkbox" id="profile_pref_LibraryShowGameRating" data-pref="LibraryShowGameRating"><label for="profile_pref_LibraryShowGameRating"> Show rating</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" id="profile_pref_LibraryShowGameClassification" data-pref="LibraryShowGameClassification" onchange="SavePrefValue_Checkbox(this);"><label for="profile_pref_LibraryShowGameClassification"> Show age classification badges</label>
|
||||
<input type="checkbox" id="profile_pref_LibraryShowGameClassification" data-pref="LibraryShowGameClassification"><label for="profile_pref_LibraryShowGameClassification"> Show age classification badges</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -55,7 +55,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<select id="profile_pref_LibraryPrimaryClassificationBadge" data-primary="primary" onchange="SavePrefValue_ClassBadge(this);">
|
||||
<select id="profile_pref_LibraryPrimaryClassificationBadge" data-primary="primary" data-minimum-results-for-search="Infinity" onchange="SavePrefValue_ClassBadge(this);">
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -64,13 +64,18 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<select id="profile_pref_LibraryFallbackClassificationBadge" onchange="SavePrefValue_ClassBadge(this);">
|
||||
<select id="profile_pref_LibraryFallbackClassificationBadge" onchange="SavePrefValue_ClassBadge(this);" data-minimum-results-for-search="Infinity">
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: right;">
|
||||
<button id="profile_pref_ok" value="OK" onclick="SavePrefs();">OK</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="properties_bodypanel_account" name="properties_profile_tab" style="display: none;">
|
||||
@@ -183,31 +188,53 @@
|
||||
}
|
||||
}
|
||||
|
||||
function SavePrefs() {
|
||||
var model = [];
|
||||
|
||||
model.push(SavePrefValue_Checkbox(document.getElementById('profile_pref_LibraryShowGameTitle')));
|
||||
model.push(SavePrefValue_Checkbox(document.getElementById('profile_pref_LibraryShowGameRating')));
|
||||
model.push(SavePrefValue_Checkbox(document.getElementById('profile_pref_LibraryShowGameClassification')));
|
||||
|
||||
|
||||
model.push(SavePrefValue_Value(document.getElementById('profile_pref-LibraryPagination')));
|
||||
|
||||
model.push(
|
||||
{
|
||||
"setting": "LibraryGameClassificationDisplayOrder",
|
||||
"value": JSON.stringify(SavePrefValue_ClassBadge(document.getElementById('profile_pref_LibraryPrimaryClassificationBadge')))
|
||||
}
|
||||
);
|
||||
|
||||
SetPreference_Batch(model);
|
||||
|
||||
if (getQueryString('page', 'string') == 'home' || getQueryString('page', 'string') == undefined) {
|
||||
executeFilter1_1(1);
|
||||
}
|
||||
|
||||
closeDialog();
|
||||
}
|
||||
|
||||
function SavePrefValue_Checkbox(e) {
|
||||
var ValueName = e.getAttribute("data-pref");
|
||||
SetPreference(ValueName, e.checked);
|
||||
|
||||
updateDisplay(ValueName, e.checked);
|
||||
|
||||
executeFilter1_1(1);
|
||||
return { "setting": ValueName, "value": e.checked.toString() };
|
||||
}
|
||||
|
||||
function SavePrefValue_Value(e) {
|
||||
var ValueName = e.getAttribute("data-pref");
|
||||
SetPreference(ValueName, e.value);
|
||||
|
||||
executeFilter1_1(1);
|
||||
return { "setting": ValueName, "value": e.value };
|
||||
}
|
||||
|
||||
function updateDisplay(ValueName, ValueSetting) {
|
||||
switch(ValueName) {
|
||||
case "LibraryShowGameClassification":
|
||||
var badgeSelector = document.getElementById("profile_pref_LibraryClassificationBadgeSelect");
|
||||
if (ValueSetting == true || ValueSetting == "true") {
|
||||
badgeSelector.style.display = '';
|
||||
} else {
|
||||
badgeSelector.style.display = 'none';
|
||||
}
|
||||
// var badgeSelector = document.getElementById("profile_pref_LibraryClassificationBadgeSelect");
|
||||
// if (ValueSetting == true || ValueSetting == "true") {
|
||||
// badgeSelector.style.display = '';
|
||||
// } else {
|
||||
// badgeSelector.style.display = 'none';
|
||||
// }
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -232,6 +259,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// save values
|
||||
var model = [];
|
||||
if (secondary.value == '-') {
|
||||
@@ -240,9 +268,7 @@
|
||||
model = [ primary.value, secondary.value ];
|
||||
}
|
||||
|
||||
SetPreference('LibraryGameClassificationDisplayOrder', JSON.stringify(model));
|
||||
|
||||
executeFilter1_1(1);
|
||||
return model;
|
||||
}
|
||||
|
||||
function checkPasswordsMatch() {
|
||||
@@ -320,4 +346,8 @@
|
||||
|
||||
ProfileSelectTab('general');
|
||||
GetPrefInitialValues();
|
||||
|
||||
$('#profile_pref-LibraryPagination').select2();
|
||||
$('#profile_pref_LibraryPrimaryClassificationBadge').select2();
|
||||
$('#profile_pref_LibraryFallbackClassificationBadge').select2();
|
||||
</script>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<div id="bgImage_Opacity"></div>
|
||||
</div>
|
||||
|
||||
<div id="emulator"></div>
|
||||
<div id="emulator" class="emulator_fullscreen"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gameId = getQueryString('gameid', 'int');
|
||||
@@ -27,12 +27,12 @@
|
||||
} else {
|
||||
if (result.cover) {
|
||||
var bg = document.getElementById('bgImage');
|
||||
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/cover/image"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/cover/image/original/' + result.cover.imageId + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
}
|
||||
}
|
||||
|
||||
if (result.cover) {
|
||||
emuBackground = '/api/v1.1/Games/' + gameId + '/cover/image';
|
||||
emuBackground = '/api/v1.1/Games/' + gameId + '/cover/image/original/' + result.cover.imageId + '.jpg';
|
||||
}
|
||||
|
||||
emuGameTitle = gameData.name;
|
||||
@@ -59,7 +59,7 @@
|
||||
artworksPosition = 0;
|
||||
}
|
||||
var bg = document.getElementById('bgImage');
|
||||
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/artwork/' + artworks[artworksPosition] + '/image"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/artwork/' + artworks[artworksPosition] + '/image/original/' + artworks[artworksPosition] + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -52,7 +52,7 @@
|
||||
|
||||
<div id="loginwindow_header_label" style="display: block; text-align: center;">Gaseous Games</div>
|
||||
|
||||
<button type="button" value="Get Started" onclick="document.getElementById('first_welcome').style.display = 'none'; document.getElementById('first_newadmin').style.display = '';" style="margin-top: 50px; width: 100%; font-size: 16px; border-radius: 10px; padding-top: 10px; padding-bottom: 10px;">Get Started</button>
|
||||
<button type="button" value="Get Started" onclick="document.getElementById('first_welcome').style.display = 'none'; document.getElementById('first_newadmin').style.display = '';" class="bigbutton">Get Started</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="loginwindow" id="first_newadmin" style="display: none;">
|
||||
@@ -85,7 +85,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="padding-top: 20px;">
|
||||
<button id="login_createaccount" type="button" value="Create Account" onclick="registerAccount();" disabled="disabled" style="margin-top: 10px; width: 100%; font-size: 16px; border-radius: 10px; padding-top: 10px; padding-bottom: 10px;">Create Account</button>
|
||||
<button id="login_createaccount" type="button" value="Create Account" onclick="registerAccount();" disabled="disabled" class="bigbutton">Create Account</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@@ -71,6 +71,7 @@
|
||||
</div>
|
||||
<div id="gamesummarymediagroups" style="display: none;">
|
||||
<h3>Media Groups</h3>
|
||||
<div id="gamesummarymediagroupscontent"></div>
|
||||
</div>
|
||||
<div id="gamesummaryroms">
|
||||
<span id="rom_edit" class="romlink" onclick="DisplayROMCheckboxes(true);">Edit</span>
|
||||
@@ -85,6 +86,21 @@
|
||||
<button id="rom_edit_creategroup" onclick="createMgGroup();" disabled="disabled">Create Media Group</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="games_library_controls">
|
||||
<div class="games_library_controlblock">
|
||||
<input id="name_filter" type="text" placeholder="Name Search">
|
||||
</div>
|
||||
<div class="games_library_controlblock">
|
||||
<select id="platform_filter"></select>
|
||||
</div>
|
||||
<div class="games_library_controlblock">
|
||||
<button value="Search" onclick="loadRoms();">Search</button>
|
||||
</div>
|
||||
<div class="games_library_controlblock">
|
||||
<span class="games_library_label">0 ROMs</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="gamesummaryromscontent"></div>
|
||||
</div>
|
||||
<div id="gamesummarysimilar" style="display: none;">
|
||||
<h3>Similar Games</h3>
|
||||
@@ -102,6 +118,8 @@
|
||||
var selectedScreenshot = 0;
|
||||
|
||||
ajaxCall('/api/v1.1/Games/' + gameId, 'GET', function (result) {
|
||||
console.log(result);
|
||||
|
||||
// populate games page
|
||||
gameData = result;
|
||||
|
||||
@@ -142,9 +160,9 @@
|
||||
var gameSummaryLabel = document.getElementById('gamesummarytext_label');
|
||||
if (result.summary || result.storyline) {
|
||||
if (result.summary) {
|
||||
gameSummaryLabel.innerHTML = result.summary;
|
||||
gameSummaryLabel.innerHTML = result.summary.replaceAll("\n", "<br />");
|
||||
} else {
|
||||
gameSummaryLabel.innerHTML = result.storyline;
|
||||
gameSummaryLabel.innerHTML = result.storyline.replaceAll("\n", "<br />");
|
||||
}
|
||||
|
||||
if (gameSummaryLabel.offsetHeight < gameSummaryLabel.scrollHeight ||
|
||||
@@ -159,21 +177,30 @@
|
||||
gameSummaryLabel.setAttribute('style', 'display: none;');
|
||||
}
|
||||
|
||||
// load artwork
|
||||
if (result.artworks) {
|
||||
artworks = result.artworks.ids;
|
||||
var startPos = randomIntFromInterval(0, result.artworks.ids.length);
|
||||
artworksPosition = startPos;
|
||||
rotateBackground();
|
||||
} else {
|
||||
var bg = document.getElementById('bgImage');
|
||||
// load cover
|
||||
var gameSummaryCover = document.getElementById('gamesummary_cover');
|
||||
var gameImage = document.createElement('img');
|
||||
gameImage.className = 'game_cover_image';
|
||||
if (result.cover) {
|
||||
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/cover/image"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
ajaxCall('/api/v1.1/games/' + gameId + '/cover', 'GET', function (coverResult) {
|
||||
if (coverResult) {
|
||||
gameImage.src = '/api/v1.1/Games/' + gameId + '/cover/image/cover_big/' + coverResult.imageId + '.jpg';
|
||||
|
||||
loadArtwork(result, coverResult);
|
||||
} else {
|
||||
var randomInt = randomIntFromInterval(1, 3);
|
||||
bg.setAttribute('style', 'background-image: url("/images/gamebg' + randomInt + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
gameImage.src = '/images/unknowngame.png';
|
||||
gameImage.className = 'game_cover_image unknown';
|
||||
|
||||
loadArtwork(result);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
gameImage.src = '/images/unknowngame.png';
|
||||
gameImage.className = 'game_cover_image unknown';
|
||||
|
||||
loadArtwork(result);
|
||||
}
|
||||
gameSummaryCover.appendChild(gameImage);
|
||||
|
||||
// load companies
|
||||
var gameHeaderDeveloperLabel = document.getElementById('gamedeveloper_label');
|
||||
@@ -229,18 +256,6 @@
|
||||
gamePublisherLabel.setAttribute('style', 'display: none;');
|
||||
}
|
||||
|
||||
// load cover
|
||||
var gameSummaryCover = document.getElementById('gamesummary_cover');
|
||||
var gameImage = document.createElement('img');
|
||||
gameImage.className = 'game_cover_image';
|
||||
if (result.cover) {
|
||||
gameImage.src = '/api/v1.1/Games/' + result.id + '/cover/image';
|
||||
} else {
|
||||
gameImage.src = '/images/unknowngame.png';
|
||||
gameImage.className = 'game_cover_image unknown';
|
||||
}
|
||||
gameSummaryCover.appendChild(gameImage);
|
||||
|
||||
// load release date
|
||||
var gameSummaryRelease = document.getElementById('gamesummary_firstrelease');
|
||||
if (result.firstReleaseDate) {
|
||||
@@ -254,14 +269,44 @@
|
||||
// load ratings
|
||||
var gameSummaryRatings = document.getElementById('gamesummary_ratings');
|
||||
if (result.ageRatings) {
|
||||
var gameRatings = document.createElement('div');
|
||||
for (var i = 0; i < result.ageRatings.ids.length; i++) {
|
||||
ajaxCall('/api/v1.1/games/' + gameId + '/agerating', 'GET', function (result) {
|
||||
var classTable = document.createElement('table');
|
||||
var gameRatingsSml = document.createElement('div');
|
||||
|
||||
var SpotlightClassifications = GetPreference("LibraryGameClassificationDisplayOrder", JSON.stringify([ "ESRB" ]));
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var ratingImage = document.createElement('img');
|
||||
ratingImage.src = '/api/v1.1/Games/' + result.id + '/agerating/' + result.ageRatings.ids[i] + '/image';
|
||||
ratingImage.className = 'rating_image';
|
||||
gameRatings.appendChild(ratingImage);
|
||||
ratingImage.src = '/images/Ratings/' + result[i].ratingBoard + '/' + result[i].ratingTitle + '.svg';
|
||||
var ratingString = ClassificationBoards[result[i].ratingBoard] + "\nRating: " + ClassificationRatings[result[i].ratingTitle];
|
||||
if (result[i].descriptions.length > 0) {
|
||||
ratingString += '\nContains: ' + result[i].descriptions.join(', ');
|
||||
}
|
||||
gameSummaryRatings.appendChild(gameRatings);
|
||||
ratingImage.title = ratingString;
|
||||
if (SpotlightClassifications.includes(result[i].ratingBoard)) {
|
||||
ratingImage.className = 'rating_image';
|
||||
|
||||
var classTableRow = document.createElement('tr');
|
||||
var classTableLogo = document.createElement('td');
|
||||
classTableLogo.className = 'rating_image_logo_table';
|
||||
classTableLogo.appendChild(ratingImage);
|
||||
classTableRow.appendChild(classTableLogo);
|
||||
var classTableDescription = document.createElement('td');
|
||||
if (result[i].descriptions.length > 0) {
|
||||
classTableDescription.innerHTML = result[i].descriptions.join('<br />');
|
||||
} else {
|
||||
classTableDescription.innerHTML = ClassificationRatings[result[i].ratingTitle];
|
||||
}
|
||||
classTableRow.appendChild(classTableDescription);
|
||||
classTable.appendChild(classTableRow);
|
||||
} else {
|
||||
ratingImage.className = 'rating_image rating_image_mini';
|
||||
gameRatingsSml.appendChild(ratingImage);
|
||||
}
|
||||
}
|
||||
gameSummaryRatings.appendChild(classTable);
|
||||
gameSummaryRatings.appendChild(gameRatingsSml);
|
||||
});
|
||||
} else {
|
||||
gameSummaryRatings.setAttribute('style', 'display: none;');
|
||||
}
|
||||
@@ -282,6 +327,34 @@
|
||||
gameSummaryGenres.setAttribute('style', 'display: none;');
|
||||
}
|
||||
|
||||
// get platforms
|
||||
var platformFilter = document.getElementById('platform_filter');
|
||||
platformFilter.style.width = "200px";
|
||||
$(platformFilter).select2({
|
||||
minimumResultsForSearch: Infinity
|
||||
});
|
||||
ajaxCall('/api/v1.1/Games/' + gameId + '/platforms', 'GET', function (result) {
|
||||
// add default option
|
||||
var platformFilter_default = document.createElement('option');
|
||||
platformFilter_default.value = "-1";
|
||||
platformFilter_default.innerHTML = "All Platforms";
|
||||
platformFilter_default.selected = "selected";
|
||||
platformFilter.appendChild(platformFilter_default);
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var platformFilter_opt = document.createElement('option');
|
||||
platformFilter_opt.value = result[i].key;
|
||||
platformFilter_opt.innerHTML = result[i].value;
|
||||
platformFilter.appendChild(platformFilter_opt);
|
||||
}
|
||||
|
||||
// load media groups
|
||||
loadMediaGroups();
|
||||
|
||||
// load roms
|
||||
loadRoms(false, 1);
|
||||
});
|
||||
|
||||
// load screenshots
|
||||
var gameScreenshots = document.getElementById('gamescreenshots');
|
||||
if (result.screenshots || result.videos) {
|
||||
@@ -294,11 +367,12 @@
|
||||
imageIndex = result.videos.ids.length;
|
||||
}
|
||||
if (result.screenshots) {
|
||||
for (var i = 0; i < result.screenshots.ids.length; i++) {
|
||||
ajaxCall('/api/v1.1/Games/' + gameId + '/screenshots', 'GET', function (screenshotsItem) {
|
||||
for (var i = 0; i < screenshotsItem.length; i++) {
|
||||
var screenshotItem = document.createElement('div');
|
||||
screenshotItem.id = 'gamescreenshots_gallery_' + imageIndex;
|
||||
screenshotItem.setAttribute('name', 'gamescreenshots_gallery_item');
|
||||
screenshotItem.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/screenshots/' + result.screenshots.ids[i] + '/image"); background-position: center; background-repeat: no-repeat; background-size: contain;)');
|
||||
screenshotItem.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/screenshots/' + screenshotsItem[i].id + '/image/screenshot_thumb/' + screenshotsItem[i].imageId + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: contain;)');
|
||||
screenshotItem.setAttribute('imageid', imageIndex);
|
||||
screenshotItem.setAttribute('imagetype', 0);
|
||||
screenshotItem.className = 'gamescreenshots_gallery_item';
|
||||
@@ -306,6 +380,9 @@
|
||||
gameScreenshots_Gallery.appendChild(screenshotItem);
|
||||
imageIndex += 1;
|
||||
}
|
||||
|
||||
selectScreenshot(0);
|
||||
});
|
||||
}
|
||||
|
||||
// load videos
|
||||
@@ -355,7 +432,7 @@
|
||||
selectScreenshot(0);
|
||||
});
|
||||
} else {
|
||||
selectScreenshot(0);
|
||||
//selectScreenshot(0);
|
||||
}
|
||||
} else {
|
||||
gamescreenshots.setAttribute('style', 'display: none;');
|
||||
@@ -382,25 +459,123 @@
|
||||
gameSummarySimilar.setAttribute('style', 'display: none;');
|
||||
}
|
||||
});
|
||||
|
||||
// load roms
|
||||
loadRoms(false);
|
||||
});
|
||||
|
||||
function loadRoms(displayCheckboxes, pageNumber, selectedPlatform) {
|
||||
function loadMediaGroups() {
|
||||
ajaxCall('/api/v1.1/Games/' + gameId + '/romgroup', 'GET', function (result) {
|
||||
// display media groups
|
||||
var mediaGroup = document.getElementById('gamesummarymediagroups');
|
||||
var mediaGroupDiv = document.getElementById('gamesummarymediagroupscontent');
|
||||
if (result.length == 0) {
|
||||
mediaGroup.style.display = 'none';
|
||||
} else {
|
||||
console.log(result);
|
||||
mediaGroup.style.display = '';
|
||||
mediaGroupDiv.innerHTML = '';
|
||||
var mgTable = document.createElement('table');
|
||||
mgTable.id = 'mediagrouptable';
|
||||
mgTable.className = 'romtable';
|
||||
mgTable.setAttribute('cellspacing', 0);
|
||||
mgTable.appendChild(createTableRow(true, ['Platform', 'Images', 'Size', '', '', '']));
|
||||
|
||||
lastPlatform = '';
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var mediaGroup = result[i];
|
||||
|
||||
// get rom details including emulator and friendly platform name
|
||||
var launchButton = '';
|
||||
if (mediaGroup.emulator) {
|
||||
if (mediaGroup.emulator.type.length > 0) {
|
||||
launchButton = '<a href="/index.html?page=emulator&engine=' + mediaGroup.emulator.type + '&core=' + mediaGroup.emulator.core + '&platformid=' + mediaGroup.platformId + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1.1/Games/' + gameId + '/romgroup/' + mediaGroup.id + '/' + gameData.name + '(' + mediaGroup.id + ')' + '.zip') + '" class="romstart">Launch</a>';
|
||||
}
|
||||
}
|
||||
|
||||
var statusText = mediaGroup.status;
|
||||
var downloadLink = '';
|
||||
var packageSize = '-';
|
||||
var launchButtonContent = '';
|
||||
var inProgress = false;
|
||||
switch (mediaGroup.status) {
|
||||
case 'NoStatus':
|
||||
statusText = '-';
|
||||
break;
|
||||
case "WaitingForBuild":
|
||||
statusText = 'Build pending';
|
||||
inProgress = true;
|
||||
break;
|
||||
case "Building":
|
||||
statusText = 'Building';
|
||||
inProgress = true;
|
||||
break;
|
||||
case "Completed":
|
||||
statusText = 'Available';
|
||||
downloadLink = '<a href="/api/v1.1/Games/' + gameId + '/romgroup/' + mediaGroup.id + '/' + gameData.name + '.zip" class="romlink"><img src="/images/download.svg" class="banner_button_image" alt="Download" title="Download" /></a>';
|
||||
packageSize = formatBytes(mediaGroup.size);
|
||||
launchButtonContent = launchButton;
|
||||
break;
|
||||
case "Failed":
|
||||
statusText = 'Build error';
|
||||
break;
|
||||
default:
|
||||
statusText = result[i].buildStatus;
|
||||
break;
|
||||
}
|
||||
|
||||
if (inProgress == true) {
|
||||
setTimeout(loadMediaGroups, 10000);
|
||||
}
|
||||
|
||||
var deleteButton = '<a href="#" onclick="showSubDialog(\'mediagroupdelete\', ' + mediaGroup.id + ');" class="romlink"><img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" /></a>';
|
||||
|
||||
var newRow = [
|
||||
mediaGroup.platform,
|
||||
mediaGroup.romIds.length,
|
||||
packageSize,
|
||||
statusText,
|
||||
launchButtonContent,
|
||||
'<div style="text-align: right;">' + downloadLink + deleteButton + '</div>'
|
||||
]
|
||||
|
||||
mgTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
|
||||
|
||||
var mgRomRow = document.createElement('tr');
|
||||
var mgRomCell = document.createElement('td');
|
||||
mgRomCell.setAttribute('colspan', 6);
|
||||
mgRomCell.className = 'romGroupTitles';
|
||||
|
||||
|
||||
// iterate the group members
|
||||
var groupMembers = [];
|
||||
for (var r = 0; r < mediaGroup.roms.length; r++) {
|
||||
groupMembers.push(mediaGroup.roms[r]);
|
||||
}
|
||||
|
||||
groupMembers.sort((a, b) => (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0));
|
||||
var groupMemberNames = [];
|
||||
for (var r = 0; r < groupMembers.length; r++) {
|
||||
groupMemberNames.push(groupMembers[r].name);
|
||||
}
|
||||
mgRomCell.innerHTML = groupMemberNames.join("<br />");
|
||||
mgRomRow.appendChild(mgRomCell);
|
||||
mgTable.appendChild(mgRomRow);
|
||||
}
|
||||
|
||||
mediaGroupDiv.appendChild(mgTable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadRoms(displayCheckboxes, pageNumber) {
|
||||
if (!pageNumber) {
|
||||
pageNumber = 1;
|
||||
}
|
||||
|
||||
if (selectedPlatform == undefined) {
|
||||
selectedPlatform = -1;
|
||||
}
|
||||
selectedPlatform = $('#platform_filter').select2('data')[0].id;
|
||||
|
||||
console.log(selectedPlatform);
|
||||
|
||||
var filterControlBlock = document.getElementById('games_library_controls');
|
||||
if (filterControlBlock) {
|
||||
filterControlBlock.remove();
|
||||
var nameSearchQuery = '';
|
||||
var nameSearch = document.getElementById('name_filter').value;
|
||||
if (nameSearch != undefined && nameSearch != "") {
|
||||
nameSearchQuery = '&NameSearch=' + encodeURIComponent(nameSearch);
|
||||
}
|
||||
|
||||
var existingTable = document.getElementById('romtable');
|
||||
@@ -413,11 +588,6 @@
|
||||
romPager.remove();
|
||||
}
|
||||
|
||||
var existingMgTable = document.getElementById('mediagrouptable');
|
||||
if (existingMgTable) {
|
||||
existingMgTable.remove();
|
||||
}
|
||||
|
||||
if (displayCheckboxes == undefined) {
|
||||
if (document.getElementById('rom_edit_panel').style.display == 'none') {
|
||||
displayCheckboxes = false;
|
||||
@@ -426,50 +596,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
var gameRoms = document.getElementById('gamesummaryroms');
|
||||
var gameRomsSection = document.getElementById('gamesummaryroms');
|
||||
var gameRoms = document.getElementById('gamesummaryromscontent');
|
||||
var pageSize = 20;
|
||||
ajaxCall('/api/v1.1/Games/' + gameId + '/roms?pageNumber=' + pageNumber + '&pageSize=' + pageSize + '&platformId=' + selectedPlatform, 'GET', function (result) {
|
||||
// display filter tools
|
||||
var filterControls = document.createElement('div');
|
||||
filterControls.id = "games_library_controls";
|
||||
|
||||
var platformFilterBlock = document.createElement('div');
|
||||
platformFilterBlock.className = 'games_library_controlblock';
|
||||
|
||||
var platformFilterOpt = document.createElement('select');
|
||||
platformFilterOpt.id = "platform_filter";
|
||||
platformFilterOpt.setAttribute('onchange', 'loadRoms(' + undefined + ', ' + 1 + ', Number(document.getElementById("platform_filter").value));');
|
||||
|
||||
var platformFilterOptDefault = document.createElement('option');
|
||||
platformFilterOptDefault.value = '-1';
|
||||
platformFilterOptDefault.innerHTML = 'All Platforms';
|
||||
if (selectedPlatform == -1) {
|
||||
platformFilterOptDefault.selected = 'selected';
|
||||
}
|
||||
platformFilterOpt.appendChild(platformFilterOptDefault);
|
||||
|
||||
for (var i = 0; i < result.platforms.length; i++) {
|
||||
var platformFilterOptValue = document.createElement('option');
|
||||
platformFilterOptValue.value = result.platforms[i].key;
|
||||
platformFilterOptValue.innerHTML = result.platforms[i].value;
|
||||
if (selectedPlatform == Number(result.platforms[i].key)) {
|
||||
platformFilterOptValue.selected = 'selected';
|
||||
}
|
||||
platformFilterOpt.appendChild(platformFilterOptValue);
|
||||
}
|
||||
platformFilterBlock.appendChild(platformFilterOpt);
|
||||
filterControls.appendChild(platformFilterBlock);
|
||||
|
||||
var romCounter = document.createElement('div');
|
||||
romCounter.className = 'games_library_controlblock';
|
||||
romCounter.innerHTML = result.count + ' ROMs';
|
||||
filterControls.appendChild(romCounter);
|
||||
|
||||
gameRoms.appendChild(filterControls);
|
||||
|
||||
ajaxCall('/api/v1.1/Games/' + gameId + '/roms?pageNumber=' + pageNumber + '&pageSize=' + pageSize + '&platformId=' + selectedPlatform + nameSearchQuery, 'GET', function (result) {
|
||||
if (result.gameRomItems) {
|
||||
var gameRomItems = result.gameRomItems;
|
||||
var mediaGroups = result.mediaGroups;
|
||||
|
||||
// display roms
|
||||
var newTable = document.createElement('table');
|
||||
@@ -559,113 +691,39 @@
|
||||
romPaginator.appendChild(nextPage);
|
||||
|
||||
gameRoms.appendChild(romPaginator);
|
||||
}
|
||||
|
||||
// display media groups
|
||||
var mediaGroupDiv = document.getElementById('gamesummarymediagroups');
|
||||
if (mediaGroups.length == 0) {
|
||||
mediaGroupDiv.style.display = 'none';
|
||||
} else {
|
||||
mediaGroupDiv.style.display = '';
|
||||
var mgTable = document.createElement('table');
|
||||
mgTable.id = 'mediagrouptable';
|
||||
mgTable.className = 'romtable';
|
||||
mgTable.setAttribute('cellspacing', 0);
|
||||
mgTable.appendChild(createTableRow(true, ['Platform', 'Images', 'Size', '', '', '']));
|
||||
|
||||
lastPlatform = '';
|
||||
for (var i = 0; i < mediaGroups.length; i++) {
|
||||
var mediaGroup = mediaGroups[i];
|
||||
|
||||
// get rom details including emulator and friendly platform name
|
||||
var launchButton = '';
|
||||
for (var r = 0; r < gameRomItems.length; r++) {
|
||||
var gameRomItem = gameRomItems[r];
|
||||
if (gameRomItem.platformId == mediaGroup.platformId) {
|
||||
if (gameRomItem.emulator) {
|
||||
if (gameRomItem.emulator.type.length > 0) {
|
||||
launchButton = '<a href="/index.html?page=emulator&engine=' + gameRomItem.emulator.type + '&core=' + gameRomItem.emulator.core + '&platformid=' + gameRomItem.platform.id + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1.1/Games/' + gameId + '/romgroup/' + mediaGroup.id + '/' + gameData.name + '(' + mediaGroup.id + ')' + '.zip') + '" class="romstart">Launch</a>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var statusText = mediaGroup.status;
|
||||
var downloadLink = '';
|
||||
var packageSize = '-';
|
||||
var launchButtonContent = '';
|
||||
switch (mediaGroup.status) {
|
||||
case 'NoStatus':
|
||||
statusText = '-';
|
||||
break;
|
||||
case "WaitingForBuild":
|
||||
statusText = 'Build pending';
|
||||
break;
|
||||
case "Building":
|
||||
statusText = 'Building';
|
||||
break;
|
||||
case "Completed":
|
||||
statusText = 'Available';
|
||||
downloadLink = '<a href="/api/v1.1/Games/' + gameId + '/romgroup/' + mediaGroup.id + '/' + gameData.name + '.zip" class="romlink"><img src="/images/download.svg" class="banner_button_image" alt="Download" title="Download" /></a>';
|
||||
packageSize = formatBytes(mediaGroup.size);
|
||||
launchButtonContent = launchButton;
|
||||
break;
|
||||
case "Failed":
|
||||
statusText = 'Build error';
|
||||
break;
|
||||
default:
|
||||
statusText = result[i].buildStatus;
|
||||
break;
|
||||
}
|
||||
|
||||
var deleteButton = '<a href="#" onclick="showSubDialog(\'mediagroupdelete\', ' + mediaGroup.id + ');" class="romlink"><img src="/images/delete.svg" class="banner_button_image" alt="Delete" title="Delete" /></a>';
|
||||
|
||||
var newRow = [
|
||||
mediaGroup.platformName,
|
||||
mediaGroup.romIds.length,
|
||||
packageSize,
|
||||
statusText,
|
||||
launchButtonContent,
|
||||
'<div style="text-align: right;">' + downloadLink + deleteButton + '</div>'
|
||||
]
|
||||
|
||||
mgTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell'));
|
||||
|
||||
var mgRomRow = document.createElement('tr');
|
||||
var mgRomCell = document.createElement('td');
|
||||
mgRomCell.setAttribute('colspan', 6);
|
||||
mgRomCell.className = 'romGroupTitles';
|
||||
|
||||
// iterate the group members
|
||||
var groupMembers = [];
|
||||
for (var r = 0; r < mediaGroup.romIds.length; r++) {
|
||||
for (var x = 0; x < gameRomItems.length; x++) {
|
||||
if (mediaGroup.romIds[r] == gameRomItems[x].id) {
|
||||
groupMembers.push(gameRomItems[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
groupMembers.sort((a, b) => (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0));
|
||||
var groupMemberNames = [];
|
||||
for (var r = 0; r < groupMembers.length; r++) {
|
||||
groupMemberNames.push(groupMembers[r].name);
|
||||
}
|
||||
mgRomCell.innerHTML = groupMemberNames.join("<br />");
|
||||
|
||||
mgRomRow.appendChild(mgRomCell);
|
||||
mgTable.appendChild(mgRomRow);
|
||||
}
|
||||
|
||||
mediaGroupDiv.appendChild(mgTable);
|
||||
gameRomsSection.appendChild(gameRoms);
|
||||
}
|
||||
} else {
|
||||
gameRoms.setAttribute('style', 'display: none;');
|
||||
gameRomsSection.setAttribute('style', 'display: none;');
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function loadArtwork(game, cover) {
|
||||
// show default background
|
||||
var bg = document.getElementById('bgImage');
|
||||
if (cover) {
|
||||
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/cover/image/original/' + cover.imageId + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
} else {
|
||||
var randomInt = randomIntFromInterval(1, 3);
|
||||
bg.setAttribute('style', 'background-image: url("/images/gamebg' + randomInt + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
}
|
||||
|
||||
// // load artwork
|
||||
// if (game.artworks) {
|
||||
// ajaxCall('/api/v1.1/games/' + gameId + '/artwork', 'GET', function (result) {
|
||||
// artworks = result;
|
||||
// var startPos = randomIntFromInterval(0, result.length);
|
||||
// artworksPosition = startPos;
|
||||
// rotateBackground();
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
function rotateBackground() {
|
||||
if (artworks) {
|
||||
artworksPosition += 1;
|
||||
@@ -673,7 +731,7 @@
|
||||
artworksPosition = 0;
|
||||
}
|
||||
var bg = document.getElementById('bgImage');
|
||||
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/artwork/' + artworks[artworksPosition] + '/image"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/artwork/' + artworks[artworksPosition].id + '/image/original/' + artworks[artworksPosition].imageId + '.jpg"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
|
||||
artworksTimer = setTimeout(rotateBackground, 60000);
|
||||
}
|
||||
}
|
||||
@@ -697,8 +755,9 @@
|
||||
gameScreenshots_Main.innerHTML = '';
|
||||
switch (gameScreenshots_Selected.getAttribute('imagetype')) {
|
||||
case "0":
|
||||
default:
|
||||
// screenshot
|
||||
gameScreenshots_Main.setAttribute('style', gameScreenshots_Selected.getAttribute('style'));
|
||||
gameScreenshots_Main.setAttribute('style', gameScreenshots_Selected.getAttribute('style').replace("/image/screenshot_thumb", "/image/original"));
|
||||
break;
|
||||
case "1":
|
||||
// video
|
||||
@@ -1015,10 +1074,12 @@
|
||||
function (result) {
|
||||
DisplayROMCheckboxes(false);
|
||||
loadRoms();
|
||||
loadMediaGroups();
|
||||
},
|
||||
function (error) {
|
||||
DisplayROMCheckboxes(false);
|
||||
loadRoms();
|
||||
loadMediaGroups();
|
||||
},
|
||||
JSON.stringify(romIds)
|
||||
);
|
||||
|
@@ -3,25 +3,28 @@
|
||||
</div>
|
||||
|
||||
<div id="games_filter_scroller">
|
||||
<div id="games_filter"></div>
|
||||
</div>
|
||||
<div id="games_home">
|
||||
<div id="games_home_box">
|
||||
<div id="games_library_controls">
|
||||
<div id="games_library_orderby" class="games_library_controlblock">
|
||||
<span>Order by: </span>
|
||||
<select id="games_library_orderby_select" onchange="executeFilter1_1();">
|
||||
<div class="games_library_controlblock">
|
||||
<span class="games_library_label">Order by: </span>
|
||||
</div>
|
||||
<div id="games_library_orderby" class="games_library_controlblock" style="text-align: left;">
|
||||
<select id="games_library_orderby_select" data-minimum-results-for-search="Infinity" onchange="executeFilter1_1(1);">
|
||||
<option selected="selected" value="NameThe">Name, The</option>
|
||||
<option value="Name">Name</option>
|
||||
<option value="Rating">User Rating</option>
|
||||
<option value="RatingCount">User Rating Count</option>
|
||||
</select>
|
||||
<select id="games_library_orderby_direction_select" onchange="executeFilter1_1();">
|
||||
<select id="games_library_orderby_direction_select" data-minimum-results-for-search="Infinity" onchange="executeFilter1_1(1);">
|
||||
<option selected="selected" value="Ascending">Ascending</option>
|
||||
<option value="Descending">Descending</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="games_library_recordcount" class="games_library_controlblock"></div>
|
||||
<div class="games_library_controlblock">
|
||||
<span id="games_library_recordcount" class="games_library_label"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="games_library"></div>
|
||||
<div id="games_library_pagerstore" style="display: none;">0</div>
|
||||
@@ -34,9 +37,12 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
ajaxCall('/api/v1.1/Filter', 'GET', function (result) {
|
||||
var filterElement = document.getElementById('games_filter');
|
||||
formatFilterPanel(filterElement, result);
|
||||
var scrollerElement = document.getElementById('games_filter_scroller');
|
||||
formatFilterPanel(scrollerElement, result);
|
||||
|
||||
executeFilter1_1();
|
||||
});
|
||||
|
||||
$('#games_library_orderby_select').select2();
|
||||
$('#games_library_orderby_direction_select').select2();
|
||||
</script>
|
@@ -71,7 +71,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" style="padding-top: 20px;">
|
||||
<button type="button" value="Sign In" onclick="UserLogin();" style="margin-top: 10px; width: 100%; font-size: 16px; border-radius: 10px; padding-top: 10px; padding-bottom: 10px;">Sign In</button>
|
||||
<button type="button" value="Sign In" onclick="UserLogin();" class="bigbutton">Sign In</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@@ -149,7 +149,7 @@
|
||||
moment(result[i].eventTime).format("YYYY-MM-DD h:mm:ss a"),
|
||||
result[i].eventType,
|
||||
result[i].process,
|
||||
result[i].message
|
||||
result[i].message.replaceAll("\n", "<br />")
|
||||
];
|
||||
|
||||
surroundingRow.appendChild(createTableRow(false, newRow, '', 'romcell logs_table_cell'));
|
||||
|
@@ -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 && result[i].itemState != "Running") {
|
||||
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>";
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,11 @@
|
||||
function formatFilterPanel(targetElement, result) {
|
||||
var existingSearchModel;
|
||||
|
||||
function formatFilterPanel(containerElement, result) {
|
||||
containerElement.innerHTML = '';
|
||||
|
||||
var targetElement = document.createElement('div');
|
||||
targetElement.id = 'games_filter';
|
||||
|
||||
var panel = document.createElement('div');
|
||||
panel.id = 'filter_panel_box';
|
||||
|
||||
@@ -14,7 +21,6 @@
|
||||
containerPanelSearchField.id = 'filter_panel_search';
|
||||
containerPanelSearchField.type = 'text';
|
||||
containerPanelSearchField.placeholder = 'Search';
|
||||
containerPanelSearchField.setAttribute('onkeydown', 'executeFilterDelayed();');
|
||||
containerPanelSearch.appendChild(containerPanelSearchField);
|
||||
|
||||
panel.appendChild(containerPanelSearch);
|
||||
@@ -27,7 +33,8 @@
|
||||
var containerPanelUserRatingCheckBox = document.createElement('input');
|
||||
containerPanelUserRatingCheckBox.id = 'filter_panel_userrating_enabled';
|
||||
containerPanelUserRatingCheckBox.type = 'checkbox';
|
||||
containerPanelUserRatingCheckBox.setAttribute('oninput', 'executeFilterDelayed();');
|
||||
containerPanelUserRatingCheckBox.className = 'filter_panel_item_checkbox';
|
||||
containerPanelUserRatingCheckBox.setAttribute('onclick', 'filter_panel_userrating_enabled_check();');
|
||||
var ratingEnabledCookie = getCookie('filter_panel_userrating_enabled');
|
||||
if (ratingEnabledCookie) {
|
||||
if (ratingEnabledCookie == "true") {
|
||||
@@ -46,10 +53,9 @@
|
||||
containerPanelUserRatingMinField.id = 'filter_panel_userrating_min';
|
||||
containerPanelUserRatingMinField.type = 'number';
|
||||
containerPanelUserRatingMinField.placeholder = '0';
|
||||
containerPanelUserRatingMinField.setAttribute('onchange', 'executeFilterDelayed();');
|
||||
containerPanelUserRatingMinField.setAttribute('onkeydown', 'executeFilterDelayed();');
|
||||
containerPanelUserRatingMinField.setAttribute('min', '0');
|
||||
containerPanelUserRatingMinField.setAttribute('max', '100');
|
||||
containerPanelUserRatingMinField.setAttribute('oninput', 'filter_panel_userrating_value();');
|
||||
containerPanelUserRating.appendChild(containerPanelUserRatingMinField);
|
||||
|
||||
var containerPanelUserRatingMaxField = document.createElement('input');
|
||||
@@ -60,10 +66,9 @@
|
||||
containerPanelUserRatingMaxField.id = 'filter_panel_userrating_max';
|
||||
containerPanelUserRatingMaxField.type = 'number';
|
||||
containerPanelUserRatingMaxField.placeholder = '100';
|
||||
containerPanelUserRatingMaxField.setAttribute('onchange', 'executeFilterDelayed();');
|
||||
containerPanelUserRatingMaxField.setAttribute('onkeydown', 'executeFilterDelayed();');
|
||||
containerPanelUserRatingMaxField.setAttribute('min', '0');
|
||||
containerPanelUserRatingMaxField.setAttribute('max', '100');
|
||||
containerPanelUserRatingMaxField.setAttribute('oninput', 'filter_panel_userrating_value();');
|
||||
containerPanelUserRating.appendChild(containerPanelUserRatingMaxField);
|
||||
|
||||
panel.appendChild(containerPanelUserRating);
|
||||
@@ -96,6 +101,25 @@
|
||||
|
||||
targetElement.appendChild(panel);
|
||||
|
||||
var buttonsDiv = document.createElement('div');
|
||||
buttonsDiv.id = 'games_library_searchbuttons'
|
||||
|
||||
// add filter button
|
||||
var searchButton = document.createElement('div');
|
||||
searchButton.id = 'games_library_searchbutton';
|
||||
searchButton.setAttribute('onclick', 'executeFilter1_1();');
|
||||
searchButton.innerHTML = 'Apply';
|
||||
|
||||
buttonsDiv.appendChild(searchButton);
|
||||
|
||||
// add reset button
|
||||
var resetButton = document.createElement('div');
|
||||
resetButton.id = 'games_library_resetbutton';
|
||||
resetButton.setAttribute('onclick', 'resetFilters();');
|
||||
resetButton.innerHTML = 'Reset';
|
||||
|
||||
buttonsDiv.appendChild(resetButton);
|
||||
|
||||
// set order by values
|
||||
var orderByCookie = getCookie('games_library_orderby_select');
|
||||
if (orderByCookie) {
|
||||
@@ -105,6 +129,10 @@
|
||||
if (orderByDirectionCookie) {
|
||||
document.getElementById('games_library_orderby_direction_select').value = orderByDirectionCookie;
|
||||
}
|
||||
|
||||
containerElement.appendChild(targetElement);
|
||||
|
||||
containerElement.appendChild(buttonsDiv);
|
||||
}
|
||||
|
||||
function buildFilterPanel(targetElement, headerString, friendlyHeaderString, valueList, showToggle, initialDisplay) {
|
||||
@@ -157,6 +185,7 @@ function buildFilterPanelHeader(headerString, friendlyHeaderString, showVisibleT
|
||||
header.appendChild(headerToggle);
|
||||
header.setAttribute('onclick', 'toggleFilterPanel("' + headerString + '");');
|
||||
header.style.cursor = 'pointer';
|
||||
header.classList.add('filter_header_toggleable');
|
||||
}
|
||||
|
||||
header.appendChild(headerLabel);
|
||||
@@ -201,7 +230,6 @@ function buildFilterPanelItem(filterType, itemString, friendlyItemString, tags)
|
||||
filterPanelItemCheckBoxItem.className = 'filter_panel_item_checkbox';
|
||||
filterPanelItemCheckBoxItem.name = 'filter_' + filterType;
|
||||
filterPanelItemCheckBoxItem.setAttribute('filter_id', itemString);
|
||||
filterPanelItemCheckBoxItem.setAttribute('oninput' , 'executeFilter1_1();');
|
||||
if (checkState == true) {
|
||||
filterPanelItemCheckBoxItem.checked = true;
|
||||
}
|
||||
@@ -252,15 +280,76 @@ function buildFilterTag(tags) {
|
||||
return boundingDiv;
|
||||
}
|
||||
|
||||
function filter_panel_userrating_enabled_check() {
|
||||
var ratingCheck = document.getElementById('filter_panel_userrating_enabled');
|
||||
var minRatingValue = document.getElementById('filter_panel_userrating_min');
|
||||
var maxRatingValue = document.getElementById('filter_panel_userrating_max');
|
||||
|
||||
if (ratingCheck.checked == false) {
|
||||
minRatingValue.value = '';
|
||||
maxRatingValue.value = '';
|
||||
} else {
|
||||
minRatingValue.value = 0;
|
||||
maxRatingValue.value = 100;
|
||||
}
|
||||
}
|
||||
|
||||
function filter_panel_userrating_value() {
|
||||
var ratingCheck = document.getElementById('filter_panel_userrating_enabled');
|
||||
var minRatingValue = document.getElementById('filter_panel_userrating_min');
|
||||
var maxRatingValue = document.getElementById('filter_panel_userrating_max');
|
||||
|
||||
if (minRatingValue.value || maxRatingValue.value) {
|
||||
ratingCheck.checked = true;
|
||||
} else {
|
||||
ratingCheck.checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
// clear name
|
||||
document.getElementById('filter_panel_search').value = '';
|
||||
|
||||
// clear filter check boxes
|
||||
var filterChecks = document.getElementsByClassName('filter_panel_item_checkbox');
|
||||
for (var i = 0; i < filterChecks.length; i++) {
|
||||
filterChecks[i].checked = false;
|
||||
}
|
||||
|
||||
// fire checkbox specific scripts
|
||||
filter_panel_userrating_enabled_check();
|
||||
|
||||
executeFilter1_1();
|
||||
}
|
||||
|
||||
function executeFilter1_1(pageNumber, pageSize) {
|
||||
var freshSearch = false;
|
||||
|
||||
if (!pageNumber) {
|
||||
pageNumber = 1;
|
||||
freshSearch = true;
|
||||
existingSearchModel = undefined;
|
||||
}
|
||||
|
||||
if (!pageSize) {
|
||||
pageSize = 30;
|
||||
}
|
||||
|
||||
var model;
|
||||
|
||||
// get order by
|
||||
var orderBy = document.getElementById('games_library_orderby_select').value;
|
||||
setCookie('games_library_orderby_select', orderBy);
|
||||
var orderByDirection = true;
|
||||
var orderByDirectionSelect = document.getElementById('games_library_orderby_direction_select').value;
|
||||
if (orderByDirectionSelect == "Ascending") {
|
||||
orderByDirection = true;
|
||||
} else {
|
||||
orderByDirection = false;
|
||||
}
|
||||
setCookie('games_library_orderby_direction_select', orderByDirectionSelect);
|
||||
|
||||
if (existingSearchModel == undefined || freshSearch == true) {
|
||||
// user ratings
|
||||
var userRatingEnabled = document.getElementById('filter_panel_userrating_enabled');
|
||||
|
||||
@@ -297,18 +386,6 @@ function executeFilter1_1(pageNumber, pageSize) {
|
||||
setCookie("filter_panel_userrating_enabled", true);
|
||||
}
|
||||
|
||||
// get order by
|
||||
var orderBy = document.getElementById('games_library_orderby_select').value;
|
||||
setCookie('games_library_orderby_select', orderBy);
|
||||
var orderByDirection = true;
|
||||
var orderByDirectionSelect = document.getElementById('games_library_orderby_direction_select').value;
|
||||
if (orderByDirectionSelect == "Ascending") {
|
||||
orderByDirection = true;
|
||||
} else {
|
||||
orderByDirection = false;
|
||||
}
|
||||
setCookie('games_library_orderby_direction_select', orderByDirectionSelect);
|
||||
|
||||
// build filter model
|
||||
var ratingAgeGroups = GetFilterQuery1_1('agegroupings');
|
||||
var ratingIncludeUnrated = false;
|
||||
@@ -316,7 +393,7 @@ function executeFilter1_1(pageNumber, pageSize) {
|
||||
ratingIncludeUnrated = true;
|
||||
}
|
||||
|
||||
var model = {
|
||||
model = {
|
||||
"Name": document.getElementById('filter_panel_search').value,
|
||||
"Platform": GetFilterQuery1_1('platform'),
|
||||
"Genre": GetFilterQuery1_1('genre'),
|
||||
@@ -340,12 +417,19 @@ function executeFilter1_1(pageNumber, pageSize) {
|
||||
}
|
||||
};
|
||||
|
||||
existingSearchModel = model;
|
||||
} else {
|
||||
existingSearchModel.Sorting.SortBy = orderBy;
|
||||
existingSearchModel.Sorting.SortAscending = orderByDirection;
|
||||
model = existingSearchModel;
|
||||
}
|
||||
|
||||
ajaxCall(
|
||||
'/api/v1.1/Games?pageNumber=' + pageNumber + '&pageSize=' + pageSize,
|
||||
'POST',
|
||||
function (result) {
|
||||
var gameElement = document.getElementById('games_library');
|
||||
formatGamesPanel(gameElement, result, pageNumber, pageSize);
|
||||
formatGamesPanel(gameElement, result, pageNumber, pageSize, true);
|
||||
},
|
||||
function (error) {
|
||||
console.log('An error occurred: ' + JSON.stringify(error));
|
||||
|
@@ -8,18 +8,71 @@
|
||||
"ACB": "Australian Classification Board (ACB)"
|
||||
};
|
||||
|
||||
function formatGamesPanel(targetElement, result, pageNumber, pageSize) {
|
||||
var ClassificationRatings = {
|
||||
"E": "Everyone",
|
||||
"E10": "Everyone 10+",
|
||||
"T": "Teen",
|
||||
"M": "Mature 17+",
|
||||
"AO": "Adults Only 18+",
|
||||
"RP": "Rating Pending",
|
||||
|
||||
"Three": "PEGI 3",
|
||||
"Seven": "PEGI 7",
|
||||
"Twelve": "PEGI 12",
|
||||
"Sixteen": "PEGI 16",
|
||||
"Eighteen": "PEGI 18",
|
||||
|
||||
"CERO_A": "All Ages",
|
||||
"CERO_B": "Ages 12 and up",
|
||||
"CERO_C": "Ages 15 and up",
|
||||
"CERO_D": "Ages 17 and up",
|
||||
"CERO_Z": "Ages 18 and up only",
|
||||
|
||||
"USK_0": "Approved without age restriction",
|
||||
"USK_6": "Approved for children aged 6 and above",
|
||||
"USK_12": "Approved for children aged 12 and above",
|
||||
"USK_16": "Approved for children aged 16 and above",
|
||||
"USK_18": "Not approved for young persons",
|
||||
|
||||
"GRAC_All": "All",
|
||||
"GRAC_Twelve": "12+",
|
||||
"GRAC_Fifteen": "15+",
|
||||
"GRAC_Eighteen": "18+",
|
||||
"GRAC_Testing": "Testing",
|
||||
|
||||
"CLASS_IND_L": "General Audiences",
|
||||
"CLASS_IND_Ten": "Not recommended for minors under ten",
|
||||
"CLASS_IND_Twelve": "Not recommended for minors under twelve",
|
||||
"CLASS_IND_Fourteen": "Not recommended for minors under fourteen",
|
||||
"CLASS_IND_Sixteen": "Not recommended for minors under sixteen",
|
||||
"CLASS_IND_Eighteen": "Not recommended for minors under eighteen",
|
||||
|
||||
"ACB_G": "General",
|
||||
"ACB_PG": "Parental Guidance",
|
||||
"ACB_M": "Mature",
|
||||
"ACB_MA15": "Mature Accompanied",
|
||||
"ACB_R18": "Restricted",
|
||||
"ACB_RC": "Refused Classification"
|
||||
};
|
||||
|
||||
var pageReloadInterval;
|
||||
|
||||
function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScrollTop) {
|
||||
console.log("Displaying page: " + pageNumber);
|
||||
console.log("Page size: " + pageSize);
|
||||
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
var pageMode = GetPreference('LibraryPagination', 'paged');
|
||||
|
||||
if (pageNumber == 1 || pageMode == 'paged') {
|
||||
targetElement.innerHTML = '';
|
||||
}
|
||||
|
||||
if (pageMode == 'paged') {
|
||||
if (forceScrollTop == true) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
var pagerCheck = document.getElementById('games_library_pagerstore');
|
||||
if (pageNumber == 1) {
|
||||
pagerCheck.innerHTML = "0";
|
||||
@@ -144,6 +197,18 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// var pageReloadFunction = function() {
|
||||
// formatGamesPanel(targetElement, result, pageNumber, pageSize, false);
|
||||
|
||||
// ajaxCall('/api/v1.1/Filter', 'GET', function (result) {
|
||||
// var scrollerElement = document.getElementById('games_filter_scroller');
|
||||
// formatFilterPanel(scrollerElement, result);
|
||||
// })
|
||||
// };
|
||||
|
||||
// window.clearTimeout(pageReloadInterval);
|
||||
// pageReloadInterval = setTimeout(pageReloadFunction, 10000);
|
||||
}
|
||||
|
||||
function isScrolledIntoView(elem) {
|
||||
@@ -192,7 +257,7 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
|
||||
}
|
||||
gameImage.src = '/images/unknowngame.png';
|
||||
if (gameObject.cover) {
|
||||
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameObject.id + '/cover/image');
|
||||
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameObject.id + '/cover/image/cover_big/' + gameObject.cover.imageId + '.jpg');
|
||||
} else {
|
||||
gameImage.className = 'game_tile_image unknown';
|
||||
}
|
||||
@@ -208,7 +273,8 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
|
||||
if (gameObject.ageRatings[c].category == classificationDisplayOrder[b]) {
|
||||
shownClassificationBoard = classificationDisplayOrder[b];
|
||||
displayClassification = true;
|
||||
classificationPath = '/api/v1.1/Ratings/Images/' + classificationDisplayOrder[b] + '/' + getKeyByValue(AgeRatingStrings, gameObject.ageRatings[c].rating) + '/image.svg';
|
||||
//classificationPath = '/api/v1.1/Ratings/Images/' + classificationDisplayOrder[b] + '/' + getKeyByValue(AgeRatingStrings, gameObject.ageRatings[c].rating) + '/image.svg';
|
||||
classificationPath = '/images/Ratings/' + classificationDisplayOrder[b] + '/' + gameObject.ageRatings[c].rating + '.svg';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@@ -245,8 +245,6 @@ function intToRGB(i) {
|
||||
}
|
||||
|
||||
function DropDownRenderGameOption(state) {
|
||||
console.log(JSON.stringify(state));
|
||||
|
||||
if (state.loading) {
|
||||
return state;
|
||||
}
|
||||
@@ -260,7 +258,7 @@ function DropDownRenderGameOption(state) {
|
||||
|
||||
if (state.cover) {
|
||||
response = $(
|
||||
'<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="https://images.igdb.com/igdb/image/upload/t_cover_small/' + state.cover.value.imageId + '.jpg" /></td><td class="dropdown-label"><span class="dropdown-title">' + state.text + '</span><span class="dropdown-releasedate">' + releaseDate + '</span></td></tr></table>'
|
||||
'<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="/api/v1.1/Games/' + state.id + '/cover/image/cover_small/' + state.cover.imageId + '.jpg" /></td><td class="dropdown-label"><span class="dropdown-title">' + state.text + '</span><span class="dropdown-releasedate">' + releaseDate + '</span></td></tr></table>'
|
||||
);
|
||||
} else {
|
||||
response = $(
|
||||
@@ -411,10 +409,14 @@ function GetTaskFriendlyName(TaskName, options) {
|
||||
return "Organise library";
|
||||
case 'LibraryScan':
|
||||
return "Library scan";
|
||||
case 'LibraryScanWorker':
|
||||
return "Library scan worker: " + options.name;
|
||||
case 'CollectionCompiler':
|
||||
return "Compress collection id: " + options;
|
||||
case 'BackgroundDatabaseUpgrade':
|
||||
return "Background database upgrade";
|
||||
case 'TempCleanup':
|
||||
return "Temporary directory cleanup";
|
||||
default:
|
||||
return TaskName;
|
||||
}
|
||||
@@ -459,6 +461,25 @@ function SetPreference(Setting, Value) {
|
||||
);
|
||||
}
|
||||
|
||||
function SetPreference_Batch(model) {
|
||||
console.log(model);
|
||||
ajaxCall(
|
||||
'/api/v1.1/Account/Preferences',
|
||||
'POST',
|
||||
function(result) {
|
||||
for (var i = 0; i < model.length; i++) {
|
||||
SetPreference_Local(model[i].setting, model[i].value.toString());
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
for (var i = 0; i < model.length; i++) {
|
||||
SetPreference_Local(model[i].setting, model[i].value.toString());
|
||||
}
|
||||
},
|
||||
JSON.stringify(model)
|
||||
);
|
||||
}
|
||||
|
||||
function SetPreference_Local(Setting, Value) {
|
||||
if (userProfile.userPreferences) {
|
||||
var prefFound = false;
|
||||
|
@@ -198,6 +198,54 @@ h3 {
|
||||
/* margin-right: 10px; */
|
||||
}
|
||||
|
||||
#games_library_searchbuttons {
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
bottom: 0;
|
||||
margin-top: 5px;
|
||||
width: 200px;
|
||||
z-index: 1;
|
||||
background-color: #5d5d5d;
|
||||
}
|
||||
|
||||
#games_library_searchbutton {
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
bottom: 0;
|
||||
width: 180px;
|
||||
height: 18px;
|
||||
padding: 10px;
|
||||
background-color: #352879;
|
||||
color: white;
|
||||
text-align: center;
|
||||
font-family: Commodore64;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#games_library_searchbutton:hover {
|
||||
cursor: pointer;
|
||||
background-color: #6C5EB5;
|
||||
}
|
||||
|
||||
#games_library_resetbutton {
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
bottom: 0;
|
||||
width: 180px;
|
||||
height: 18px;
|
||||
padding: 10px;
|
||||
background-color: #646464;
|
||||
color: white;
|
||||
text-align: center;
|
||||
font-family: Commodore64;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#games_library_resetbutton:hover {
|
||||
cursor: pointer;
|
||||
background-color: #adadad;
|
||||
}
|
||||
|
||||
#games_filter {
|
||||
|
||||
width: 200px;
|
||||
@@ -217,6 +265,10 @@ h3 {
|
||||
background-color: #2b2b2b;
|
||||
}
|
||||
|
||||
.filter_header_toggleable:hover {
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.filter_panel_box {
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
@@ -226,7 +278,7 @@ h3 {
|
||||
input[type='text'], input[type='number'], input[type="email"], input[type="password"], input[type="datetime-local"] {
|
||||
background-color: #2b2b2b;
|
||||
color: white;
|
||||
padding: 5px;
|
||||
padding: 4px;
|
||||
font-family: "PT Sans", Arial, Helvetica, sans-serif;
|
||||
font-kerning: normal;
|
||||
font-style: normal;
|
||||
@@ -235,7 +287,13 @@ input[type='text'], input[type='number'], input[type="email"], input[type="passw
|
||||
border-radius: 5px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: lightgray;
|
||||
/* border-color: lightgray; */
|
||||
border-color: #2b2b2b;
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
input[type='text']:hover, input[type='number']:hover, input[type="email"]:hover, input[type="password"]:hover, input[type="datetime-local"]:hover {
|
||||
border-color: #939393;
|
||||
}
|
||||
|
||||
input[id='filter_panel_search'] {
|
||||
@@ -391,13 +449,22 @@ input[id='filter_panel_userrating_max'] {
|
||||
border-color: #2b2b2b;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
padding-top: 7px;
|
||||
padding-bottom: 10px;
|
||||
padding-right: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.games_library_controlblock {
|
||||
margin-left: 20px;
|
||||
margin-left: 10px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.games_library_label {
|
||||
display: inline-block;
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
#games_library {
|
||||
@@ -579,13 +646,17 @@ input[id='filter_panel_userrating_max'] {
|
||||
|
||||
.rating_image {
|
||||
display: inline-block;
|
||||
height: 64px;
|
||||
max-width: 64px;
|
||||
max-height: 64px;
|
||||
margin-right: 20px;
|
||||
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);
|
||||
/* margin-bottom: 20px; */
|
||||
}
|
||||
|
||||
.rating_image_logo_table {
|
||||
min-height: 70px;
|
||||
min-width: 70px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rating_image_mini {
|
||||
@@ -841,8 +912,14 @@ div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
background-color: #2b2b2b !important;
|
||||
background-color: #2b2b2b;
|
||||
color: white !important;
|
||||
border: 1px solid #2b2b2b;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.select2-container--default:hover, .select2-selection--multiple:hover {
|
||||
border-color: #939393;
|
||||
}
|
||||
|
||||
.select2-container--open .select2-dropdown--below,
|
||||
@@ -854,8 +931,23 @@ div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover
|
||||
border: 1px solid #2b2b2b;
|
||||
}
|
||||
|
||||
.select2-selection__choice {
|
||||
background-color: #2b2b2b !important;
|
||||
/* tag item */
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #575757 !important;
|
||||
border: 1px solid #2b2b2b;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* tag item delete button */
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||
border-right: none;
|
||||
background-color: #939393;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* tag item label */
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__display {
|
||||
background-color: #4e4e4e;
|
||||
}
|
||||
|
||||
.select2-selection__choice__display {
|
||||
@@ -870,8 +962,24 @@ div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover
|
||||
background-color: #2b2b2b;
|
||||
color: white !important;
|
||||
border: 1px solid #2b2b2b;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.select2-selection--single:hover, .select2-selection__rendered:hover {
|
||||
border-color: #939393;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single {
|
||||
background-color: #2b2b2b;
|
||||
color: white !important;
|
||||
border: 1px solid #2b2b2b;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* .select2-container--default:hover, .select2-selection--single:hover {
|
||||
border-color: #939393;
|
||||
} */
|
||||
|
||||
.select2-search__field {
|
||||
background-color: #2b2b2b;
|
||||
color: white;
|
||||
@@ -907,7 +1015,7 @@ div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover
|
||||
color: lightgray;
|
||||
}
|
||||
|
||||
button {
|
||||
button:not(.select2-selection__choice__remove):not(.ejs_menu_button):not(.bigbutton) {
|
||||
background-color: #555;
|
||||
color: white;
|
||||
border-width: 1px;
|
||||
@@ -915,23 +1023,40 @@ button {
|
||||
border-style: solid;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
margin-right: 3px;
|
||||
margin-bottom: 3px;
|
||||
font-size: 13px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
button:not(.select2-selection__choice__remove):not(.ejs_menu_button):hover {
|
||||
background-color: #888;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
||||
background-color: #555;
|
||||
color: #888;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.bigbutton {
|
||||
background-color: #555;
|
||||
color: white;
|
||||
border-width: 1px;
|
||||
border-color: #555;
|
||||
border-style: solid;
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
font-size: 16px;
|
||||
border-radius: 10px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.redbutton {
|
||||
background-color: darkred;
|
||||
border-color: darkred;
|
||||
@@ -946,11 +1071,23 @@ button:disabled {
|
||||
}
|
||||
|
||||
#emulator {
|
||||
|
||||
}
|
||||
|
||||
.emulator_partscreen {
|
||||
margin: 0 auto;
|
||||
width: 640px;
|
||||
padding-top: 100px;
|
||||
}
|
||||
|
||||
.emulator_fullscreen {
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
#emulatorbios {
|
||||
margin: 0 auto;
|
||||
width: 640px;
|
||||
@@ -1163,16 +1300,17 @@ button:disabled {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
text-align: center;
|
||||
text-align: right;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.tagBoxItem {
|
||||
display: block;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
width: 10px;
|
||||
min-width: 10px;
|
||||
height: 10px;
|
||||
background-color: darkslategray;
|
||||
color: white;
|
||||
|