Assorted bug fixes (#242)

* Fixed DBNull error when updating metadata

* Fixed platform id bug with media group launching

* Updates to support Hasheous - testing only

* Refactored alot of code, initial support for Hasheous
This commit is contained in:
Michael Green
2023-12-30 20:28:23 +11:00
committed by GitHub
parent ea0a5a6a71
commit 311c7733fa
26 changed files with 898 additions and 896 deletions

View File

@@ -304,7 +304,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) {
@@ -749,7 +749,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;
}
}
@@ -801,7 +801,7 @@ namespace gaseous_server.Classes
get {
long Size = 0;
foreach (Roms.GameRomItem Rom in Roms) {
Size += Rom.Size;
Size += (long)Rom.Size;
}
return Size;

View File

@@ -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>

View File

@@ -473,22 +473,56 @@ 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 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 string HasheousHost = _HasheousHost;
}
public class IGDB

View File

@@ -0,0 +1,286 @@
using System.IO.Compression;
using HasheousClient.Models;
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
using SharpCompress.Common;
namespace gaseous_server.Classes
{
public class FileSignature
{
public static gaseous_server.Models.Signatures_Games GetFileSignature(Common.hashObject hash, FileInfo fi, string GameFileImportPath)
{
gaseous_server.Models.Signatures_Games discoveredSignature = new gaseous_server.Models.Signatures_Games();
discoveredSignature = _GetFileSignature(hash, fi, 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
Logging.Log(Logging.LogType.Information, "Get Signature", "Decompressing " + GameFileImportPath + " to examine contents");
string ExtractPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, Path.GetRandomFileName());
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
try
{
switch(ImportedFileExtension)
{
case ".zip":
ZipFile.ExtractToDirectory(GameFileImportPath, ExtractPath);
break;
case ".rar":
using (var archive = RarArchive.Open(GameFileImportPath))
{
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
entry.WriteToDirectory(ExtractPath, new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
}
break;
case ".7z":
using (var archive = SharpCompress.Archives.SevenZip.SevenZipArchive.Open(GameFileImportPath))
{
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
entry.WriteToDirectory(ExtractPath, new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
}
break;
}
// loop through contents until we find the first signature match
foreach (string file in Directory.GetFiles(ExtractPath, "*.*", SearchOption.AllDirectories))
{
FileInfo zfi = new FileInfo(file);
Common.hashObject zhash = new Common.hashObject(file);
gaseous_server.Models.Signatures_Games zDiscoveredSignature = _GetFileSignature(zhash, zfi, 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;
break;
}
}
}
catch (Exception ex)
{
Logging.Log(Logging.LogType.Critical, "Get Signature", "Error processing zip file: " + GameFileImportPath, ex);
}
if (Directory.Exists(ExtractPath)) { Directory.Delete(ExtractPath, true); }
}
return discoveredSignature;
}
private static gaseous_server.Models.Signatures_Games _GetFileSignature(Common.hashObject hash, FileInfo fi, string GameFileImportPath, bool IsInZip)
{
gaseous_server.Models.Signatures_Games discoveredSignature = new gaseous_server.Models.Signatures_Games();
// do database search first
gaseous_server.Models.Signatures_Games? dbSignature = _GetFileSignatureFromDatabase(hash, fi, GameFileImportPath);
if (dbSignature != null)
{
// local signature found
discoveredSignature = dbSignature;
}
else
{
// no local signature attempt to pull from Hasheous
dbSignature = _GetFileSignatureFromHasheous(hash, fi, GameFileImportPath);
if (dbSignature != null)
{
// signature retrieved from Hasheous
discoveredSignature = dbSignature;
}
else
{
// construct a signature from file data
dbSignature = _GetFileSignatureFromFileData(hash, fi, GameFileImportPath);
discoveredSignature = dbSignature;
}
}
Logging.Log(Logging.LogType.Information, "Import Game", " Determined import file as: " + discoveredSignature.Game.Name + " (" + discoveredSignature.Game.Year + ") " + discoveredSignature.Game.System);
return discoveredSignature;
}
private static gaseous_server.Models.Signatures_Games? _GetFileSignatureFromDatabase(Common.hashObject hash, FileInfo fi, string GameFileImportPath)
{
// 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.Count == 0)
{
// 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);
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, fi, false);
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;
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, fi, false);
}
}
return discoveredSignature;
}
return null;
}
private static gaseous_server.Models.Signatures_Games? _GetFileSignatureFromHasheous(Common.hashObject hash, FileInfo fi, 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;
}
}
}
}
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref signature, fi, false);
return signature;
}
}
}
return null;
}
private static gaseous_server.Models.Signatures_Games _GetFileSignatureFromFileData(Common.hashObject hash, FileInfo fi, 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(fi.Name);
if (signatures.Count == 1)
{
// only 1 signature found!
discoveredSignature = signatures.ElementAt(0);
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, fi, false);
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;
gaseous_server.Models.PlatformMapping.GetIGDBPlatformMapping(ref discoveredSignature, fi, false);
}
}
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();
// 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_server.Models.Signatures_Games.RomItem.SignatureSourceType.None;
return discoveredSignature;
}
}
}
}

