Add a Platform Map editor to the UI (#104)
This commit is contained in:
@@ -437,7 +437,7 @@ namespace gaseous_server.Classes
|
||||
case CollectionItem.FolderStructures.RetroPie:
|
||||
try
|
||||
{
|
||||
PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMappingByIGDBid(collectionPlatformItem.Id);
|
||||
PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(collectionPlatformItem.Id);
|
||||
ZipPlatformPath = Path.Combine(ZipFileTempPath, "roms", platformMapItem.RetroPieDirectoryName);
|
||||
}
|
||||
catch
|
||||
|
@@ -22,7 +22,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Platform? GetPlatform(long Id)
|
||||
public static Platform? GetPlatform(long Id, bool forceRefresh = false)
|
||||
{
|
||||
if (Id == 0)
|
||||
{
|
||||
@@ -46,18 +46,18 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<Platform> RetVal = _GetPlatform(SearchUsing.id, Id);
|
||||
Task<Platform> RetVal = _GetPlatform(SearchUsing.id, Id, forceRefresh);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static Platform GetPlatform(string Slug)
|
||||
public static Platform GetPlatform(string Slug, bool forceRefresh = false)
|
||||
{
|
||||
Task<Platform> RetVal = _GetPlatform(SearchUsing.slug, Slug);
|
||||
Task<Platform> RetVal = _GetPlatform(SearchUsing.slug, Slug, forceRefresh);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<Platform> _GetPlatform(SearchUsing searchUsing, object searchValue)
|
||||
private static async Task<Platform> _GetPlatform(SearchUsing searchUsing, object searchValue, bool forceRefresh)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
@@ -70,6 +70,11 @@ namespace gaseous_server.Classes.Metadata
|
||||
cacheStatus = Storage.GetCacheStatus("Platform", (string)searchValue);
|
||||
}
|
||||
|
||||
if (forceRefresh == true)
|
||||
{
|
||||
if (cacheStatus == Storage.CacheStatus.Current) { cacheStatus = Storage.CacheStatus.Expired; }
|
||||
}
|
||||
|
||||
// set up where clause
|
||||
string WhereClause = "";
|
||||
switch (searchUsing)
|
||||
@@ -91,11 +96,13 @@ namespace gaseous_server.Classes.Metadata
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
UpdateSubClasses(returnValue);
|
||||
AddPlatformMapping(returnValue);
|
||||
return returnValue;
|
||||
case Storage.CacheStatus.Expired:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
UpdateSubClasses(returnValue);
|
||||
AddPlatformMapping(returnValue);
|
||||
return returnValue;
|
||||
case Storage.CacheStatus.Current:
|
||||
return Storage.GetCacheValue<Platform>(returnValue, "id", (long)searchValue);
|
||||
@@ -120,6 +127,31 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddPlatformMapping(Platform platform)
|
||||
{
|
||||
// ensure a mapping item exists for this platform
|
||||
Models.PlatformMapping.PlatformMapItem item = new Models.PlatformMapping.PlatformMapItem();
|
||||
try
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Checking if " + platform.Name + " is in database.");
|
||||
item = Models.PlatformMapping.GetPlatformMap((long)platform.Id);
|
||||
// exists - skip
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Skipping import of " + platform.Name + " - already in database.");
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + platform.Name + " from predefined data.");
|
||||
// doesn't exist - add it
|
||||
item = new Models.PlatformMapping.PlatformMapItem{
|
||||
IGDBId = (long)platform.Id,
|
||||
IGDBName = platform.Name,
|
||||
IGDBSlug = platform.Slug,
|
||||
AlternateNames = new List<string>{ platform.AlternativeName }
|
||||
};
|
||||
Models.PlatformMapping.WritePlatformMap(item, false);
|
||||
}
|
||||
}
|
||||
|
||||
private enum SearchUsing
|
||||
{
|
||||
id,
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using gaseous_server.Models;
|
||||
using gaseous_tools;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
@@ -9,8 +10,29 @@ namespace gaseous_server.Classes
|
||||
public static void RefreshMetadata(bool forceRefresh = false)
|
||||
{
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT Id, `Name` FROM Game;";
|
||||
DataTable dt = db.ExecuteCMD(sql);
|
||||
string sql = "";
|
||||
DataTable dt = new DataTable();
|
||||
|
||||
// update platforms
|
||||
sql = "SELECT Id, `Name` FROM Platform;";
|
||||
dt = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dt.Rows)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Metadata Refresh", "Refreshing metadata for platform " + dr["name"] + " (" + dr["id"] + ")");
|
||||
Metadata.Platforms.GetPlatform((long)dr["id"], true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Metadata Refresh", "An error occurred while refreshing metadata for " + dr["name"], ex);
|
||||
}
|
||||
}
|
||||
|
||||
// update games
|
||||
sql = "SELECT Id, `Name` FROM Game;";
|
||||
dt = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dt.Rows)
|
||||
{
|
||||
|
166
gaseous-server/Controllers/PlatformMapsController.cs
Normal file
166
gaseous-server/Controllers/PlatformMapsController.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Models;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[Route("api/v1/[controller]")]
|
||||
[ApiController]
|
||||
public class PlatformMapsController : Controller
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(List<PlatformMapping.PlatformMapItem>), StatusCodes.Status200OK)]
|
||||
public ActionResult GetPlatformMap(bool ResetToDefault = false)
|
||||
{
|
||||
if (ResetToDefault == true)
|
||||
{
|
||||
PlatformMapping.ExtractPlatformMap(true);
|
||||
}
|
||||
|
||||
return Ok(PlatformMapping.PlatformMap);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("{PlatformId}")]
|
||||
[ProducesResponseType(typeof(PlatformMapping.PlatformMapItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult PlatformMap(long PlatformId)
|
||||
{
|
||||
try
|
||||
{
|
||||
PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(PlatformId);
|
||||
|
||||
if (platformMapItem != null)
|
||||
{
|
||||
return Ok(platformMapItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(List<IFormFile>), StatusCodes.Status200OK)]
|
||||
[RequestSizeLimit(long.MaxValue)]
|
||||
[DisableRequestSizeLimit, RequestFormLimits(MultipartBodyLengthLimit = long.MaxValue, ValueLengthLimit = int.MaxValue)]
|
||||
public async Task<IActionResult> UploadPlatformMap(List<IFormFile> files)
|
||||
{
|
||||
Guid sessionid = Guid.NewGuid();
|
||||
|
||||
string workPath = Path.Combine(Config.LibraryConfiguration.LibraryUploadDirectory, sessionid.ToString());
|
||||
|
||||
long size = files.Sum(f => f.Length);
|
||||
|
||||
List<Dictionary<string, object>> UploadedFiles = new List<Dictionary<string, object>>();
|
||||
|
||||
foreach (IFormFile formFile in files)
|
||||
{
|
||||
if (formFile.Length > 0)
|
||||
{
|
||||
Guid FileId = Guid.NewGuid();
|
||||
|
||||
string filePath = Path.Combine(workPath, Path.GetFileName(formFile.FileName));
|
||||
|
||||
if (!Directory.Exists(workPath))
|
||||
{
|
||||
Directory.CreateDirectory(workPath);
|
||||
}
|
||||
|
||||
using (var stream = System.IO.File.Create(filePath))
|
||||
{
|
||||
await formFile.CopyToAsync(stream);
|
||||
|
||||
Dictionary<string, object> UploadedFile = new Dictionary<string, object>();
|
||||
UploadedFile.Add("id", FileId.ToString());
|
||||
UploadedFile.Add("originalname", Path.GetFileName(formFile.FileName));
|
||||
UploadedFile.Add("fullpath", filePath);
|
||||
UploadedFiles.Add(UploadedFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process uploaded files
|
||||
foreach (Dictionary<string, object> UploadedFile in UploadedFiles)
|
||||
{
|
||||
Models.PlatformMapping.ExtractPlatformMap((string)UploadedFile["fullpath"]);
|
||||
}
|
||||
|
||||
if (Directory.Exists(workPath))
|
||||
{
|
||||
Directory.Delete(workPath, true);
|
||||
}
|
||||
|
||||
return Ok(new { count = files.Count, size });
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("{PlatformId}")]
|
||||
[ProducesResponseType(typeof(PlatformMapping.PlatformMapItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
||||
public ActionResult NewPlatformMap(long PlatformId, PlatformMapping.PlatformMapItem Map)
|
||||
{
|
||||
try
|
||||
{
|
||||
PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(PlatformId);
|
||||
|
||||
if (platformMapItem != null)
|
||||
{
|
||||
return Conflict();
|
||||
}
|
||||
else
|
||||
{
|
||||
PlatformMapping.WritePlatformMap(Map, false);
|
||||
return Ok(PlatformMapping.GetPlatformMap(PlatformId));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPatch]
|
||||
[Route("{PlatformId}")]
|
||||
[ProducesResponseType(typeof(PlatformMapping.PlatformMapItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult EditPlatformMap(long PlatformId, PlatformMapping.PlatformMapItem Map)
|
||||
{
|
||||
try
|
||||
{
|
||||
PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(PlatformId);
|
||||
|
||||
if (platformMapItem != null)
|
||||
{
|
||||
PlatformMapping.WritePlatformMap(Map, true);
|
||||
return Ok(PlatformMapping.GetPlatformMap(PlatformId));
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Models;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@@ -21,6 +22,11 @@ namespace gaseous_server.Controllers
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(List<Platform>), StatusCodes.Status200OK)]
|
||||
public ActionResult Platform()
|
||||
{
|
||||
return Ok(PlatformsController.GetPlatforms());
|
||||
}
|
||||
|
||||
public static List<Platform> GetPlatforms()
|
||||
{
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
@@ -34,7 +40,7 @@ namespace gaseous_server.Controllers
|
||||
RetVal.Add(Classes.Metadata.Platforms.GetPlatform((long)dr["id"]));
|
||||
}
|
||||
|
||||
return Ok(RetVal);
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
|
@@ -1,49 +1,309 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Controllers;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace gaseous_server.Models
|
||||
{
|
||||
public class PlatformMapping
|
||||
{
|
||||
public PlatformMapping()
|
||||
/// <summary>
|
||||
/// Updates the platform map from the embedded platform map resource
|
||||
/// </summary>
|
||||
public static void ExtractPlatformMap(bool ResetToDefault = false)
|
||||
{
|
||||
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("gaseous_server.Support.PlatformMap.json"))
|
||||
using (StreamReader reader = new StreamReader(stream))
|
||||
{
|
||||
string rawJson = reader.ReadToEnd();
|
||||
List<PlatformMapItem> platforms = new List<PlatformMapItem>();
|
||||
platforms = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson);
|
||||
|
||||
foreach (PlatformMapItem mapItem in platforms)
|
||||
{
|
||||
// check if it exists first - only add if it doesn't exist
|
||||
try
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Checking if " + mapItem.IGDBName + " is in database.");
|
||||
PlatformMapItem item = GetPlatformMap(mapItem.IGDBId);
|
||||
// exists
|
||||
if (ResetToDefault == false)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Skipping import of " + mapItem.IGDBName + " - already in database.");
|
||||
}
|
||||
else
|
||||
{
|
||||
WritePlatformMap(mapItem, true);
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Overwriting " + mapItem.IGDBName + " with default values.");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + mapItem.IGDBName + " from predefined data.");
|
||||
// doesn't exist - add it
|
||||
WritePlatformMap(mapItem, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the platform map from the provided file - existing items are overwritten
|
||||
/// </summary>
|
||||
/// <param name="ImportFile"></param>
|
||||
public static void ExtractPlatformMap(string ImportFile)
|
||||
{
|
||||
string rawJson = File.ReadAllText(ImportFile);
|
||||
List<PlatformMapItem> platforms = new List<PlatformMapItem>();
|
||||
platforms = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson);
|
||||
|
||||
foreach (PlatformMapItem mapItem in platforms)
|
||||
{
|
||||
try
|
||||
{
|
||||
PlatformMapItem item = GetPlatformMap(mapItem.IGDBId);
|
||||
|
||||
// still here? we must have found the item we're looking for! overwrite it
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Replacing " + mapItem.IGDBName + " from external JSON file.");
|
||||
WritePlatformMap(mapItem, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// we caught a not found error, insert a new record
|
||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + mapItem.IGDBName + " from external JSON file.");
|
||||
WritePlatformMap(mapItem, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//private static List<PlatformMapItem> _PlatformMaps = new List<PlatformMapItem>();
|
||||
public static List<PlatformMapItem> PlatformMap
|
||||
{
|
||||
get
|
||||
{
|
||||
// load platform maps from: gaseous_server.Support.PlatformMap.json
|
||||
List<PlatformMapItem> _PlatformMaps = new List<PlatformMapItem>();
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var resourceName = "gaseous_server.Support.PlatformMap.json";
|
||||
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||
using (StreamReader reader = new StreamReader(stream))
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM PlatformMap";
|
||||
DataTable data = db.ExecuteCMD(sql);
|
||||
|
||||
List<PlatformMapItem> platformMaps = new List<PlatformMapItem>();
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
string rawJson = reader.ReadToEnd();
|
||||
_PlatformMaps.Clear();
|
||||
_PlatformMaps = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson);
|
||||
platformMaps.Add(BuildPlatformMapItem(row));
|
||||
}
|
||||
|
||||
return _PlatformMaps;
|
||||
platformMaps.Sort((x, y) => x.IGDBName.CompareTo(y.IGDBName));
|
||||
|
||||
return platformMaps;
|
||||
}
|
||||
}
|
||||
|
||||
public static PlatformMapItem GetPlatformMappingByIGDBid(long Id)
|
||||
public static PlatformMapItem GetPlatformMap(long Id)
|
||||
{
|
||||
foreach (Models.PlatformMapping.PlatformMapItem platformMapping in PlatformMap)
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM PlatformMap WHERE Id = @Id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("Id", Id);
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
if (data.Rows.Count > 0)
|
||||
{
|
||||
if (platformMapping.IGDBId == Id)
|
||||
PlatformMapItem platformMap = BuildPlatformMapItem(data.Rows[0]);
|
||||
|
||||
return platformMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("");
|
||||
}
|
||||
}
|
||||
|
||||
public static void WritePlatformMap(PlatformMapItem item, bool Update)
|
||||
{
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
if (Update == false)
|
||||
{
|
||||
// insert
|
||||
sql = "INSERT INTO PlatformMap (Id, RetroPieDirectoryName, WebEmulator_Type, WebEmulator_Core) VALUES (@Id, @RetroPieDirectoryName, @WebEmulator_Type, @WebEmulator_Core)";
|
||||
}
|
||||
else
|
||||
{
|
||||
// update
|
||||
sql = "UPDATE PlatformMap SET RetroPieDirectoryName=@RetroPieDirectoryName, WebEmulator_Type=@WebEmulator_Type, WebEmulator_Core=@WebEmulator_Core WHERE Id = @Id";
|
||||
}
|
||||
dbDict.Add("Id", item.IGDBId);
|
||||
dbDict.Add("RetroPieDirectoryName", item.RetroPieDirectoryName);
|
||||
if (item.WebEmulator != null)
|
||||
{
|
||||
dbDict.Add("WebEmulator_Type", item.WebEmulator.Type);
|
||||
dbDict.Add("WebEmulator_Core", item.WebEmulator.Core);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbDict.Add("WebEmulator_Type", "");
|
||||
dbDict.Add("WebEmulator_Core", "");
|
||||
}
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
// remove existing items so they can be re-inserted
|
||||
sql = "DELETE FROM PlatformMap_AlternateNames WHERE Id = @Id; DELETE FROM PlatformMap_Extensions WHERE Id = @Id; DELETE FROM PlatformMap_UniqueExtensions WHERE Id = @Id; DELETE FROM PlatformMap_Bios WHERE Id = @Id;";
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
// insert alternate names
|
||||
if (item.AlternateNames != null)
|
||||
{
|
||||
foreach (string alternateName in item.AlternateNames)
|
||||
{
|
||||
return platformMapping;
|
||||
sql = "INSERT INTO PlatformMap_AlternateNames (Id, Name) VALUES (@Id, @Name);";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("Id", item.IGDBId);
|
||||
dbDict.Add("Name", alternateName);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Platform id not found");
|
||||
// insert extensions
|
||||
if (item.Extensions != null)
|
||||
{
|
||||
foreach (string extension in item.Extensions.SupportedFileExtensions)
|
||||
{
|
||||
sql = "INSERT INTO PlatformMap_Extensions (Id, Extension) VALUES (@Id, @Extension);";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("Id", item.IGDBId);
|
||||
dbDict.Add("Extension", extension);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
|
||||
// delete duplicates
|
||||
sql = "DELETE FROM PlatformMap_UniqueExtensions; INSERT INTO PlatformMap_UniqueExtensions SELECT * FROM PlatformMap_Extensions WHERE Extension IN (SELECT Extension FROM PlatformMap_Extensions GROUP BY Extension HAVING COUNT(Extension) = 1);";
|
||||
db.ExecuteCMD(sql);
|
||||
}
|
||||
|
||||
// insert bios
|
||||
if (item.Bios != null)
|
||||
{
|
||||
foreach (PlatformMapItem.EmulatorBiosItem biosItem in item.Bios)
|
||||
{
|
||||
sql = "INSERT INTO PlatformMap_Bios (Id, Filename, Description, Hash) VALUES (@Id, @Filename, @Description, @Hash);";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("Id", item.IGDBId);
|
||||
dbDict.Add("Filename", biosItem.filename);
|
||||
dbDict.Add("Description", biosItem.description);
|
||||
dbDict.Add("Hash", biosItem.hash);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PlatformMapItem BuildPlatformMapItem(DataRow row)
|
||||
{
|
||||
long IGDBId = (long)row["Id"];
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
string sql = "";
|
||||
|
||||
// get platform data
|
||||
IGDB.Models.Platform platform = Platforms.GetPlatform(IGDBId);
|
||||
|
||||
// get platform alternate names
|
||||
sql = "SELECT * FROM PlatformMap_AlternateNames WHERE Id = @Id ORDER BY Name";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("Id", IGDBId);
|
||||
DataTable altTable = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<string> alternateNames = new List<string>();
|
||||
foreach (DataRow altRow in altTable.Rows)
|
||||
{
|
||||
string altVal = (string)altRow["Name"];
|
||||
if (!alternateNames.Contains(altVal, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
alternateNames.Add(altVal);
|
||||
}
|
||||
}
|
||||
if (platform.AlternativeName != null)
|
||||
{
|
||||
if (!alternateNames.Contains(platform.AlternativeName, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
alternateNames.Add(platform.AlternativeName);
|
||||
}
|
||||
}
|
||||
|
||||
// get platform known extensions
|
||||
sql = "SELECT * FROM PlatformMap_Extensions WHERE Id = @Id ORDER BY Extension";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("Id", IGDBId);
|
||||
DataTable extTable = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<string> knownExtensions = new List<string>();
|
||||
foreach (DataRow extRow in extTable.Rows)
|
||||
{
|
||||
string extVal = (string)extRow["Extension"];
|
||||
if (!knownExtensions.Contains(extVal, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
knownExtensions.Add(extVal);
|
||||
}
|
||||
}
|
||||
|
||||
// get platform unique extensions
|
||||
sql = "SELECT * FROM PlatformMap_UniqueExtensions WHERE Id = @Id ORDER BY Extension";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("Id", IGDBId);
|
||||
DataTable uextTable = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<string> uniqueExtensions = new List<string>();
|
||||
foreach (DataRow uextRow in uextTable.Rows)
|
||||
{
|
||||
string uextVal = (string)uextRow["Extension"];
|
||||
if (!uniqueExtensions.Contains(uextVal, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
uniqueExtensions.Add(uextVal);
|
||||
}
|
||||
}
|
||||
|
||||
// get platform bios
|
||||
sql = "SELECT * FROM PlatformMap_Bios WHERE Id = @Id ORDER BY Filename";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("Id", IGDBId);
|
||||
DataTable biosTable = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<PlatformMapItem.EmulatorBiosItem> bioss = new List<PlatformMapItem.EmulatorBiosItem>();
|
||||
foreach (DataRow biosRow in biosTable.Rows)
|
||||
{
|
||||
PlatformMapItem.EmulatorBiosItem bios = new PlatformMapItem.EmulatorBiosItem
|
||||
{
|
||||
filename = (string)Common.ReturnValueIfNull(biosRow["Filename"], ""),
|
||||
description = (string)Common.ReturnValueIfNull(biosRow["Description"], ""),
|
||||
hash = (string)Common.ReturnValueIfNull(biosRow["Hash"], "")
|
||||
};
|
||||
bioss.Add(bios);
|
||||
}
|
||||
|
||||
// build item
|
||||
PlatformMapItem mapItem = new PlatformMapItem();
|
||||
mapItem.IGDBId = IGDBId;
|
||||
mapItem.IGDBName = platform.Name;
|
||||
mapItem.IGDBSlug = platform.Slug;
|
||||
mapItem.AlternateNames = alternateNames;
|
||||
mapItem.Extensions = new PlatformMapItem.FileExtensions{
|
||||
SupportedFileExtensions = knownExtensions,
|
||||
UniqueFileExtensions = uniqueExtensions
|
||||
};
|
||||
mapItem.RetroPieDirectoryName = (string)Common.ReturnValueIfNull(row["RetroPieDirectoryName"], "");
|
||||
mapItem.WebEmulator = new PlatformMapItem.WebEmulatorItem{
|
||||
Type = (string)Common.ReturnValueIfNull(row["WebEmulator_Type"], ""),
|
||||
Core = (string)Common.ReturnValueIfNull(row["WebEmulator_Core"], "")
|
||||
};
|
||||
mapItem.Bios = bioss;
|
||||
|
||||
return mapItem;
|
||||
}
|
||||
|
||||
public static void GetIGDBPlatformMapping(ref Models.Signatures_Games Signature, FileInfo RomFileInfo, bool SetSystemName)
|
||||
@@ -51,17 +311,20 @@ namespace gaseous_server.Models
|
||||
bool PlatformFound = false;
|
||||
foreach (Models.PlatformMapping.PlatformMapItem PlatformMapping in Models.PlatformMapping.PlatformMap)
|
||||
{
|
||||
if (PlatformMapping.KnownFileExtensions.Contains(RomFileInfo.Extension, StringComparer.OrdinalIgnoreCase))
|
||||
if (PlatformMapping.Extensions != null)
|
||||
{
|
||||
if (SetSystemName == true)
|
||||
if (PlatformMapping.Extensions.UniqueFileExtensions.Contains(RomFileInfo.Extension, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
if (Signature.Game != null) { Signature.Game.System = PlatformMapping.IGDBName; }
|
||||
}
|
||||
Signature.Flags.IGDBPlatformId = PlatformMapping.IGDBId;
|
||||
Signature.Flags.IGDBPlatformName = PlatformMapping.IGDBName;
|
||||
if (SetSystemName == true)
|
||||
{
|
||||
if (Signature.Game != null) { Signature.Game.System = PlatformMapping.IGDBName; }
|
||||
}
|
||||
Signature.Flags.IGDBPlatformId = PlatformMapping.IGDBId;
|
||||
Signature.Flags.IGDBPlatformName = PlatformMapping.IGDBName;
|
||||
|
||||
PlatformFound = true;
|
||||
break;
|
||||
PlatformFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,10 +353,19 @@ namespace gaseous_server.Models
|
||||
|
||||
public class PlatformMapItem
|
||||
{
|
||||
public int IGDBId { get; set; }
|
||||
public long IGDBId { get; set; }
|
||||
public string IGDBName { get; set; }
|
||||
public string IGDBSlug { get; set; }
|
||||
public List<string> AlternateNames { get; set; } = new List<string>();
|
||||
public List<string> KnownFileExtensions { get; set; } = new List<string>();
|
||||
|
||||
public FileExtensions Extensions { get; set; }
|
||||
public class FileExtensions
|
||||
{
|
||||
public List<string> SupportedFileExtensions { get; set; } = new List<string>();
|
||||
|
||||
public List<string> UniqueFileExtensions { get; set; } = new List<string>();
|
||||
}
|
||||
|
||||
public string RetroPieDirectoryName { get; set; }
|
||||
public WebEmulatorItem? WebEmulator { get; set; }
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using gaseous_server;
|
||||
using gaseous_server.Models;
|
||||
using gaseous_server.SignatureIngestors.XML;
|
||||
using gaseous_tools;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
@@ -141,8 +142,8 @@ Config.LibraryConfiguration.InitLibrary();
|
||||
gaseous_server.Classes.Metadata.Games.GetGame(0, false, false, false);
|
||||
gaseous_server.Classes.Metadata.Platforms.GetPlatform(0);
|
||||
|
||||
// organise library
|
||||
//gaseous_server.Classes.ImportGame.OrganiseLibrary();
|
||||
// extract platform map if not present
|
||||
PlatformMapping.ExtractPlatformMap();
|
||||
|
||||
// add background tasks
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(ProcessQueue.QueueItemType.SignatureIngestor, 60));
|
||||
|
File diff suppressed because it is too large
Load Diff
2
gaseous-server/wwwroot/images/map.svg
Normal file
2
gaseous-server/wwwroot/images/map.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M10 7L8.364 1H2.636L1 7zM7.6 2l1.09 4H2.31L3.4 2zm8.036 15l-.818 3H6v-7h8.545L14 15h9l-1.636-6h-5.728l-.818 3H6V9h4l-.273-1H1.273L1 9h4v12h9.545L14 23h9l-1.636-6zm.764-7h4.2l1.09 4h-6.38zm-1.09 12l1.09-4h4.2l1.09 4z"/><path fill="none" d="M0 0h24v24H0z"/></svg>
|
After Width: | Height: | Size: 478 B |
@@ -12,6 +12,7 @@
|
||||
<script src="/scripts/jquery.lazy.plugins.min.js"></script>
|
||||
<script src="/scripts/select2.min.js"></script>
|
||||
<script src="/scripts/dropzone.min.js"></script>
|
||||
<script src="/scripts/simpleUpload.min.js"></script>
|
||||
<script src="/scripts/main.js" type="text/javascript"></script>
|
||||
<script src="/scripts/filterformating.js" type="text/javascript"></script>
|
||||
<script src="/scripts/gamesformating.js" type="text/javascript"></script>
|
||||
|
257
gaseous-server/wwwroot/pages/dialogs/platformmapedit.html
Normal file
257
gaseous-server/wwwroot/pages/dialogs/platformmapedit.html
Normal file
@@ -0,0 +1,257 @@
|
||||
<div style="position: absolute; top: 60px; left: 10px; right: 10px; bottom: 40px; overflow-x: scroll;">
|
||||
<div style="width: 985px;">
|
||||
<h3>Title Matching</h3>
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td style="width: 25%; vertical-align: top;">
|
||||
<h4>Alternative Names</h4>
|
||||
</td>
|
||||
<td>
|
||||
<select id="mapping_edit_alternativenames" multiple="multiple" style="width: 100%;"></select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 25%; vertical-align: top;">
|
||||
<h4>Supported File Extensions</h4>
|
||||
</td>
|
||||
<td>
|
||||
<select id="mapping_edit_supportedfileextensions" multiple="multiple" style="width: 100%;"></select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Collections</h3>
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td style="width: 25%;">
|
||||
<h4>Standard Directory Naming</h4>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<input id="mapping_edit_igdbslug" readonly="readonly" type="text" style="width: 95%;"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><strong>Note</strong>: Standard directory naming uses the IGDB slug for the platform is not editable.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<h4>RetroPie Directory Naming</h4>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<input id="mapping_edit_retropie" type="text" style="width: 95%;"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Web Emulator</h3>
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td style="width: 25%;">
|
||||
<h4>Web Emulator</h4>
|
||||
</td>
|
||||
<td>
|
||||
<input id="mapping_edit_enablewebemulator" type="checkbox"><label for="mapping_edit_enablewebemulator" style="margin-left: 5px;">Enabled</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 25%;">
|
||||
<h4>Engine</h4>
|
||||
</td>
|
||||
<td>
|
||||
<select id="mapping_edit_webemulatorengine" style="width: 100%;">
|
||||
<option value="">-</option>
|
||||
<option value="EmulatorJS">EmulatorJS</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width: 25%;">
|
||||
<h4>Core</h4>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<input id="mapping_edit_webemulatorcore" type="text" style="width: 95%;"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>BIOS/Firmware</h3>
|
||||
<div id="mapping_edit_bios"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="position: absolute; height: 35px; left: 10px; right: 10px; bottom: 0px; text-align: right;">
|
||||
<button value="Ok" onclick="SubmitMappingItem();">Ok</button>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var modalContent = document.getElementsByClassName('modal-content');
|
||||
if (!modalContent[0].classList.contains('collections_modal')) {
|
||||
modalContent[0].classList.add('collections_modal');
|
||||
}
|
||||
|
||||
ajaxCall(
|
||||
'/api/v1/PlatformMaps/' + modalVariables,
|
||||
'GET',
|
||||
function (result) {
|
||||
// set heading
|
||||
document.getElementById('modal-heading').innerHTML = result.igdbName;
|
||||
|
||||
// populate page
|
||||
$('#mapping_edit_alternativenames').select2 ({
|
||||
tags: true,
|
||||
tokenSeparators: [',']
|
||||
});
|
||||
AddTokensFromList('#mapping_edit_alternativenames', result.alternateNames);
|
||||
|
||||
$('#mapping_edit_supportedfileextensions').select2 ({
|
||||
tags: true,
|
||||
tokenSeparators: [','],
|
||||
createTag: function (params) {
|
||||
if (params.term.indexOf('.') === -1) {
|
||||
// Return null to disable tag creation
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
id: params.term.toUpperCase(),
|
||||
text: params.term.toUpperCase()
|
||||
}
|
||||
}
|
||||
});
|
||||
AddTokensFromList('#mapping_edit_supportedfileextensions', result.extensions.supportedFileExtensions);
|
||||
|
||||
document.getElementById('mapping_edit_igdbslug').value = result.igdbSlug;
|
||||
document.getElementById('mapping_edit_retropie').value = result.retroPieDirectoryName;
|
||||
|
||||
$('#mapping_edit_webemulatorengine').select2();
|
||||
if (result.webEmulator.type.length > 0) {
|
||||
document.getElementById('mapping_edit_enablewebemulator').checked = true;
|
||||
$('#mapping_edit_webemulatorengine').val(result.webEmulator.type);
|
||||
$('#mapping_edit_webemulatorengine').trigger('change');
|
||||
document.getElementById('mapping_edit_webemulatorcore').value = result.webEmulator.core;
|
||||
} else {
|
||||
document.getElementById('mapping_edit_enablewebemulator').checked = false;
|
||||
}
|
||||
|
||||
var biosTableHeaders = [
|
||||
{
|
||||
"name": "filename",
|
||||
"label": "Filename"
|
||||
},
|
||||
{
|
||||
"name": "description",
|
||||
"label": "Description"
|
||||
},
|
||||
{
|
||||
"name": "hash",
|
||||
"label": "MD5 Hash"
|
||||
}
|
||||
];
|
||||
document.getElementById('mapping_edit_bios').appendChild(
|
||||
CreateEditableTable(
|
||||
'bios',
|
||||
biosTableHeaders
|
||||
)
|
||||
);
|
||||
|
||||
LoadEditableTableData('bios', biosTableHeaders, result.bios);
|
||||
}
|
||||
);
|
||||
|
||||
function AddTokensFromList(selectObj, tagList) {
|
||||
for (var i = 0; i < tagList.length; i++) {
|
||||
var data = {
|
||||
id: tagList[i],
|
||||
text: tagList[i]
|
||||
}
|
||||
|
||||
var newOption = new Option(data.text, data.id, true, true);
|
||||
$(selectObj).append(newOption).trigger('change');
|
||||
}
|
||||
}
|
||||
|
||||
function SubmitMappingItem() {
|
||||
var alternateNames = [];
|
||||
for (var i = 0; i < document.getElementById('mapping_edit_alternativenames').childNodes.length; i++) {
|
||||
var optionObj = document.getElementById('mapping_edit_alternativenames').childNodes[i];
|
||||
alternateNames.push(optionObj.innerHTML);
|
||||
}
|
||||
|
||||
var knownExtensions = $('#mapping_edit_supportedfileextensions').val();
|
||||
|
||||
var extensions = {
|
||||
"IGDBId": modalVariables,
|
||||
"supportedFileExtensions": knownExtensions,
|
||||
"uniqueFileExtensions": knownExtensions
|
||||
};
|
||||
|
||||
var emulator = null;
|
||||
if (document.getElementById('mapping_edit_enablewebemulator').checked == true) {
|
||||
emulator = {
|
||||
"type": document.getElementById('mapping_edit_webemulatorengine').value,
|
||||
"core": document.getElementById('mapping_edit_webemulatorcore').value
|
||||
};
|
||||
}
|
||||
|
||||
var bios = [];
|
||||
var biosTable = document.getElementById('EditableTable_bios');
|
||||
// get rows
|
||||
for (var i = 0; i < biosTable.childNodes.length; i++) {
|
||||
var rowObj = biosTable.childNodes[i];
|
||||
var biosObj = {};
|
||||
var addBiosObj = false;
|
||||
|
||||
// get cells
|
||||
for (var v = 0; v < rowObj.childNodes.length; v++) {
|
||||
var cell = rowObj.childNodes[v];
|
||||
if (cell.tagName.toLowerCase() != 'th') {
|
||||
// get input boxes
|
||||
for (var c = 0; c < cell.childNodes.length; c++) {
|
||||
var element = cell.childNodes[c];
|
||||
if (element) {
|
||||
if (element.getAttribute('data-cell')) {
|
||||
var nodeName = element.getAttribute('data-cell');
|
||||
biosObj[nodeName] = element.value;
|
||||
addBiosObj = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (addBiosObj == true) {
|
||||
bios.push(biosObj);
|
||||
}
|
||||
}
|
||||
|
||||
var item = {
|
||||
"igdbId": Number(modalVariables),
|
||||
"igdbName": document.getElementById('modal-heading').innerHTML,
|
||||
"igdbSlug": document.getElementById('mapping_edit_igdbslug').value,
|
||||
"alternateNames": alternateNames,
|
||||
"extensions": extensions,
|
||||
"retroPieDirectoryName": document.getElementById('mapping_edit_retropie').value,
|
||||
"webEmulator": emulator,
|
||||
"bios": bios
|
||||
};
|
||||
|
||||
console.log(JSON.stringify(item));
|
||||
|
||||
ajaxCall(
|
||||
'/api/v1/PlatformMaps/' + modalVariables,
|
||||
'PATCH',
|
||||
function (result) {
|
||||
loadPlatformMapping();
|
||||
closeDialog();
|
||||
},
|
||||
function (error) {
|
||||
console.error(JSON.stringify(error));
|
||||
},
|
||||
JSON.stringify(item)
|
||||
);
|
||||
}
|
||||
</script>
|
@@ -368,7 +368,7 @@
|
||||
var platformRow = document.createElement('tr');
|
||||
var platformHeader = document.createElement('th');
|
||||
platformHeader.setAttribute('colspan', 6);
|
||||
platformHeader.innerHTML = '<a href="#" onclick="ShowCollectionDialog(' + result[i].platform.id + ');" style="float: right; text-decoration: none;" class="romlink"><img src="/images/collections.svg" class="banner_button_image banner_button_image_smaller" alt="Add to collection" title="Add to collection" /></a>' + result[i].platform.name;
|
||||
platformHeader.innerHTML = '<a href="#" onclick="ShowPlatformMappingDialog(' + result[i].platform.id + ');" style="float: right; text-decoration: none;" class="romlink"><img src="/images/map.svg" class="banner_button_image banner_button_image_smaller" alt="Edit platform mapping" title="Edit platform mapping" /></a><a href="#" onclick="ShowCollectionDialog(' + result[i].platform.id + ');" style="float: right; text-decoration: none;" class="romlink"><img src="/images/collections.svg" class="banner_button_image banner_button_image_smaller" alt="Add to collection" title="Add to collection" /></a>' + result[i].platform.name;
|
||||
platformRow.appendChild(platformHeader);
|
||||
newTable.appendChild(platformRow);
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@
|
||||
<div id="properties_toc" class="settings_toc">
|
||||
<div class="filter_header">Settings</div>
|
||||
<div id="properties_toc_system" name="properties_toc_item" onclick="SelectTab('system');">System</div>
|
||||
<div id="properties_toc_mapping" name="properties_toc_item" onclick="SelectTab('mapping');">Platform Mapping</div>
|
||||
<div id="properties_toc_bios" name="properties_toc_item" onclick="SelectTab('bios');">Firmware</div>
|
||||
<div id="properties_toc_logs" name="properties_toc_item" onclick="SelectTab('logs');">Logs</div>
|
||||
<div id="properties_toc_about" name="properties_toc_item" onclick="SelectTab('about');">About</div>
|
||||
|
@@ -31,7 +31,7 @@
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var exceptionString = '';
|
||||
if (result[i].exceptionValue) {
|
||||
exceptionString = "<h3>Exception</h3><pre class='logs_table_exception'>" + syntaxHighlight(JSON.stringify(result[i].exceptionValue, null, 2)) + "</pre>";
|
||||
exceptionString = "<h3>Exception</h3><pre class='logs_table_exception'>" + syntaxHighlight(JSON.stringify(result[i].exceptionValue, null, 2)).replace(/\\n/g, "<br /> ") + "</pre>";
|
||||
}
|
||||
|
||||
var newRow = [
|
||||
|
87
gaseous-server/wwwroot/pages/settings/mapping.html
Normal file
87
gaseous-server/wwwroot/pages/settings/mapping.html
Normal file
@@ -0,0 +1,87 @@
|
||||
<div id="gametitle">
|
||||
<h1 id="gametitle_label">Platform Mapping</h1>
|
||||
</div>
|
||||
|
||||
<p>When determining the platform of a ROM or image (which is later used when determining the game title), only the "Unique File Extensions" are used. All other extensions are ignored as they will limit the ability of Gaseous to determine the game title (see <a href="https://github.com/gaseous-project/gaseous-server#game-image-title-matching" class="romlink">https://github.com/gaseous-project/gaseous-server#game-image-title-matching</a> for more information on how matching works).</p>
|
||||
|
||||
<p>This list is pre-populated with some of the more common platforms. New platforms will appear in this list as titles are added.</p>
|
||||
|
||||
<p><button value="Export to JSON" onclick="DownloadJSON();">Export to JSON</button><button id="importjson" value="Import JSON">Import JSON</button><button value="Reset to Default" onclick="loadPlatformMapping(true);">Reset to Default</button></p>
|
||||
|
||||
<input id='uploadjson' type='file' name='files' hidden/>
|
||||
|
||||
<table id="settings_mapping_table" style="width: 100%;" cellspacing="0">
|
||||
|
||||
</table>
|
||||
|
||||
<script type="text/javascript">
|
||||
function loadPlatformMapping(Overwrite) {
|
||||
var queryString = '';
|
||||
if (Overwrite == true) {
|
||||
queryString = '?ResetToDefault=true';
|
||||
}
|
||||
|
||||
ajaxCall(
|
||||
'/api/v1/PlatformMaps' + queryString,
|
||||
'GET',
|
||||
function (result) {
|
||||
var newTable = document.getElementById('settings_mapping_table');
|
||||
newTable.innerHTML = '';
|
||||
newTable.appendChild(
|
||||
createTableRow(
|
||||
true,
|
||||
[
|
||||
'Platform',
|
||||
'Supported File Extensions',
|
||||
'Unique File Extensions',
|
||||
'Has Web Emulator'
|
||||
],
|
||||
'',
|
||||
''
|
||||
)
|
||||
);
|
||||
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var hasWebEmulator = '';
|
||||
if (result[i].webEmulator.type.length > 0) {
|
||||
hasWebEmulator = 'Yes';
|
||||
}
|
||||
|
||||
var newRow = [
|
||||
'<span onclick="ShowPlatformMappingDialog(' + result[i].igdbId + ');" class="romlink">' + result[i].igdbName + '</span>',
|
||||
result[i].extensions.supportedFileExtensions.join(', '),
|
||||
result[i].extensions.uniqueFileExtensions.join(', '),
|
||||
hasWebEmulator
|
||||
];
|
||||
|
||||
newTable.appendChild(createTableRow(false, newRow, 'romrow', 'romcell logs_table_cell'));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function DownloadJSON() {
|
||||
window.open('/api/v1/PlatformMaps', '_blank');
|
||||
}
|
||||
|
||||
document.getElementById('importjson').addEventListener('click', openDialog);
|
||||
|
||||
function openDialog() {
|
||||
document.getElementById('uploadjson').click();
|
||||
}
|
||||
|
||||
$('#uploadjson').change(function () {
|
||||
$(this).simpleUpload("/api/v1/PlatformMaps", {
|
||||
start: function (file) {
|
||||
//upload started
|
||||
console.log("JSON upload started");
|
||||
},
|
||||
success: function(data){
|
||||
//upload successful
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
loadPlatformMapping();
|
||||
</script>
|
@@ -283,3 +283,94 @@ function syntaxHighlight(json) {
|
||||
return '<span class="' + cls + '">' + match + '</span>';
|
||||
});
|
||||
}
|
||||
|
||||
function ShowPlatformMappingDialog(platformId) {
|
||||
showDialog('platformmapedit', platformId);
|
||||
}
|
||||
|
||||
function CreateEditableTable(TableName, Headers) {
|
||||
var eDiv = document.createElement('div');
|
||||
|
||||
var eTable = document.createElement('table');
|
||||
eTable.id = 'EditableTable_' + TableName;
|
||||
eTable.style.width = '100%';
|
||||
|
||||
var headRow = document.createElement('tr');
|
||||
for (var i = 0; i < Headers.length; i++) {
|
||||
var headCell = document.createElement('th');
|
||||
headCell.id = 'EditableTable_' + TableName + '_' + Headers[i].name;
|
||||
headCell.innerHTML = Headers[i].label;
|
||||
headRow.appendChild(headCell);
|
||||
}
|
||||
eTable.appendChild(headRow);
|
||||
|
||||
eDiv.appendChild(eTable);
|
||||
|
||||
// add more button
|
||||
var addButton = document.createElement('button');
|
||||
addButton.value = 'Add Row';
|
||||
addButton.innerHTML = 'Add Row';
|
||||
|
||||
$(addButton).click(function() {
|
||||
eTable.appendChild(AddEditableTableRow(Headers));
|
||||
});
|
||||
|
||||
eDiv.appendChild(addButton);
|
||||
|
||||
return eDiv;
|
||||
}
|
||||
|
||||
function AddEditableTableRow(Headers) {
|
||||
var uniqueId = Math.floor(Math.random() * Date.now());
|
||||
|
||||
var row = document.createElement('tr');
|
||||
row.setAttribute('id', uniqueId);
|
||||
for (var i = 0; i < Headers.length; i++) {
|
||||
var cell = document.createElement('td');
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
input.setAttribute('data-cell', Headers[i].name);
|
||||
input.style.width = '95%';
|
||||
|
||||
cell.appendChild(input);
|
||||
row.appendChild(cell);
|
||||
}
|
||||
|
||||
// delete button
|
||||
var delButtonCell = document.createElement('td');
|
||||
delButtonCell.style.textAlign = 'right';
|
||||
var delButton = document.createElement('button');
|
||||
delButton.value = 'Delete';
|
||||
delButton.innerHTML = 'Delete';
|
||||
delButton.setAttribute('onclick', 'document.getElementById("' + uniqueId + '").remove();');
|
||||
|
||||
delButtonCell.appendChild(delButton);
|
||||
row.appendChild(delButtonCell);
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
function LoadEditableTableData(TableName, Headers, Values) {
|
||||
var eTable = document.getElementById('EditableTable_' + TableName);
|
||||
|
||||
for (var i = 0; i < Values.length; i++) {
|
||||
// get new row
|
||||
var row = AddEditableTableRow(Headers);
|
||||
for (var v = 0; v < row.childNodes.length; v++) {
|
||||
// looking at the cells here
|
||||
var cell = row.childNodes[v];
|
||||
for (var c = 0; c < cell.childNodes.length; c++) {
|
||||
if (cell.childNodes[c].getAttribute('data-cell')) {
|
||||
var nodeName = cell.childNodes[c].getAttribute('data-cell');
|
||||
if (Values[i][nodeName]) {
|
||||
row.childNodes[v].childNodes[c].value = Values[i][nodeName];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eTable.appendChild(row);
|
||||
}
|
||||
}
|
13
gaseous-server/wwwroot/scripts/simpleUpload.min.js
vendored
Normal file
13
gaseous-server/wwwroot/scripts/simpleUpload.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -146,7 +146,7 @@ h3 {
|
||||
.banner_button_image_smaller {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin: unset;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#banner_header {
|
||||
|
@@ -34,6 +34,14 @@ namespace gaseous_tools
|
||||
}
|
||||
}
|
||||
|
||||
public static string PlatformMappingFile
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".gaseous-server", "platformmap.json");
|
||||
}
|
||||
}
|
||||
|
||||
public static ConfigFile.Database DatabaseConfiguration
|
||||
{
|
||||
get
|
||||
|
@@ -14,3 +14,33 @@ ALTER TABLE `RomCollections`
|
||||
ADD COLUMN `FolderStructure` INT NULL DEFAULT 0 AFTER `MaximumCollectionSizeInBytes`,
|
||||
ADD COLUMN `IncludeBIOSFiles` BOOLEAN NULL DEFAULT 0 AFTER `FolderStructure`,
|
||||
ADD COLUMN `AlwaysInclude` JSON NULL AFTER `IncludeBIOSFiles`;
|
||||
|
||||
CREATE TABLE `PlatformMap` (
|
||||
`Id` BIGINT NOT NULL,
|
||||
`RetroPieDirectoryName` VARCHAR(45) NULL,
|
||||
`WebEmulator_Type` VARCHAR(45) NULL,
|
||||
`WebEmulator_Core` VARCHAR(45) NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE INDEX `Id_UNIQUE` (`Id` ASC) VISIBLE);
|
||||
|
||||
CREATE TABLE `PlatformMap_AlternateNames` (
|
||||
`Id` BIGINT NOT NULL,
|
||||
`Name` VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY (`Id`, `Name`));
|
||||
|
||||
CREATE TABLE `PlatformMap_Extensions` (
|
||||
`Id` BIGINT NOT NULL,
|
||||
`Extension` VARCHAR(45) NOT NULL,
|
||||
PRIMARY KEY (`Id`, `Extension`));
|
||||
|
||||
CREATE TABLE `PlatformMap_UniqueExtensions` (
|
||||
`Id` BIGINT NOT NULL,
|
||||
`Extension` VARCHAR(45) NOT NULL,
|
||||
PRIMARY KEY (`Id`, `Extension`));
|
||||
|
||||
CREATE TABLE `PlatformMap_Bios` (
|
||||
`Id` BIGINT NOT NULL,
|
||||
`Filename` VARCHAR(45) NOT NULL,
|
||||
`Description` LONGTEXT NOT NULL,
|
||||
`Hash` VARCHAR(45) NOT NULL,
|
||||
PRIMARY KEY (`Id`, `Filename`, `Hash`));
|
||||
|
@@ -74,9 +74,7 @@ namespace gaseous_tools
|
||||
|
||||
// write log file
|
||||
string JsonOutput = Newtonsoft.Json.JsonConvert.SerializeObject(logItem, serializerSettings);
|
||||
StreamWriter jsonLogFile = File.AppendText(Config.LogFilePath);
|
||||
jsonLogFile.WriteLine(JsonOutput);
|
||||
jsonLogFile.Close();
|
||||
File.AppendAllText(Config.LogFilePath, JsonOutput);
|
||||
}
|
||||
|
||||
// quick clean before we go
|
||||
@@ -116,7 +114,14 @@ namespace gaseous_tools
|
||||
FileInfo fi = new FileInfo(file);
|
||||
if (fi.LastAccessTime.AddDays(Config.LoggingConfiguration.LogRetention) < DateTime.Now)
|
||||
{
|
||||
fi.Delete();
|
||||
try
|
||||
{
|
||||
fi.Delete();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log(LogType.Warning, "Log Cleanup", "Failed purging log " + fi.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user