WIP
This commit is contained in:
@@ -4,7 +4,7 @@ FROM mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm
|
|||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
|
|
||||||
# download and unzip EmulatorJS from CDN
|
# download and unzip EmulatorJS from CDN
|
||||||
RUN apt-get install -y p7zip-full
|
RUN apt-get install -y p7zip-full default-jdk nodejs wget
|
||||||
RUN mkdir -p out/wwwroot/emulators/EmulatorJS
|
RUN mkdir -p out/wwwroot/emulators/EmulatorJS
|
||||||
RUN wget https://cdn.emulatorjs.org/releases/4.1.1.7z
|
RUN wget https://cdn.emulatorjs.org/releases/4.1.1.7z
|
||||||
RUN 7z x -y -oout/wwwroot/emulators/EmulatorJS 4.1.1.7z
|
RUN 7z x -y -oout/wwwroot/emulators/EmulatorJS 4.1.1.7z
|
@@ -1,27 +1,25 @@
|
|||||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||||
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
|
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
|
||||||
{
|
{
|
||||||
"name": "C# (.NET)",
|
"name": "Gaseous C# (.NET)",
|
||||||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
||||||
//"image": "mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm",
|
//"image": "mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm",
|
||||||
"dockerComposeFile": "docker-compose.yml",
|
"dockerComposeFile": "docker-compose.yml",
|
||||||
"service": "development",
|
"service": "development",
|
||||||
"workspaceFolder": "/workspace",
|
"workspaceFolder": "/workspace",
|
||||||
|
|
||||||
// Features to add to the dev container. More info: https://containers.dev/features.
|
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||||
// "features": {},
|
// "features": {},
|
||||||
|
|
||||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
"forwardPorts": [5198],
|
"forwardPorts": [
|
||||||
|
5198
|
||||||
|
],
|
||||||
"portsAttributes": {
|
"portsAttributes": {
|
||||||
"5198": {
|
"5198": {
|
||||||
"protocol": "http"
|
"protocol": "http"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Use 'postCreateCommand' to run commands after the container is created.
|
// Use 'postCreateCommand' to run commands after the container is created.
|
||||||
"postCreateCommand": "dotnet restore",
|
"postCreateCommand": "dotnet restore",
|
||||||
|
|
||||||
// Configure tool-specific properties.
|
// Configure tool-specific properties.
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
@@ -38,11 +36,11 @@
|
|||||||
"ms-dotnettools.vscodeintellicode-csharp",
|
"ms-dotnettools.vscodeintellicode-csharp",
|
||||||
"Zignd.html-css-class-completion",
|
"Zignd.html-css-class-completion",
|
||||||
"PWABuilder.pwa-studio",
|
"PWABuilder.pwa-studio",
|
||||||
"ms-azuretools.vscode-docker"
|
"ms-azuretools.vscode-docker",
|
||||||
|
"SonarSource.sonarlint-vscode"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||||
// "remoteUser": "root"
|
// "remoteUser": "root"
|
||||||
}
|
}
|
@@ -337,11 +337,23 @@ namespace gaseous_server.Classes
|
|||||||
// only IGDB metadata is supported
|
// only IGDB metadata is supported
|
||||||
if (metadataResult.Source == HasheousClient.Models.MetadataSources.IGDB)
|
if (metadataResult.Source == HasheousClient.Models.MetadataSources.IGDB)
|
||||||
{
|
{
|
||||||
if (metadataResult.Id.Length > 0)
|
if (metadataResult.ImmutableId.Length > 0)
|
||||||
{
|
{
|
||||||
|
// use immutable id
|
||||||
|
Platform hasheousPlatform = Platforms.GetPlatform(long.Parse(metadataResult.ImmutableId));
|
||||||
|
signature.MetadataSources.AddPlatform((long)hasheousPlatform.Id, hasheousPlatform.Name, metadataResult.Source);
|
||||||
|
}
|
||||||
|
else if (metadataResult.Id.Length > 0)
|
||||||
|
{
|
||||||
|
// fall back to id
|
||||||
Platform hasheousPlatform = Platforms.GetPlatform(metadataResult.Id);
|
Platform hasheousPlatform = Platforms.GetPlatform(metadataResult.Id);
|
||||||
signature.MetadataSources.AddPlatform((long)hasheousPlatform.Id, hasheousPlatform.Name, metadataResult.Source);
|
signature.MetadataSources.AddPlatform((long)hasheousPlatform.Id, hasheousPlatform.Name, metadataResult.Source);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no id or immutable id - use unknown platform
|
||||||
|
signature.MetadataSources.AddPlatform(0, "Unknown Platform", HasheousClient.Models.MetadataSources.None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,11 +369,20 @@ namespace gaseous_server.Classes
|
|||||||
// only IGDB metadata is supported
|
// only IGDB metadata is supported
|
||||||
if (metadataResult.Source == HasheousClient.Models.MetadataSources.IGDB)
|
if (metadataResult.Source == HasheousClient.Models.MetadataSources.IGDB)
|
||||||
{
|
{
|
||||||
if (metadataResult.Id.Length > 0)
|
if (metadataResult.ImmutableId.Length > 0)
|
||||||
|
{
|
||||||
|
signature.MetadataSources.AddGame(long.Parse(metadataResult.ImmutableId), HasheousResult.Name, metadataResult.Source);
|
||||||
|
}
|
||||||
|
else if (metadataResult.Id.Length > 0)
|
||||||
{
|
{
|
||||||
gaseous_server.Models.Game hasheousGame = Games.GetGame(HasheousClient.Models.MetadataSources.IGDB, metadataResult.Id);
|
gaseous_server.Models.Game hasheousGame = Games.GetGame(HasheousClient.Models.MetadataSources.IGDB, metadataResult.Id);
|
||||||
signature.MetadataSources.AddGame((long)hasheousGame.Id, hasheousGame.Name, metadataResult.Source);
|
signature.MetadataSources.AddGame((long)hasheousGame.Id, hasheousGame.Name, metadataResult.Source);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no id or immutable id - use unknown game
|
||||||
|
signature.MetadataSources.AddGame(0, "Unknown Game", HasheousClient.Models.MetadataSources.None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -561,7 +561,7 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
gameSlug = game.Slug;
|
gameSlug = game.Slug;
|
||||||
}
|
}
|
||||||
string DestinationPath = Path.Combine(GameLibrary.GetDefaultLibrary.Path, gameSlug, platformSlug);
|
string DestinationPath = Path.Combine(GameLibrary.GetDefaultLibrary.Path, platformSlug);
|
||||||
if (!Directory.Exists(DestinationPath))
|
if (!Directory.Exists(DestinationPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(DestinationPath);
|
Directory.CreateDirectory(DestinationPath);
|
||||||
|
@@ -1110,8 +1110,10 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
|
|
||||||
public async Task<string> GetSpecificImageFromServer(string ImagePath, string ImageId, IGDBAPI_ImageSize size, List<IGDBAPI_ImageSize>? FallbackSizes = null)
|
public async Task<string> GetSpecificImageFromServer(string ImagePath, string ImageId, IGDBAPI_ImageSize size, List<IGDBAPI_ImageSize>? FallbackSizes = null)
|
||||||
{
|
{
|
||||||
string originalPath = Path.Combine(ImagePath, IGDBAPI_ImageSize.original.ToString(), ImageId + ".jpg");
|
string originalPath = Path.Combine(ImagePath, _MetadataSource.ToString(), IGDBAPI_ImageSize.original.ToString());
|
||||||
string requestedPath = Path.Combine(ImagePath, size.ToString(), ImageId + ".jpg");
|
string originalFilePath = Path.Combine(originalPath, ImageId);
|
||||||
|
string requestedPath = Path.Combine(ImagePath, _MetadataSource.ToString(), size.ToString());
|
||||||
|
string requestedFilePath = Path.Combine(requestedPath, ImageId);
|
||||||
|
|
||||||
// create the directory if it doesn't exist
|
// create the directory if it doesn't exist
|
||||||
if (!Directory.Exists(Path.GetDirectoryName(originalPath)))
|
if (!Directory.Exists(Path.GetDirectoryName(originalPath)))
|
||||||
@@ -1127,7 +1129,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
Point resolution = Common.GetResolution(size);
|
Point resolution = Common.GetResolution(size);
|
||||||
|
|
||||||
// check if the original image exists
|
// check if the original image exists
|
||||||
if (!File.Exists(originalPath))
|
if (!File.Exists(originalFilePath))
|
||||||
{
|
{
|
||||||
// sleep if the rate limiter is active
|
// sleep if the rate limiter is active
|
||||||
if (RateLimitResumeTime > DateTime.UtcNow)
|
if (RateLimitResumeTime > DateTime.UtcNow)
|
||||||
@@ -1147,14 +1149,21 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
Communications comms = new Communications();
|
Communications comms = new Communications();
|
||||||
switch (_MetadataSource)
|
switch (_MetadataSource)
|
||||||
{
|
{
|
||||||
|
case HasheousClient.Models.MetadataSources.None:
|
||||||
|
await comms.API_GetURL(ImageId, originalPath);
|
||||||
|
|
||||||
|
return originalFilePath;
|
||||||
|
|
||||||
case HasheousClient.Models.MetadataSources.IGDB:
|
case HasheousClient.Models.MetadataSources.IGDB:
|
||||||
|
originalFilePath = originalFilePath + ".jpg";
|
||||||
|
requestedFilePath = requestedFilePath + ".jpg";
|
||||||
if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false)
|
if (Config.MetadataConfiguration.MetadataUseHasheousProxy == false)
|
||||||
{
|
{
|
||||||
await comms.IGDBAPI_GetImage(ImageId, ImagePath);
|
await comms.IGDBAPI_GetImage(ImageId, originalPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await comms.HasheousAPI_GetImage(ImageId, ImagePath);
|
await comms.HasheousAPI_GetImage(ImageId, originalPath);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1164,10 +1173,10 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if the requested image exists
|
// check if the requested image exists
|
||||||
if (!File.Exists(requestedPath))
|
if (!File.Exists(requestedFilePath))
|
||||||
{
|
{
|
||||||
// get the original image
|
// get the original image
|
||||||
using (var image = new ImageMagick.MagickImage(originalPath))
|
using (var image = new ImageMagick.MagickImage(originalFilePath))
|
||||||
{
|
{
|
||||||
image.Resize(resolution.X, resolution.Y);
|
image.Resize(resolution.X, resolution.Y);
|
||||||
image.Strip();
|
image.Strip();
|
||||||
@@ -1175,7 +1184,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return requestedPath;
|
return requestedFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T? GetSearchCache<T>(string SearchFields, string SearchString)
|
public static T? GetSearchCache<T>(string SearchFields, string SearchString)
|
||||||
@@ -1228,6 +1237,80 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
db.ExecuteNonQuery(sql, dbDict);
|
db.ExecuteNonQuery(sql, dbDict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void PopulateHasheousPlatformData(long Id)
|
||||||
|
{
|
||||||
|
// fetch all platforms
|
||||||
|
ConfigureHasheousClient(ref hasheous);
|
||||||
|
var hasheousPlatforms = hasheous.GetPlatforms();
|
||||||
|
|
||||||
|
foreach (var hasheousPlatform in hasheousPlatforms)
|
||||||
|
{
|
||||||
|
// check the metadata attribute for a igdb platform id
|
||||||
|
if (hasheousPlatform.Metadata != null)
|
||||||
|
{
|
||||||
|
foreach (var metadata in hasheousPlatform.Metadata)
|
||||||
|
{
|
||||||
|
if (metadata.Source == HasheousClient.Models.MetadataSources.IGDB)
|
||||||
|
{
|
||||||
|
if (metadata.ImmutableId.Length > 0)
|
||||||
|
{
|
||||||
|
long objId = 0;
|
||||||
|
long.TryParse(metadata.ImmutableId, out objId);
|
||||||
|
if (objId == Id)
|
||||||
|
{
|
||||||
|
// we have a match - check hasheousPlatform attributes for a logo
|
||||||
|
foreach (var hasheousPlatformAttribute in hasheousPlatform.Attributes)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
hasheousPlatformAttribute.attributeType == HasheousClient.Models.AttributeItem.AttributeType.ImageId &&
|
||||||
|
hasheousPlatformAttribute.attributeName == HasheousClient.Models.AttributeItem.AttributeName.Logo &&
|
||||||
|
hasheousPlatformAttribute.Value != null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Uri logoUrl = new Uri(
|
||||||
|
new Uri(HasheousClient.WebApp.HttpHelper.BaseUri, UriKind.Absolute),
|
||||||
|
new Uri("/api/v1/images/" + hasheousPlatformAttribute.Value, UriKind.Relative));
|
||||||
|
|
||||||
|
// generate a platform logo object
|
||||||
|
HasheousClient.Models.Metadata.IGDB.PlatformLogo platformLogo = new HasheousClient.Models.Metadata.IGDB.PlatformLogo
|
||||||
|
{
|
||||||
|
AlphaChannel = false,
|
||||||
|
Animated = false,
|
||||||
|
ImageId = (string)hasheousPlatformAttribute.Value,
|
||||||
|
Url = logoUrl.ToString()
|
||||||
|
};
|
||||||
|
|
||||||
|
// generate a long id from the value
|
||||||
|
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(platformLogo.ImageId);
|
||||||
|
long longId = BitConverter.ToInt64(bytes, 0);
|
||||||
|
platformLogo.Id = longId;
|
||||||
|
|
||||||
|
// store the platform logo object
|
||||||
|
Storage.CacheStatus cacheStatus = Storage.GetCacheStatus(HasheousClient.Models.MetadataSources.None, "PlatformLogo", longId);
|
||||||
|
switch (cacheStatus)
|
||||||
|
{
|
||||||
|
case Storage.CacheStatus.NotPresent:
|
||||||
|
Storage.NewCacheValue<PlatformLogo>(HasheousClient.Models.MetadataSources.None, platformLogo, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the platform object
|
||||||
|
Platform? platform = Platforms.GetPlatform(Id);
|
||||||
|
if (platform != null)
|
||||||
|
{
|
||||||
|
platform.PlatformLogo = platformLogo.Id;
|
||||||
|
Storage.NewCacheValue<Platform>(HasheousClient.Models.MetadataSources.None, platform, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// See https://api-docs.igdb.com/?javascript#images for more information about the image url structure
|
/// See https://api-docs.igdb.com/?javascript#images for more information about the image url structure
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1238,9 +1321,8 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
string urlTemplate = "https://images.igdb.com/igdb/image/upload/t_{size}/{hash}.jpg";
|
string urlTemplate = "https://images.igdb.com/igdb/image/upload/t_{size}/{hash}.jpg";
|
||||||
|
|
||||||
string url = urlTemplate.Replace("{size}", "original").Replace("{hash}", ImageId);
|
string url = urlTemplate.Replace("{size}", "original").Replace("{hash}", ImageId);
|
||||||
string newOutputPath = Path.Combine(OutputPath, "original");
|
|
||||||
string OutputFile = ImageId + ".jpg";
|
string OutputFile = ImageId + ".jpg";
|
||||||
string fullPath = Path.Combine(newOutputPath, OutputFile);
|
string fullPath = Path.Combine(OutputPath, OutputFile);
|
||||||
|
|
||||||
await _DownloadFile(new Uri(url), fullPath);
|
await _DownloadFile(new Uri(url), fullPath);
|
||||||
}
|
}
|
||||||
@@ -1250,9 +1332,19 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
string urlTemplate = HasheousClient.WebApp.HttpHelper.BaseUri + "api/v1/MetadataProxy/IGDB/Image/{hash}.jpg";
|
string urlTemplate = HasheousClient.WebApp.HttpHelper.BaseUri + "api/v1/MetadataProxy/IGDB/Image/{hash}.jpg";
|
||||||
|
|
||||||
string url = urlTemplate.Replace("{hash}", ImageId);
|
string url = urlTemplate.Replace("{hash}", ImageId);
|
||||||
string newOutputPath = Path.Combine(OutputPath, "original");
|
|
||||||
string OutputFile = ImageId + ".jpg";
|
string OutputFile = ImageId + ".jpg";
|
||||||
string fullPath = Path.Combine(newOutputPath, OutputFile);
|
string fullPath = Path.Combine(OutputPath, OutputFile);
|
||||||
|
|
||||||
|
await _DownloadFile(new Uri(url), fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task API_GetURL(string FileName, string OutputPath)
|
||||||
|
{
|
||||||
|
string urlTemplate = HasheousClient.WebApp.HttpHelper.BaseUri + "api/v1/images/{imageid}";
|
||||||
|
|
||||||
|
string url = urlTemplate.Replace("{imageid}", FileName);
|
||||||
|
string OutputFile = FileName;
|
||||||
|
string fullPath = Path.Combine(OutputPath, OutputFile);
|
||||||
|
|
||||||
await _DownloadFile(new Uri(url), fullPath);
|
await _DownloadFile(new Uri(url), fullPath);
|
||||||
}
|
}
|
||||||
|
@@ -294,12 +294,24 @@ ORDER BY Platform.`Name`;";
|
|||||||
if (platform.Id != 0)
|
if (platform.Id != 0)
|
||||||
{
|
{
|
||||||
Models.PlatformMapping.PlatformMapItem platformMap = PlatformMapping.GetPlatformMap((long)platform.Id);
|
Models.PlatformMapping.PlatformMapItem platformMap = PlatformMapping.GetPlatformMap((long)platform.Id);
|
||||||
emulatorConfiguration = new PlatformMapping.UserEmulatorConfiguration
|
if (platformMap != null)
|
||||||
{
|
{
|
||||||
EmulatorType = platformMap.WebEmulator.Type,
|
emulatorConfiguration = new PlatformMapping.UserEmulatorConfiguration
|
||||||
Core = platformMap.WebEmulator.Core,
|
{
|
||||||
EnableBIOSFiles = platformMap.EnabledBIOSHashes
|
EmulatorType = platformMap.WebEmulator.Type,
|
||||||
};
|
Core = platformMap.WebEmulator.Core,
|
||||||
|
EnableBIOSFiles = platformMap.EnabledBIOSHashes
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emulatorConfiguration = new PlatformMapping.UserEmulatorConfiguration
|
||||||
|
{
|
||||||
|
EmulatorType = "",
|
||||||
|
Core = "",
|
||||||
|
EnableBIOSFiles = new List<string>()
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -93,21 +93,13 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
// check cached metadata status
|
// check cached metadata status
|
||||||
// if metadata is not cached or expired, get it from the source. Otherwise, return the cached metadata
|
// if metadata is not cached or expired, get it from the source. Otherwise, return the cached metadata
|
||||||
Storage.CacheStatus? cacheStatus;
|
Storage.CacheStatus? cacheStatus;
|
||||||
if (SourceType == HasheousClient.Models.MetadataSources.None)
|
if (idType == IdType.Long)
|
||||||
{
|
{
|
||||||
// if source is None, set cache status to current
|
cacheStatus = Storage.GetCacheStatus(SourceType, type, (long)Id);
|
||||||
cacheStatus = Storage.CacheStatus.Current;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (idType == IdType.Long)
|
cacheStatus = Storage.GetCacheStatus(SourceType, type, (string)Id);
|
||||||
{
|
|
||||||
cacheStatus = Storage.GetCacheStatus(SourceType, type, (long)Id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cacheStatus = Storage.GetCacheStatus(SourceType, type, (string)Id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ForceRefresh is true, set cache status to expired if it is current
|
// if ForceRefresh is true, set cache status to expired if it is current
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using HasheousClient.Models.Metadata.IGDB;
|
using HasheousClient.Models.Metadata.IGDB;
|
||||||
|
using static gaseous_server.Models.PlatformMapping;
|
||||||
|
|
||||||
|
|
||||||
namespace gaseous_server.Classes.Metadata
|
namespace gaseous_server.Classes.Metadata
|
||||||
@@ -12,7 +13,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlatformLogo? GetPlatformLogo(long? Id)
|
public static PlatformLogo? GetPlatformLogo(long? Id, HasheousClient.Models.MetadataSources SourceType = HasheousClient.Models.MetadataSources.IGDB)
|
||||||
{
|
{
|
||||||
if ((Id == 0) || (Id == null))
|
if ((Id == 0) || (Id == null))
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PlatformLogo? RetVal = Metadata.GetMetadata<PlatformLogo>(HasheousClient.Models.MetadataSources.IGDB, (long)Id, false);
|
PlatformLogo? RetVal = Metadata.GetMetadata<PlatformLogo>(SourceType, (long)Id, false);
|
||||||
return RetVal;
|
return RetVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,16 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Platform? RetVal = Metadata.GetMetadata<Platform>(HasheousClient.Models.MetadataSources.IGDB, (long)Id, false);
|
Platform? RetVal = new Platform();
|
||||||
|
if (Config.MetadataConfiguration.DefaultMetadataSource == HasheousClient.Models.MetadataSources.None)
|
||||||
|
{
|
||||||
|
|
||||||
|
RetVal = (Platform?)Storage.GetCacheValue<Platform>(HasheousClient.Models.MetadataSources.None, RetVal, "Id", (long)Id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RetVal = Metadata.GetMetadata<Platform>(HasheousClient.Models.MetadataSources.IGDB, (long)Id, false);
|
||||||
|
}
|
||||||
return RetVal;
|
return RetVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -127,7 +127,7 @@ namespace gaseous_server.Controllers
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
logoObject = PlatformLogos.GetPlatformLogo((long)platformObject.PlatformLogo);
|
logoObject = PlatformLogos.GetPlatformLogo((long)platformObject.PlatformLogo, Communications.MetadataSource);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -141,17 +141,17 @@ namespace gaseous_server.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return NotFound();
|
return GetDummyImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return NotFound();
|
return GetDummyImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(platformObject));
|
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(platformObject), Communications.MetadataSource.ToString());
|
||||||
string imagePath = Path.Combine(basePath, size.ToString(), logoObject.ImageId + ".jpg");
|
string imagePath = Path.Combine(basePath, size.ToString(), logoObject.ImageId);
|
||||||
|
|
||||||
if (!System.IO.File.Exists(imagePath))
|
if (!System.IO.File.Exists(imagePath))
|
||||||
{
|
{
|
||||||
@@ -171,9 +171,71 @@ namespace gaseous_server.Controllers
|
|||||||
|
|
||||||
if (System.IO.File.Exists(imagePath))
|
if (System.IO.File.Exists(imagePath))
|
||||||
{
|
{
|
||||||
string filename = logoObject.ImageId + ".jpg";
|
// get image info
|
||||||
|
var info = new ImageMagick.MagickImageInfo(imagePath);
|
||||||
|
string extension = ".jpg";
|
||||||
|
string mimeType = "image/jpg";
|
||||||
|
switch (info.Format)
|
||||||
|
{
|
||||||
|
case ImageMagick.MagickFormat.Jpeg:
|
||||||
|
extension = ".jpg";
|
||||||
|
mimeType = "image/jpg";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageMagick.MagickFormat.Png:
|
||||||
|
extension = ".png";
|
||||||
|
mimeType = "image/png";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageMagick.MagickFormat.Gif:
|
||||||
|
extension = ".gif";
|
||||||
|
mimeType = "image/gif";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageMagick.MagickFormat.Bmp:
|
||||||
|
extension = ".bmp";
|
||||||
|
mimeType = "image/bmp";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageMagick.MagickFormat.Tiff:
|
||||||
|
extension = ".tiff";
|
||||||
|
mimeType = "image/tiff";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageMagick.MagickFormat.Unknown:
|
||||||
|
extension = ".jpg";
|
||||||
|
mimeType = "image/jpg";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageMagick.MagickFormat.WebP:
|
||||||
|
extension = ".webp";
|
||||||
|
mimeType = "image/webp";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageMagick.MagickFormat.Heic:
|
||||||
|
extension = ".heic";
|
||||||
|
mimeType = "image/heic";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageMagick.MagickFormat.Heif:
|
||||||
|
extension = ".heif";
|
||||||
|
mimeType = "image/heif";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ImageMagick.MagickFormat.Svg:
|
||||||
|
extension = ".svg";
|
||||||
|
mimeType = "image/svg+xml";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
extension = ".jpg";
|
||||||
|
mimeType = "image/jpg";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
string filename = logoObject.ImageId + extension;
|
||||||
string filepath = imagePath;
|
string filepath = imagePath;
|
||||||
string contentType = "image/jpg";
|
string contentType = mimeType;
|
||||||
|
|
||||||
var cd = new System.Net.Mime.ContentDisposition
|
var cd = new System.Net.Mime.ContentDisposition
|
||||||
{
|
{
|
||||||
@@ -195,14 +257,60 @@ namespace gaseous_server.Controllers
|
|||||||
|
|
||||||
return File(filedata, contentType);
|
return File(filedata, contentType);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return NotFound();
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ActionResult GetDummyImage()
|
||||||
|
{
|
||||||
|
// return resource named DefaultPlatformLogo.svg
|
||||||
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
|
string resourceName = "gaseous_server.Support.DefaultPlatformLogo.svg";
|
||||||
|
string[] resources = Assembly.GetExecutingAssembly().GetManifestResourceNames();
|
||||||
|
if (resources.Contains(resourceName))
|
||||||
|
{
|
||||||
|
string svgData = "";
|
||||||
|
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||||
|
using (StreamReader reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
svgData = reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
var cd = new System.Net.Mime.ContentDisposition
|
||||||
|
{
|
||||||
|
FileName = "DefaultPlatformLogo.svg",
|
||||||
|
Inline = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
Response.Headers.Add("Content-Disposition", cd.ToString());
|
||||||
|
Response.Headers.Add("Cache-Control", "public, max-age=604800");
|
||||||
|
|
||||||
|
byte[] filedata = null;
|
||||||
|
using (MemoryStream ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
using (StreamWriter writer = new StreamWriter(ms))
|
||||||
|
{
|
||||||
|
writer.Write(svgData);
|
||||||
|
writer.Flush();
|
||||||
|
ms.Position = 0;
|
||||||
|
filedata = ms.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return File(filedata, "image/svg+xml");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -102,9 +102,16 @@ namespace gaseous_server.Models
|
|||||||
AlternativeName = mapItem.AlternateNames.FirstOrDefault()
|
AlternativeName = mapItem.AlternateNames.FirstOrDefault()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Storage.GetCacheStatus(Communications.MetadataSource, "Platform", mapItem.IGDBId) == Storage.CacheStatus.NotPresent)
|
if (Storage.GetCacheStatus(HasheousClient.Models.MetadataSources.None, "Platform", mapItem.IGDBId) == Storage.CacheStatus.NotPresent)
|
||||||
{
|
{
|
||||||
Storage.NewCacheValue(Communications.MetadataSource, platform);
|
Storage.NewCacheValue(HasheousClient.Models.MetadataSources.None, platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
Communications.PopulateHasheousPlatformData(mapItem.IGDBId);
|
||||||
|
|
||||||
|
if (Storage.GetCacheStatus(HasheousClient.Models.MetadataSources.IGDB, "Platform", mapItem.IGDBId) == Storage.CacheStatus.NotPresent)
|
||||||
|
{
|
||||||
|
Storage.NewCacheValue(HasheousClient.Models.MetadataSources.IGDB, platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
return platform;
|
return platform;
|
||||||
|
@@ -54,6 +54,21 @@ namespace gaseous_server.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_flags.PlatformId == 0)
|
||||||
|
{
|
||||||
|
// fall back to the IGDB source if present
|
||||||
|
foreach (SourceValues.SourceValueItem source in MetadataSources.Platforms)
|
||||||
|
{
|
||||||
|
if (source.Source == HasheousClient.Models.MetadataSources.IGDB)
|
||||||
|
{
|
||||||
|
_flags.PlatformId = source.Id;
|
||||||
|
_flags.PlatformName = source.Name;
|
||||||
|
_flags.PlatformMetadataSource = source.Source;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (SourceValues.SourceValueItem source in MetadataSources.Games)
|
foreach (SourceValues.SourceValueItem source in MetadataSources.Games)
|
||||||
{
|
{
|
||||||
if (source.Source == Config.MetadataConfiguration.DefaultMetadataSource)
|
if (source.Source == Config.MetadataConfiguration.DefaultMetadataSource)
|
||||||
@@ -65,6 +80,13 @@ namespace gaseous_server.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_flags.GameId == null || _flags.GameId == 0)
|
||||||
|
{
|
||||||
|
_flags.GameId = 0;
|
||||||
|
_flags.GameName = "Unknown Game";
|
||||||
|
_flags.GameMetadataSource = HasheousClient.Models.MetadataSources.None;
|
||||||
|
}
|
||||||
|
|
||||||
return _flags;
|
return _flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
gaseous-server/Support/DefaultPlatformLogo.svg
Normal file
3
gaseous-server/Support/DefaultPlatformLogo.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M403.2 803.2c-0.8 0-8.8 64-9.6 65.6-1.6 13.6-4 21.6-11.2 28-2.4 2.4-4.8 3.2-7.2 4.8-5.6 4-10.4 6.4-16.8 10.4-4.8 2.4-10.4 12-4.8 14.4h316.8c5.6-2.4 0-11.2-4.8-13.6-6.4-4-11.2-7.2-16.8-12-2.4-1.6-4.8-4-7.2-6.4-6.4-6.4-9.6-12-11.2-25.6 0-1.6-9.6-71.2-9.6-65.6" fill="#D2D5D6" /><path d="M992 704.8V124c0-14.4-11.2-26.4-25.6-26.4H57.6c-14.4 0-25.6 12-25.6 26.4v581.6" fill="#938993" /><path d="M84 149.6h856v503.2h-856z" fill="#E2D3E2" /><path d="M376 137.6l576 528v-528z" fill="#FAFBFA" /><path d="M32 704v72.8c0 14.4 11.2 26.4 25.6 26.4h908c14.4 0 25.6-12 25.6-26.4V704" fill="#D2D5D6" /><path d="M511.2 754.4m-24 0a24 24 0 1 0 48 0 24 24 0 1 0-48 0Z" fill="#414343" /><path d="M623.2 827.2c-0.8-24-1.6-24-1.6-24H404s-0.8 0-1.6 24h220.8z" fill="#0D1014" /><path d="M449.6 568.8l-1.6 4z" fill="#99D9E6" /><path d="M353.6 934.4c-0.8 0-2.4 0-3.2-0.8-4-1.6-7.2-5.6-7.2-10.4 0-8 6.4-16 11.2-18.4l3.2-1.6c4.8-2.4 8.8-4.8 12-8 1.6-0.8 2.4-1.6 4-2.4 0.8-0.8 1.6-0.8 2.4-1.6 4.8-4 6.4-10.4 8-22.4 8-67.2 8-67.2 16-67.2 4.8 0 8 3.2 8 8v2.4c-0.8 5.6-7.2 54.4-8 58.4-1.6 14.4-4.8 24.8-13.6 32.8-1.6 1.6-4 3.2-5.6 4-0.8 0.8-1.6 0.8-2.4 1.6-4.8 4-9.6 6.4-14.4 8.8l-3.2 1.6H656c-5.6-3.2-10.4-7.2-15.2-10.4-1.6-1.6-3.2-3.2-5.6-4.8l-2.4-1.6c-8.8-8-12-16.8-13.6-30.4-0.8-4-6.4-48.8-8-58.4 0-0.8-0.8-1.6-0.8-3.2 0-4 3.2-8 7.2-8.8 8.8-0.8 8.8-0.8 16.8 67.2 1.6 12.8 4 16.8 8 20.8l2.4 2.4c1.6 1.6 3.2 2.4 4 4 5.6 4 9.6 7.2 16 11.2 4.8 2.4 12 10.4 11.2 17.6 0 4.8-3.2 8-7.2 10.4-0.8 0.8-2.4 0.8-3.2 0.8l-312-1.6zM992 712.8c-4.8 0-8-3.2-8-8V124c0-10.4-8-18.4-17.6-18.4H57.6c-9.6 0-17.6 8-17.6 18.4v581.6c0 4.8-3.2 8-8 8s-8-3.2-8-8V124c0-19.2 15.2-34.4 33.6-34.4h908c18.4 0 33.6 15.2 33.6 34.4v581.6c0.8 4-2.4 7.2-7.2 7.2z" fill="#6A576D" /><path d="M940 660.8h-856c-4.8 0-8-3.2-8-8V149.6c0-4.8 3.2-8 8-8h856c4.8 0 8 3.2 8 8v503.2c0 4.8-4 8-8 8z m-848-16h840V157.6h-840v487.2zM966.4 811.2H57.6c-18.4 0-33.6-15.2-33.6-34.4V704c0-4.8 3.2-8 8-8h960c4.8 0 8 3.2 8 8v72.8c0 19.2-15.2 34.4-33.6 34.4zM40 712v64.8c0 10.4 8 18.4 17.6 18.4h908c9.6 0 17.6-8 17.6-18.4V712H40z" fill="#6A576D" /></svg>
|
After Width: | Height: | Size: 2.3 KiB |
@@ -20,7 +20,7 @@
|
|||||||
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
|
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
|
||||||
<PackageReference Include="gaseous-signature-parser" Version="2.3.0" />
|
<PackageReference Include="gaseous-signature-parser" Version="2.3.0" />
|
||||||
<PackageReference Include="gaseous.IGDB" Version="1.0.2" />
|
<PackageReference Include="gaseous.IGDB" Version="1.0.2" />
|
||||||
<PackageReference Include="hasheous-client" Version="1.2.1" />
|
<PackageReference Include="hasheous-client" Version="1.2.2" />
|
||||||
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.8.0" />
|
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.8.0" />
|
||||||
<PackageReference Include="sharpcompress" Version="0.37.2" />
|
<PackageReference Include="sharpcompress" Version="0.37.2" />
|
||||||
<PackageReference Include="Squid-Box.SevenZipSharp" Version="1.6.2.24" />
|
<PackageReference Include="Squid-Box.SevenZipSharp" Version="1.6.2.24" />
|
||||||
@@ -92,6 +92,7 @@
|
|||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Support\Country.txt" />
|
<EmbeddedResource Include="Support\Country.txt" />
|
||||||
<EmbeddedResource Include="Support\Language.txt" />
|
<EmbeddedResource Include="Support\Language.txt" />
|
||||||
|
<EmbeddedResource Include="Support\DefaultPlatformLogo.svg" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1000.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1000.sql" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1001.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1001.sql" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1002.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1002.sql" />
|
||||||
|
@@ -15,6 +15,7 @@ function loadPlatformMapping(Overwrite) {
|
|||||||
createTableRow(
|
createTableRow(
|
||||||
true,
|
true,
|
||||||
[
|
[
|
||||||
|
'',
|
||||||
'Platform',
|
'Platform',
|
||||||
'Supported File Extensions',
|
'Supported File Extensions',
|
||||||
'Unique File Extensions',
|
'Unique File Extensions',
|
||||||
@@ -27,6 +28,12 @@ function loadPlatformMapping(Overwrite) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (let i = 0; i < result.length; i++) {
|
for (let i = 0; i < result.length; i++) {
|
||||||
|
let logo = document.createElement('img');
|
||||||
|
logo.src = '/api/v1.1/Platforms/' + result[i].igdbId + '/platformlogo/original/logo.png';
|
||||||
|
logo.alt = result[i].igdbName;
|
||||||
|
logo.title = result[i].igdbName;
|
||||||
|
logo.classList.add('platform_image');
|
||||||
|
|
||||||
let hasWebEmulator = '';
|
let hasWebEmulator = '';
|
||||||
if (result[i].webEmulator.type.length > 0) {
|
if (result[i].webEmulator.type.length > 0) {
|
||||||
hasWebEmulator = 'Yes';
|
hasWebEmulator = 'Yes';
|
||||||
@@ -49,6 +56,7 @@ function loadPlatformMapping(Overwrite) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let newRow = [
|
let newRow = [
|
||||||
|
logo,
|
||||||
result[i].igdbName,
|
result[i].igdbName,
|
||||||
result[i].extensions.supportedFileExtensions.join(', '),
|
result[i].extensions.supportedFileExtensions.join(', '),
|
||||||
result[i].extensions.uniqueFileExtensions.join(', '),
|
result[i].extensions.uniqueFileExtensions.join(', '),
|
||||||
|
@@ -2930,6 +2930,7 @@ button:not(.select2-selection__choice__remove):not(.select2-selection__clear):no
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
|
padding-left: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -2946,15 +2947,24 @@ button:not(.select2-selection__choice__remove):not(.select2-selection__clear):no
|
|||||||
.platform_item_background:hover {}
|
.platform_item_background:hover {}
|
||||||
|
|
||||||
.platform_image_container {
|
.platform_image_container {
|
||||||
margin-left: 10px;
|
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
max-width: 50px;
|
width: 70px;
|
||||||
max-height: 50px;
|
height: 70px;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
/* text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: 75px; */
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.platform_image {
|
.platform_image {
|
||||||
width: 40px;
|
width: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.platform_name_container {
|
.platform_name_container {
|
||||||
|
Reference in New Issue
Block a user