View File

@@ -6,10 +6,13 @@ 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
{
@@ -102,7 +105,7 @@ namespace gaseous_server.Classes
{
Logging.Log(Logging.LogType.Information, "Import Game", " " + GameFileImportPath + " not in database - processing");
Models.Signatures_Games discoveredSignature = GetFileSignature(hash, fi, GameFileImportPath);
gaseous_server.Models.Signatures_Games discoveredSignature = GetFileSignature(hash, fi, GameFileImportPath);
// get discovered platform
IGDB.Models.Platform? determinedPlatform = null;
@@ -121,7 +124,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);
// add to database
StoreROM(GameLibrary.GetDefaultLibrary, hash, determinedGame, determinedPlatform, discoveredSignature, GameFileImportPath);
@@ -152,155 +155,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)
{
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)
{
// 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, false);
}
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 +300,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);
@@ -682,7 +559,7 @@ namespace gaseous_server.Classes
Common.hashObject hash = new Common.hashObject(LibraryFile);
FileInfo fi = new FileInfo(LibraryFile);
Models.Signatures_Games sig = GetFileSignature(hash, fi, LibraryFile);
gaseous_server.Models.Signatures_Games sig = GetFileSignature(hash, fi, LibraryFile);
Logging.Log(Logging.LogType.Information, "Library Scan", " Orphaned file found in library: " + LibraryFile);
@@ -697,17 +574,17 @@ namespace gaseous_server.Classes
if (library.DefaultPlatformId == 0)
{
determinedPlatform = new IGDB.Models.Platform();
determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
determinedGame = SearchForGame(sig, sig.Flags.IGDBPlatformId);
}
else
{
determinedPlatform = Platforms.GetPlatform(library.DefaultPlatformId);
determinedGame = SearchForGame(sig.Game.Name, library.DefaultPlatformId);
determinedGame = SearchForGame(sig, library.DefaultPlatformId);
}
}
else
{
determinedGame = SearchForGame(sig.Game.Name, (long)determinedPlatform.Id);
determinedGame = SearchForGame(sig, (long)determinedPlatform.Id);
}
StoreROM(library, hash, determinedGame, determinedPlatform, sig, LibraryFile);
@@ -734,7 +611,7 @@ 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);
@@ -778,11 +655,11 @@ namespace gaseous_server.Classes
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 OR GameId = 0) AND MetadataSource = 0) OR (PlatformId = 0 AND GameId = 0)) AND (LastMatchAttemptDate IS NULL OR LastMatchAttemptDate < @lastmatchattemptdate) 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 OR GameId = 0) AND MetadataSource = 0) OR (PlatformId = 0 AND GameId = 0));";
}
Dictionary<string, object> dbDict = new Dictionary<string, object>();
dbDict.Add("lastmatchattemptdate", DateTime.UtcNow.AddDays(-7));
@@ -808,7 +685,7 @@ 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);
gaseous_server.Models.Signatures_Games sig = GetFileSignature(hash, fi, romPath);
// determine rom platform
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
@@ -817,7 +694,7 @@ namespace gaseous_server.Classes
determinedPlatform = new IGDB.Models.Platform();
}
IGDB.Models.Game determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
IGDB.Models.Game determinedGame = SearchForGame(sig, sig.Flags.IGDBPlatformId);
StoreROM(library, hash, determinedGame, determinedPlatform, sig, romPath, romId);

