diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8c23067 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "nuget" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..6d9f542 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/gaseous-server/bin/Debug/net7.0/gaseous-server.dll", + "args": [], + "cwd": "${workspaceFolder}/gaseous-server", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..04fd839 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/gaseous-server/gaseous-server.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/gaseous-server/gaseous-server.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/gaseous-server/gaseous-server.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/Gaseous.sln b/Gaseous.sln index d15120a..f7adb01 100644 --- a/Gaseous.sln +++ b/Gaseous.sln @@ -13,6 +13,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-signature-ingestor" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-tools", "gaseous-tools\gaseous-tools.csproj", "{08FE408A-5EC1-4110-ABD8-D19A1155B8CE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gaseous-server", "gaseous-server\gaseous-server.csproj", "{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{B07A4655-A003-416B-A790-ADAA5B548E1A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -47,6 +51,14 @@ Global {08FE408A-5EC1-4110-ABD8-D19A1155B8CE}.Debug|Any CPU.Build.0 = Debug|Any CPU {08FE408A-5EC1-4110-ABD8-D19A1155B8CE}.Release|Any CPU.ActiveCfg = Release|Any CPU {08FE408A-5EC1-4110-ABD8-D19A1155B8CE}.Release|Any CPU.Build.0 = Release|Any CPU + {A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.Build.0 = Release|Any CPU + {B07A4655-A003-416B-A790-ADAA5B548E1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B07A4655-A003-416B-A790-ADAA5B548E1A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B07A4655-A003-416B-A790-ADAA5B548E1A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B07A4655-A003-416B-A790-ADAA5B548E1A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/gaseous-server/Controllers/SignaturesController.cs b/gaseous-server/Controllers/SignaturesController.cs new file mode 100644 index 0000000..7f69893 --- /dev/null +++ b/gaseous-server/Controllers/SignaturesController.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Security.Cryptography; +using System.Threading.Tasks; +using gaseous_tools; +using Microsoft.AspNetCore.Mvc; + +// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace gaseous_server.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] + public class SignaturesController : ControllerBase + { + /// + /// Get the current signature counts from the database + /// + /// Number of sources, publishers, games, and rom signatures in the database + [HttpGet] + public Models.Signatures_Status Status() + { + return new Models.Signatures_Status(); + } + + [HttpGet] + [Route("api/[controller]/[action]")] + public List GetSignature(string md5 = "", string sha1 = "") + { + if (md5.Length > 0) + { + return _GetSignature("signatures_roms.md5 = @searchstring", md5); + } else + { + return _GetSignature("signatures_roms.sha1 = @searchstring", sha1); + } + } + + private List _GetSignature(string sqlWhere, string searchString) + { + Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); + string sql = "SELECT \n view_signatures_games.*,\n signatures_roms.id AS romid,\n signatures_roms.name AS romname,\n signatures_roms.size,\n signatures_roms.crc,\n signatures_roms.md5,\n signatures_roms.sha1,\n signatures_roms.developmentstatus,\n signatures_roms.flags,\n signatures_roms.romtype,\n signatures_roms.romtypemedia,\n signatures_roms.medialabel\nFROM\n signatures_roms\n INNER JOIN\n view_signatures_games ON signatures_roms.gameid = view_signatures_games.id WHERE " + sqlWhere; + Dictionary dbDict = new Dictionary(); + dbDict.Add("searchString", searchString); + + DataTable sigDb = db.ExecuteCMD(sql, dbDict); + + List GamesList = new List(); + + 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"], + Sha1 = (string)sigDbRow["sha1"], + DevelopmentStatus = (string)sigDbRow["developmentstatus"], + flags = Newtonsoft.Json.JsonConvert.DeserializeObject>((string)sigDbRow["flags"]), + RomType = (Models.Signatures_Games.RomItem.RomTypes)(int)sigDbRow["romtype"], + RomTypeMedia = (string)sigDbRow["romtypemedia"], + MediaLabel = (string)sigDbRow["medialabel"] + } + }; + GamesList.Add(gameItem); + } + return GamesList; + } + } +} + diff --git a/gaseous-server/Models/Signatures_Games.cs b/gaseous-server/Models/Signatures_Games.cs new file mode 100644 index 0000000..9765714 --- /dev/null +++ b/gaseous-server/Models/Signatures_Games.cs @@ -0,0 +1,98 @@ +using System; +using static gaseous_romsignatureobject.RomSignatureObject.Game; + +namespace gaseous_server.Models +{ + public class Signatures_Games + { + public Signatures_Games() + { + } + + public GameItem? Game { get; set; } + public RomItem? Rom { get; set; } + + 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 + } + } + + 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 flags { get; set; } = new List(); + + public RomTypes RomType { get; set; } + public string? RomTypeMedia { get; set; } + public string? MediaLabel { get; set; } + + public enum RomTypes + { + /// + /// Media type is unknown + /// + Unknown = 0, + + /// + /// Optical media + /// + Disc = 1, + + /// + /// Magnetic media + /// + Disk = 2, + + /// + /// Individual files + /// + File = 3, + + /// + /// Individual pars + /// + Part = 4, + + /// + /// Tape base media + /// + Tape = 5, + + /// + /// Side of the media + /// + Side = 6 + } + } + } +} + diff --git a/gaseous-server/Models/Signatures_Status.cs b/gaseous-server/Models/Signatures_Status.cs new file mode 100644 index 0000000..8d2c904 --- /dev/null +++ b/gaseous-server/Models/Signatures_Status.cs @@ -0,0 +1,63 @@ +using System; +using System.Data; +using gaseous_tools; + +namespace gaseous_server.Models +{ + public class Signatures_Status + { + + private Int64 _SourceCount = 0; + private Int64 _PlatformCount = 0; + private Int64 _GameCount = 0; + private Int64 _RomCount = 0; + + public Signatures_Status() + { + Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); + string sql = "select (select count(*) from signatures_sources) as SourceCount, (select count(*) from signatures_platforms) as PlatformCount, (select count(*) from signatures_games) as GameCount, (select count(*) from signatures_roms) as RomCount;"; + + DataTable sigDb = db.ExecuteCMD(sql); + if (sigDb.Rows.Count > 0) + { + _SourceCount = (Int64)sigDb.Rows[0]["SourceCount"]; + _PlatformCount = (Int64)sigDb.Rows[0]["PlatformCount"]; + _GameCount = (Int64)sigDb.Rows[0]["GameCount"]; + _RomCount = (Int64)sigDb.Rows[0]["RomCount"]; + } + } + + public Int64 Sources + { + get + { + return _SourceCount; + } + } + + public Int64 Platforms + { + get + { + return _PlatformCount; + } + } + + public Int64 Games + { + get + { + return _GameCount; + } + } + + public Int64 Roms + { + get + { + return _RomCount; + } + } + } +} + diff --git a/gaseous-server/Program.cs b/gaseous-server/Program.cs new file mode 100644 index 0000000..6fd856e --- /dev/null +++ b/gaseous-server/Program.cs @@ -0,0 +1,38 @@ +using System.Text.Json.Serialization; +using gaseous_tools; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers().AddJsonOptions(x => +{ + // serialize enums as strings in api responses (e.g. Role) + x.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); +}); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +// set up db +Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); +db.InitDB(); + +// start the app +app.Run(); + diff --git a/gaseous-server/Properties/launchSettings.json b/gaseous-server/Properties/launchSettings.json new file mode 100644 index 0000000..6cb3fd1 --- /dev/null +++ b/gaseous-server/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:38715", + "sslPort": 44314 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5198", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7282;http://localhost:5198", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/gaseous-server/appsettings.Development.json b/gaseous-server/appsettings.Development.json new file mode 100644 index 0000000..ce16a2e --- /dev/null +++ b/gaseous-server/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} + diff --git a/gaseous-server/appsettings.json b/gaseous-server/appsettings.json new file mode 100644 index 0000000..af0538f --- /dev/null +++ b/gaseous-server/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} + diff --git a/gaseous-server/gaseous-server.csproj b/gaseous-server/gaseous-server.csproj new file mode 100644 index 0000000..35f78b0 --- /dev/null +++ b/gaseous-server/gaseous-server.csproj @@ -0,0 +1,34 @@ + + + + net7.0 + enable + enable + gaseous_server + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gaseous-tools/Database.cs b/gaseous-tools/Database.cs index 9f87e3c..db1f2c6 100644 --- a/gaseous-tools/Database.cs +++ b/gaseous-tools/Database.cs @@ -122,17 +122,33 @@ namespace gaseous_tools } } + public DataTable ExecuteCMD(string Command) + { + Dictionary dbDict = new Dictionary(); + return _ExecuteCMD(Command, dbDict, 30, ""); + } + + public DataTable ExecuteCMD(string Command, Dictionary Parameters) + { + return _ExecuteCMD(Command, Parameters, 30, ""); + } + public DataTable ExecuteCMD(string Command, Dictionary Parameters, int Timeout = 30, string ConnectionString = "") { - if (ConnectionString == "") { ConnectionString = _ConnectionString; } + return _ExecuteCMD(Command, Parameters, Timeout, ConnectionString); + } + + private DataTable _ExecuteCMD(string Command, Dictionary Parameters, int Timeout = 30, string ConnectionString = "") + { + if (ConnectionString == "") { ConnectionString = _ConnectionString; } switch (_ConnectorType) - { - case databaseType.MySql: + { + case databaseType.MySql: MySQLServerConnector conn = new MySQLServerConnector(ConnectionString); - return (DataTable)conn.ExecCMD(Command, Parameters, Timeout); - default: - return new DataTable(); - } + return (DataTable)conn.ExecCMD(Command, Parameters, Timeout); + default: + return new DataTable(); + } } private partial class MySQLServerConnector