View File

@@ -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)
{
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);
return RetVal.Result;
}
}
public static Artwork GetArtwork(string Slug, string LogoPath)
public static Artwork GetArtwork(string Slug, string ImagePath)
{
Task<Artwork> RetVal = _GetArtwork(SearchUsing.slug, Slug, LogoPath);
Task<Artwork> RetVal = _GetArtwork(SearchUsing.slug, Slug, ImagePath);
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)
{
// 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,13 @@ 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 ((!File.Exists(localFile)) || forceImageDownload == 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);
Logging.Log(Logging.LogType.Information, "Metadata: " + returnValue.GetType().Name, "Artwork download forced.");
GetImageFromServer(ImagePath, returnValue.ImageId);
}
return returnValue;
@@ -104,64 +107,23 @@ 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)
private static async void GetImageFromServer(string ImagePath, 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);
Communications comms = new Communications();
List<Communications.IGDBAPI_ImageSize> imageSizes = new List<Communications.IGDBAPI_ImageSize>();
imageSizes.AddRange(Enum.GetValues(typeof(Communications.IGDBAPI_ImageSize)).Cast<Communications.IGDBAPI_ImageSize>());
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
await comms.IGDBAPI_GetImage(imageSizes, ImageId, ImagePath);
}
}
}

View File

@@ -1,4 +1,6 @@
using System.ComponentModel;
using System.Net;
using Humanizer;
using IGDB;
using RestEase;
@@ -15,10 +17,12 @@ namespace gaseous_server.Classes.Metadata
Config.IGDB.Secret
);
private HttpClient client = new HttpClient();
/// <summary>
/// Configure metadata API communications
/// </summary>
public static MetadataSources MetadataSource
public static HasheousClient.Models.MetadataModel.MetadataSources MetadataSource
{
get
{
@@ -30,7 +34,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 +50,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 +146,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 +158,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 +222,207 @@ 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;
Logging.Log(Logging.LogType.Information, "Communications", "Downloading from " + uri.ToString() + " to " + DestinationFile);
try
{
using (var s = client.GetStreamAsync(uri))
{
s.ConfigureAwait(false);
if (!Directory.Exists(DestinationDirectory))
{
Directory.CreateDirectory(DestinationDirectory);
}
using (var fs = new FileStream(DestinationFile, FileMode.OpenOrCreate))
{
s.Result.CopyTo(fs);
}
}
if (File.Exists(DestinationFile))
{
FileInfo fi = new FileInfo(DestinationFile);
if (fi.Length > 0)
{
return true;
}
else
{
File.Delete(DestinationFile);
throw new Exception("Zero length file");
}
}
else
{
throw new Exception("Zero length file");
}
}
catch (Exception ex)
{
Logging.Log(Logging.LogType.Critical, "Communications", "Error while downloading from " + uri.ToString(), ex);
throw;
}
return false;
}
public static async Task<string> GetSpecificImageFromServer(string ImagePath, string ImageId, IGDBAPI_ImageSize size, List<IGDBAPI_ImageSize>? FallbackSizes = null)
{
Communications comms = new Communications();
List<IGDBAPI_ImageSize> imageSizes = new List<IGDBAPI_ImageSize>
{
size
};
string returnPath = "";
FileInfo? fi;
// get the image
try
{
returnPath = Path.Combine(ImagePath, size.ToString(), ImageId + ".jpg");
if (!File.Exists(returnPath))
{
await comms.IGDBAPI_GetImage(imageSizes, ImageId, ImagePath);
}
if (File.Exists(returnPath))
{
fi = new FileInfo(returnPath);
if (fi.Length == 0 || fi.LastWriteTimeUtc.AddDays(7) < DateTime.UtcNow)
{
File.Delete(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);
}
}
}
}
return returnPath;
}
/// <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";
await _DownloadFile(new Uri(url), Path.Combine(newOutputPath, OutputFile));
}
}
public enum IGDBAPI_ImageSize
{
/// <summary>
/// 90x128 Fit
/// </summary>
[Description("cover_small")]
cover_small,
/// <summary>
/// 264x374 Fit
/// </summary>
[Description("cover_big")]
cover_big,
/// <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
}
}
}

View File

@@ -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,13 @@ 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.");
GetImageFromServer(ImagePath, returnValue.ImageId);
}
return returnValue;
@@ -109,64 +109,23 @@ 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)
private static async void GetImageFromServer(string ImagePath, string ImageId)
{
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);
Communications comms = new Communications();
List<Communications.IGDBAPI_ImageSize> imageSizes = new List<Communications.IGDBAPI_ImageSize>();
imageSizes.AddRange(Enum.GetValues(typeof(Communications.IGDBAPI_ImageSize)).Cast<Communications.IGDBAPI_ImageSize>());
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
await comms.IGDBAPI_GetImage(imageSizes, ImageId, ImagePath);
}
}
}

View File

@@ -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 = true)
{
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 = true)
{
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,19 +63,20 @@ 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;
if (GetImages == true) { forceImageDownload = true; }
break;
case Storage.CacheStatus.Expired:
try
{
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
if (GetImages == true) { forceImageDownload = true; }
}
catch (Exception ex)
{
@@ -88,11 +91,21 @@ namespace gaseous_server.Classes.Metadata
throw new Exception("How did you get here?");
}
if ((!File.Exists(Path.Combine(LogoPath, "Cover.jpg"))) || forceImageDownload == true)
if (forceImageDownload == 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);
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>();
imageSizes.AddRange(Enum.GetValues(typeof(Communications.IGDBAPI_ImageSize)).Cast<Communications.IGDBAPI_ImageSize>());
foreach (Communications.IGDBAPI_ImageSize size in imageSizes)
{
string localFile = Path.Combine(ImagePath, size.ToString(), returnValue.ImageId + ".jpg");
if ((!File.Exists(localFile)) || forceImageDownload == true)
{
Communications.GetSpecificImageFromServer(ImagePath, returnValue.ImageId, size, null);
}
}
}
return returnValue;
@@ -104,63 +117,23 @@ 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)
public static async void GetImageFromServer(string ImagePath, 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);
Communications comms = new Communications();
List<Communications.IGDBAPI_ImageSize> imageSizes = new List<Communications.IGDBAPI_ImageSize>();
imageSizes.AddRange(Enum.GetValues(typeof(Communications.IGDBAPI_ImageSize)).Cast<Communications.IGDBAPI_ImageSize>());
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
await comms.IGDBAPI_GetImage(imageSizes, ImageId, ImagePath);
}
}
}

View File

@@ -129,7 +129,7 @@ namespace gaseous_server.Classes.Metadata
{
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), false);
}
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);
}

View File

@@ -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,13 @@ 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.");
GetImageFromServer(ImagePath, returnValue.ImageId);
}
}
@@ -109,64 +112,23 @@ 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 results = await comms.APIComm<PlatformLogo>(IGDBClient.Endpoints.Artworks, fieldList, WhereClause);
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)
private static async void GetImageFromServer(string ImagePath, string ImageId)
{
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);
Communications comms = new Communications();
List<Communications.IGDBAPI_ImageSize> imageSizes = new List<Communications.IGDBAPI_ImageSize>();
imageSizes.AddRange(Enum.GetValues(typeof(Communications.IGDBAPI_ImageSize)).Cast<Communications.IGDBAPI_ImageSize>());
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
comms.IGDBAPI_GetImage(imageSizes, ImageId, ImagePath);
}
}
}

View File

@@ -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)
{
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);
return RetVal.Result;
}
}
public static Screenshot GetScreenshot(string Slug, string LogoPath)
public static Screenshot GetScreenshot(string Slug, string ImagePath)
{
Task<Screenshot> RetVal = _GetScreenshot(SearchUsing.slug, Slug, LogoPath);
Task<Screenshot> RetVal = _GetScreenshot(SearchUsing.slug, Slug, ImagePath);
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)
{
// 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,13 @@ 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 ((!File.Exists(localFile)) || forceImageDownload == 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);
Logging.Log(Logging.LogType.Information, "Metadata: " + returnValue.GetType().Name, "Screenshot download forced.");
GetImageFromServer(ImagePath, returnValue.ImageId);
}
return returnValue;
@@ -105,64 +107,24 @@ 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)
private static async void GetImageFromServer(string ImagePath, 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);
Communications comms = new Communications();
List<Communications.IGDBAPI_ImageSize> imageSizes = new List<Communications.IGDBAPI_ImageSize>();
imageSizes.Add(Communications.IGDBAPI_ImageSize.original);
imageSizes.Add(Communications.IGDBAPI_ImageSize.thumb);
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
await comms.IGDBAPI_GetImage(imageSizes, ImageId, ImagePath);
}
}
}

View File

@@ -13,7 +13,7 @@ namespace gaseous_server.Classes
DataTable dt = new DataTable();
// disabling forceRefresh
forceRefresh = false;
forceRefresh = true;
// update platforms
sql = "SELECT Id, `Name` FROM Platform;";
@@ -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)
{

View File

@@ -139,16 +139,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"])
};
@@ -176,130 +176,43 @@ namespace gaseous_server.Classes
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 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? 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 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; }
}
}
}

View 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;
}
}
}

View File

@@ -525,10 +525,10 @@ namespace gaseous_server.Controllers
[MapToApiVersion("1.0")]
[MapToApiVersion("1.1")]
[HttpGet]
[Route("{GameId}/artwork/{ArtworkId}/image")]
[Route("{GameId}/artwork/{ArtworkId}/image/{size}")]
[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)
{
try
{
@@ -538,13 +538,13 @@ namespace gaseous_server.Controllers
{
IGDB.Models.Artwork artworkObject = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject));
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");
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 +592,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 +616,32 @@ namespace gaseous_server.Controllers
[MapToApiVersion("1.0")]
[MapToApiVersion("1.1")]
[HttpGet]
[Route("{GameId}/cover/image")]
[Route("{GameId}/cover/image/{size}")]
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GameCoverImage(long GameId)
[ResponseCache(CacheProfileName = "None")]
public ActionResult GameCoverImage(long GameId, Communications.IGDBAPI_ImageSize size)
{
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");
Task<string> ImgFetch = Communications.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
{
@@ -639,15 +650,14 @@ namespace gaseous_server.Controllers
};
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("Cache-Control", "public, max-age=604800");
//Response.Headers.Add("Cache-Control", "public, max-age=604800");
return File(filedata, contentType);
}
else
{
return NotFound();
}
}
return NotFound();
}
catch
{
return NotFound();
@@ -1232,7 +1242,7 @@ 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);
gaseous_server.Models.Signatures_Games romSig = FileSignature.GetFileSignature(hash, new FileInfo(romItem.Path), romItem.Path);
List<Game> searchResults = Classes.ImportGame.SearchForGame_GetAll(romSig.Game.Name, romSig.Flags.IGDBPlatformId);
return Ok(searchResults);
@@ -1325,10 +1335,10 @@ namespace gaseous_server.Controllers
[MapToApiVersion("1.0")]
[MapToApiVersion("1.1")]
[HttpGet]
[Route("{GameId}/screenshots/{ScreenshotId}/image")]
[Route("{GameId}/screenshots/{ScreenshotId}/image/{size}")]
[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)
{
try
{
@@ -1336,13 +1346,13 @@ namespace gaseous_server.Controllers
IGDB.Models.Screenshot screenshotObject = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject));
string coverFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Screenshots", screenshotObject.ImageId + ".png");
string coverFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Screenshots", Size.ToString(), screenshotObject.ImageId + ".jpg");
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
{

View File

@@ -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;
}
}
}

View File

@@ -358,7 +358,7 @@ namespace gaseous_server.Models
return mapItem;
}
public static void GetIGDBPlatformMapping(ref Models.Signatures_Games Signature, FileInfo RomFileInfo, bool SetSystemName)
public static void GetIGDBPlatformMapping(ref gaseous_server.Models.Signatures_Games Signature, FileInfo RomFileInfo, bool SetSystemName)
{
bool PlatformFound = false;
foreach (Models.PlatformMapping.PlatformMapItem PlatformMapping in Models.PlatformMapping.PlatformMap)

View File

@@ -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; }
}
}
}

View File

@@ -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()
{

View File

@@ -20,11 +20,14 @@
<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="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" />
@@ -187,4 +190,7 @@
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1010.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1011.sql" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\hasheous-client\hasheous-client.csproj" />
</ItemGroup>
</Project>

View File

@@ -28,5 +28,7 @@
EJS_backgroundBlur = true;
EJS_gameName = emuGameTitle;
EJS_threads = false;
</script>
<script src='/emulators/EmulatorJS/data/loader.js'></script>

View File

@@ -128,9 +128,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>";

View File

@@ -168,7 +168,7 @@
} else {
var bg = document.getElementById('bgImage');
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);');
bg.setAttribute('style', 'background-image: url("/api/v1.1/Games/' + gameId + '/cover/image/original"); 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);');
@@ -234,7 +234,7 @@
var gameImage = document.createElement('img');
gameImage.className = 'game_cover_image';
if (result.cover) {
gameImage.src = '/api/v1.1/Games/' + result.id + '/cover/image';
gameImage.src = '/api/v1.1/Games/' + result.id + '/cover/image/cover_big';
} else {
gameImage.src = '/images/unknowngame.png';
gameImage.className = 'game_cover_image unknown';
@@ -298,7 +298,7 @@
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/' + result.screenshots.ids[i] + '/image/thumb"); background-position: center; background-repeat: no-repeat; background-size: contain;)');
screenshotItem.setAttribute('imageid', imageIndex);
screenshotItem.setAttribute('imagetype', 0);
screenshotItem.className = 'gamescreenshots_gallery_item';
@@ -584,7 +584,7 @@
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>';
launchButton = '<a href="/index.html?page=emulator&engine=' + gameRomItem.emulator.type + '&core=' + gameRomItem.emulator.core + '&platformid=' + gameRomItem.platformId + '&gameid=' + gameId + '&rompath=' + encodeURIComponent('/api/v1.1/Games/' + gameId + '/romgroup/' + mediaGroup.id + '/' + gameData.name + '(' + mediaGroup.id + ')' + '.zip') + '" class="romstart">Launch</a>';
break;
}
}
@@ -673,7 +673,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"); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);');
artworksTimer = setTimeout(rotateBackground, 60000);
}
}
@@ -698,7 +698,7 @@
switch (gameScreenshots_Selected.getAttribute('imagetype')) {
case "0":
// screenshot
gameScreenshots_Main.setAttribute('style', gameScreenshots_Selected.getAttribute('style'));
gameScreenshots_Main.setAttribute('style', gameScreenshots_Selected.getAttribute('style').replace("/image/thumb", "/image/original"));
break;
case "1":
// video

View File

@@ -192,7 +192,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');
} else {
gameImage.className = 'game_tile_image unknown';
}

View File

@@ -260,7 +260,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" /></td><td class="dropdown-label"><span class="dropdown-title">' + state.text + '</span><span class="dropdown-releasedate">' + releaseDate + '</span></td></tr></table>'
);
} else {
response = $(