Compare commits
6 Commits
v1.7.0-pre
...
branch-v1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e4cffb6fb4 | ||
![]() |
0e125d42ec | ||
![]() |
6d110731c4 | ||
![]() |
de628e6766 | ||
![]() |
308338580d | ||
![]() |
49784dc325 |
15
.github/release.yml
vendored
15
.github/release.yml
vendored
@@ -1,15 +0,0 @@
|
||||
changelog:
|
||||
categories:
|
||||
- title: What's New
|
||||
labels:
|
||||
- '*'
|
||||
exclude:
|
||||
labels:
|
||||
- bug
|
||||
- dependencies
|
||||
- title: Bug Fixes
|
||||
labels:
|
||||
- bug
|
||||
- title: Dependencies
|
||||
labels:
|
||||
- dependencies
|
@@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 25.0.1704.4
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
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("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{17FA6F12-8532-420C-9489-CB8FDE42137C}"
|
||||
@@ -35,6 +37,10 @@ Global
|
||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{08FE408A-5EC1-4110-ABD8-D19A1155B8CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{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
|
||||
|
19
README.MD
19
README.MD
@@ -1,6 +1,6 @@
|
||||
# Gaseous Server
|
||||
|
||||
This is the server for the Gaseous system. It offers ROM and title management, as well as some basic in browser emulation of those ROMs.
|
||||
This is the server for the Gaseous system. It offers ROM and title management, as well as some basic in browser emulation of those ROM's.
|
||||
|
||||
## Warning
|
||||
|
||||
@@ -16,12 +16,11 @@ If you expose the server to the internet, **you do so at your own risk**.
|
||||

|
||||
|
||||
## Requirements
|
||||
* MariaDB 11.1.2 or MySQL Server 8+
|
||||
* These are the database versions Gaseous has been tested and developed against. Your mileage may vary with earlier versions.
|
||||
* Currently MariaDB is the preferred database server, while MySQL will continue to be supported for existing users (they should be interchangable).
|
||||
* Note that due to the earlier database schema using MySQL specific features, moving to MariaDB from MySQL will require rebuilding your database from scratch. The "Library Scan" background task can be used to re-import all titles.
|
||||
* MySQL Server 8+*
|
||||
* Internet Game Database API Key. See: https://api-docs.igdb.com/#account-creation
|
||||
|
||||
***Note**: MariaDB is currently not supported as Gaseous uses features present only in MySQL. This is being tracked in https://github.com/gaseous-project/gaseous-server/issues/93
|
||||
|
||||
## Third Party Projects
|
||||
The following projects are used by Gaseous
|
||||
* https://dotnet.microsoft.com/en-us/apps/aspnet
|
||||
@@ -67,7 +66,7 @@ When Gaseous-Server is started for the first time, it creates a configuration fi
|
||||
},
|
||||
"LoggingConfiguration": {
|
||||
"DebugLogging": false,
|
||||
"LogRetention": 7
|
||||
"LogFormat": "text"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +75,7 @@ When Gaseous-Server is started for the first time, it creates a configuration fi
|
||||
## Docker
|
||||
### Deploy with the prebuilt Docker image
|
||||
Dockerfile and docker-compose.yml files have been provided to make deployment of the server as easy as possible.
|
||||
1. Download the docker-compose-{database}.yml file for the database type you would like to use.
|
||||
1. Download the docker-compose.yml file
|
||||
2. Open the docker-compose.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
|
||||
3. Run the command ```docker-compose up -d```
|
||||
4. Connect to the host on port 5198
|
||||
@@ -86,13 +85,13 @@ Dockerfile and docker-compose-build.yml files have been provided to make deploym
|
||||
1. Clone the repo with ```git clone https://github.com/gaseous-project/gaseous-server.git```
|
||||
2. Change into the gaseous-server directory
|
||||
3. Clone the submodules with the command ```git submodule update --init```
|
||||
4. Open the docker-compose-{database}-build.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
|
||||
5. Run the command ```docker-compose --file docker-compose-{database}-build.yml up -d```
|
||||
4. Open the docker-compose-build.yml file and edit the igdbclientid and igdbclientsecret to the values retrieved from your IGDB account
|
||||
5. Run the command ```docker-compose --file docker-compose-build.yml up -d```
|
||||
6. Connect to the host on port 5198
|
||||
|
||||
## Source
|
||||
### Build and deploy
|
||||
1. Install and configure a MariaDB or MySQL instance - this is beyond the scope of this document
|
||||
1. Install and configure a MySQL instance
|
||||
2. Install the dotnet 7.0 packages appropriate for your operating system
|
||||
* See: https://learn.microsoft.com/en-us/dotnet/core/install/linux
|
||||
3. Create a database user with permission to create a databse. Gaseous will create the new database and apply the database schema on it's first startup.
|
||||
|
@@ -1,39 +0,0 @@
|
||||
version: '2'
|
||||
services:
|
||||
gaseous-server:
|
||||
container_name: gaseous-server
|
||||
build:
|
||||
context: ./
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- gaseous
|
||||
depends_on:
|
||||
- gsdb
|
||||
ports:
|
||||
- 5198:80
|
||||
volumes:
|
||||
- gs:/root/.gaseous-server
|
||||
environment:
|
||||
- dbhost=gsdb
|
||||
- dbuser=root
|
||||
- dbpass=gaseous
|
||||
- igdbclientid=<clientid>
|
||||
- igdbclientsecret=<clientsecret>
|
||||
gsdb:
|
||||
container_name: gsdb
|
||||
image: mariadb
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- gaseous
|
||||
volumes:
|
||||
- gsdb:/var/lib/mysql
|
||||
environment:
|
||||
- MARIADB_ROOT_PASSWORD=gaseous
|
||||
- MARIADB_USER=gaseous
|
||||
- MARIADB_PASSWORD=gaseous
|
||||
networks:
|
||||
gaseous:
|
||||
driver: bridge
|
||||
volumes:
|
||||
gs:
|
||||
gsdb:
|
@@ -1,38 +0,0 @@
|
||||
version: '2'
|
||||
services:
|
||||
gaseous-server:
|
||||
container_name: gaseous-server
|
||||
image: gaseousgames/gaseousserver:latest
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- gaseous
|
||||
depends_on:
|
||||
- gsdb
|
||||
ports:
|
||||
- 5198:80
|
||||
volumes:
|
||||
- gs:/root/.gaseous-server
|
||||
environment:
|
||||
- dbhost=gsdb
|
||||
- dbuser=root
|
||||
- dbpass=gaseous
|
||||
- igdbclientid=<clientid>
|
||||
- igdbclientsecret=<clientsecret>
|
||||
gsdb:
|
||||
container_name: gsdb
|
||||
image: mariadb
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- gaseous
|
||||
volumes:
|
||||
- gsdb:/var/lib/mysql
|
||||
environment:
|
||||
- MARIADB_ROOT_PASSWORD=gaseous
|
||||
- MARIADB_USER=gaseous
|
||||
- MARIADB_PASSWORD=gaseous
|
||||
networks:
|
||||
gaseous:
|
||||
driver: bridge
|
||||
volumes:
|
||||
gs:
|
||||
gsdb:
|
BIN
gaseous-server/.DS_Store
vendored
BIN
gaseous-server/.DS_Store
vendored
Binary file not shown.
BIN
gaseous-server/Assets/.DS_Store
vendored
BIN
gaseous-server/Assets/.DS_Store
vendored
Binary file not shown.
BIN
gaseous-server/Assets/Ratings/.DS_Store
vendored
BIN
gaseous-server/Assets/Ratings/.DS_Store
vendored
Binary file not shown.
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that implements the ASP.NET Identity
|
||||
/// IRole interface
|
||||
/// </summary>
|
||||
public class ApplicationRole : IdentityRole
|
||||
{
|
||||
}
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that implements the ASP.NET Identity
|
||||
/// IUser interface
|
||||
/// </summary>
|
||||
public class ApplicationUser : IdentityUser
|
||||
{
|
||||
public SecurityProfileViewModel SecurityProfile { get; set; }
|
||||
public List<UserPreferenceViewModel> UserPreferences { get; set; }
|
||||
}
|
||||
}
|
@@ -1,171 +0,0 @@
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using MySqlConnector;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that implements the key ASP.NET Identity role store iterfaces
|
||||
/// </summary>
|
||||
public class RoleStore : IQueryableRoleStore<ApplicationRole>
|
||||
{
|
||||
private RoleTable roleTable;
|
||||
public Database Database { get; private set; }
|
||||
|
||||
public IQueryable<ApplicationRole> Roles
|
||||
{
|
||||
get
|
||||
{
|
||||
List<ApplicationRole> roles = roleTable.GetRoles();
|
||||
return roles.AsQueryable();
|
||||
}
|
||||
}
|
||||
|
||||
public RoleStore()
|
||||
{
|
||||
Database = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
roleTable = new RoleTable(Database);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that takes a MySQLDatabase as argument
|
||||
/// </summary>
|
||||
/// <param name="database"></param>
|
||||
public RoleStore(Database database)
|
||||
{
|
||||
Database = database;
|
||||
roleTable = new RoleTable(database);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> CreateAsync(ApplicationRole role, CancellationToken cancellationToken)
|
||||
{
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
roleTable.Insert(role);
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> DeleteAsync(ApplicationRole role, CancellationToken cancellationToken)
|
||||
{
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
roleTable.Delete(role.Id);
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<ApplicationRole> FindByIdAsync(string roleId, CancellationToken cancellationToken)
|
||||
{
|
||||
ApplicationRole result = roleTable.GetRoleById(roleId) as ApplicationRole;
|
||||
|
||||
return Task.FromResult<ApplicationRole>(result);
|
||||
}
|
||||
|
||||
public Task<bool> RoleExistsAsync(string roleId, CancellationToken cancellationToken)
|
||||
{
|
||||
ApplicationRole? result = roleTable.GetRoleById(roleId) as ApplicationRole;
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
return Task.FromResult<bool>(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Task.FromResult<bool>(true);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ApplicationRole?> FindByNameAsync(string roleName, CancellationToken cancellationToken)
|
||||
{
|
||||
ApplicationRole? result = roleTable.GetRoleByName(roleName) as ApplicationRole;
|
||||
|
||||
return Task.FromResult<ApplicationRole?>(result);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> UpdateAsync(ApplicationRole role, CancellationToken cancellationToken)
|
||||
{
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
roleTable.Update(role);
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Database != null)
|
||||
{
|
||||
Database = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<string> GetRoleIdAsync(ApplicationRole role, CancellationToken cancellationToken)
|
||||
{
|
||||
if (role != null)
|
||||
{
|
||||
return Task.FromResult<string>(roleTable.GetRoleId(role.Name));
|
||||
}
|
||||
|
||||
return Task.FromResult<string>(null);
|
||||
}
|
||||
|
||||
public Task<string?> GetRoleNameAsync(ApplicationRole role, CancellationToken cancellationToken)
|
||||
{
|
||||
if (role != null)
|
||||
{
|
||||
return Task.FromResult<string?>(roleTable.GetRoleName(role.Id));
|
||||
}
|
||||
|
||||
return Task.FromResult<string?>(null);
|
||||
}
|
||||
|
||||
public Task SetRoleNameAsync(ApplicationRole role, string? roleName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
role.Name = roleName;
|
||||
roleTable.Update(role);
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<string?> GetNormalizedRoleNameAsync(ApplicationRole role, CancellationToken cancellationToken)
|
||||
{
|
||||
if (role != null)
|
||||
{
|
||||
return Task.FromResult<string?>(roleTable.GetRoleName(role.Id));
|
||||
}
|
||||
|
||||
return Task.FromResult<string?>(null);
|
||||
}
|
||||
|
||||
public Task SetNormalizedRoleNameAsync(ApplicationRole role, string? normalizedName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
role.Name = normalizedName;
|
||||
roleTable.Update(role);
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,168 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that represents the Role table in the MySQL Database
|
||||
/// </summary>
|
||||
public class RoleTable
|
||||
{
|
||||
private Database _database;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that takes a MySQLDatabase instance
|
||||
/// </summary>
|
||||
/// <param name="database"></param>
|
||||
public RoleTable(Database database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deltes a role from the Roles table
|
||||
/// </summary>
|
||||
/// <param name="roleId">The role Id</param>
|
||||
/// <returns></returns>
|
||||
public int Delete(string roleId)
|
||||
{
|
||||
string commandText = "Delete from Roles where Id = @id";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@id", roleId);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a new Role in the Roles table
|
||||
/// </summary>
|
||||
/// <param name="roleName">The role's name</param>
|
||||
/// <returns></returns>
|
||||
public int Insert(ApplicationRole role)
|
||||
{
|
||||
string commandText = "Insert into Roles (Id, Name) values (@id, @name)";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@name", role.Name);
|
||||
parameters.Add("@id", role.Id);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a role name given the roleId
|
||||
/// </summary>
|
||||
/// <param name="roleId">The role Id</param>
|
||||
/// <returns>Role name</returns>
|
||||
public string? GetRoleName(string roleId)
|
||||
{
|
||||
string commandText = "Select Name from Roles where Id = @id";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@id", roleId);
|
||||
|
||||
DataTable table = _database.ExecuteCMD(commandText, parameters);
|
||||
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (string)table.Rows[0][0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the role Id given a role name
|
||||
/// </summary>
|
||||
/// <param name="roleName">Role's name</param>
|
||||
/// <returns>Role's Id</returns>
|
||||
public string? GetRoleId(string roleName)
|
||||
{
|
||||
string? roleId = null;
|
||||
string commandText = "Select Id from Roles where Name = @name";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@name", roleName } };
|
||||
|
||||
DataTable result = _database.ExecuteCMD(commandText, parameters);
|
||||
if (result.Rows.Count > 0)
|
||||
{
|
||||
return Convert.ToString(result.Rows[0][0]);
|
||||
}
|
||||
|
||||
return roleId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ApplicationRole given the role Id
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <returns></returns>
|
||||
public ApplicationRole? GetRoleById(string roleId)
|
||||
{
|
||||
var roleName = GetRoleName(roleId);
|
||||
ApplicationRole? role = null;
|
||||
|
||||
if(roleName != null)
|
||||
{
|
||||
role = new ApplicationRole();
|
||||
role.Id = roleId;
|
||||
role.Name = roleName;
|
||||
role.NormalizedName = roleName.ToUpper();
|
||||
}
|
||||
|
||||
return role;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ApplicationRole given the role name
|
||||
/// </summary>
|
||||
/// <param name="roleName"></param>
|
||||
/// <returns></returns>
|
||||
public ApplicationRole? GetRoleByName(string roleName)
|
||||
{
|
||||
var roleId = GetRoleId(roleName);
|
||||
ApplicationRole role = null;
|
||||
|
||||
if (roleId != null)
|
||||
{
|
||||
role = new ApplicationRole();
|
||||
role.Id = roleId;
|
||||
role.Name = roleName;
|
||||
role.NormalizedName = roleName.ToUpper();
|
||||
}
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
public int Update(ApplicationRole role)
|
||||
{
|
||||
string commandText = "Update Roles set Name = @name where Id = @id";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@id", role.Id);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
public List<ApplicationRole> GetRoles()
|
||||
{
|
||||
List<ApplicationRole> roles = new List<ApplicationRole>();
|
||||
|
||||
string commandText = "Select Name from Roles";
|
||||
|
||||
var rows = _database.ExecuteCMDDict(commandText);
|
||||
foreach(Dictionary<string, object> row in rows)
|
||||
{
|
||||
ApplicationRole role = (ApplicationRole)Activator.CreateInstance(typeof(ApplicationRole));
|
||||
role.Id = (string)row["Id"];
|
||||
role.Name = (string)row["Name"];
|
||||
role.NormalizedName = ((string)row["Name"]).ToUpper();
|
||||
roles.Add(role);
|
||||
}
|
||||
|
||||
return roles;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,95 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Security.Claims;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that represents the UserClaims table in the MySQL Database
|
||||
/// </summary>
|
||||
public class UserClaimsTable
|
||||
{
|
||||
private Database _database;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that takes a MySQLDatabase instance
|
||||
/// </summary>
|
||||
/// <param name="database"></param>
|
||||
public UserClaimsTable(Database database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a ClaimsIdentity instance given a userId
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id</param>
|
||||
/// <returns></returns>
|
||||
public ClaimsIdentity FindByUserId(string userId)
|
||||
{
|
||||
ClaimsIdentity claims = new ClaimsIdentity();
|
||||
string commandText = "Select * from UserClaims where UserId = @userId";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@UserId", userId } };
|
||||
|
||||
var rows = _database.ExecuteCMD(commandText, parameters).Rows;
|
||||
foreach (DataRow row in rows)
|
||||
{
|
||||
Claim claim = new Claim((string)row["ClaimType"], (string)row["ClaimValue"]);
|
||||
claims.AddClaim(claim);
|
||||
}
|
||||
|
||||
return claims;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all claims from a user given a userId
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id</param>
|
||||
/// <returns></returns>
|
||||
public int Delete(string userId)
|
||||
{
|
||||
string commandText = "Delete from UserClaims where UserId = @userId";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("userId", userId);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a new claim in UserClaims table
|
||||
/// </summary>
|
||||
/// <param name="userClaim">User's claim to be added</param>
|
||||
/// <param name="userId">User's id</param>
|
||||
/// <returns></returns>
|
||||
public int Insert(Claim userClaim, string userId)
|
||||
{
|
||||
string commandText = "Insert into UserClaims (ClaimValue, ClaimType, UserId) values (@value, @type, @userId)";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("value", userClaim.Value);
|
||||
parameters.Add("type", userClaim.Type);
|
||||
parameters.Add("userId", userId);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a claim from a user
|
||||
/// </summary>
|
||||
/// <param name="user">The user to have a claim deleted</param>
|
||||
/// <param name="claim">A claim to be deleted from user</param>
|
||||
/// <returns></returns>
|
||||
public int Delete(IdentityUser user, Claim claim)
|
||||
{
|
||||
string commandText = "Delete from UserClaims where UserId = @userId and @ClaimValue = @value and ClaimType = @type";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("userId", user.Id);
|
||||
parameters.Add("value", claim.Value);
|
||||
parameters.Add("type", claim.Type);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,117 +0,0 @@
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that represents the UserLogins table in the MySQL Database
|
||||
/// </summary>
|
||||
public class UserLoginsTable
|
||||
{
|
||||
private Database _database;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that takes a MySQLDatabase instance
|
||||
/// </summary>
|
||||
/// <param name="database"></param>
|
||||
public UserLoginsTable(Database database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a login from a user in the UserLogins table
|
||||
/// </summary>
|
||||
/// <param name="user">User to have login deleted</param>
|
||||
/// <param name="login">Login to be deleted from user</param>
|
||||
/// <returns></returns>
|
||||
public int Delete(IdentityUser user, UserLoginInfo login)
|
||||
{
|
||||
string commandText = "Delete from UserLogins where UserId = @userId and LoginProvider = @loginProvider and ProviderKey = @providerKey";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("UserId", user.Id);
|
||||
parameters.Add("loginProvider", login.LoginProvider);
|
||||
parameters.Add("providerKey", login.ProviderKey);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all Logins from a user in the UserLogins table
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id</param>
|
||||
/// <returns></returns>
|
||||
public int Delete(string userId)
|
||||
{
|
||||
string commandText = "Delete from UserLogins where UserId = @userId";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("UserId", userId);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a new login in the UserLogins table
|
||||
/// </summary>
|
||||
/// <param name="user">User to have new login added</param>
|
||||
/// <param name="login">Login to be added</param>
|
||||
/// <returns></returns>
|
||||
public int Insert(IdentityUser user, UserLoginInfo login)
|
||||
{
|
||||
string commandText = "Insert into UserLogins (LoginProvider, ProviderKey, UserId) values (@loginProvider, @providerKey, @userId)";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("loginProvider", login.LoginProvider);
|
||||
parameters.Add("providerKey", login.ProviderKey);
|
||||
parameters.Add("userId", user.Id);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a userId given a user's login
|
||||
/// </summary>
|
||||
/// <param name="userLogin">The user's login info</param>
|
||||
/// <returns></returns>
|
||||
public string? FindUserIdByLogin(UserLoginInfo userLogin)
|
||||
{
|
||||
string commandText = "Select UserId from UserLogins where LoginProvider = @loginProvider and ProviderKey = @providerKey";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("loginProvider", userLogin.LoginProvider);
|
||||
parameters.Add("providerKey", userLogin.ProviderKey);
|
||||
|
||||
DataTable table = _database.ExecuteCMD(commandText, parameters);
|
||||
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (string)table.Rows[0][0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of user's logins
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id</param>
|
||||
/// <returns></returns>
|
||||
public List<UserLoginInfo> FindByUserId(string userId)
|
||||
{
|
||||
List<UserLoginInfo> logins = new List<UserLoginInfo>();
|
||||
string commandText = "Select * from UserLogins where UserId = @userId";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@userId", userId } };
|
||||
|
||||
var rows = _database.ExecuteCMD(commandText, parameters).Rows;
|
||||
foreach (DataRow row in rows)
|
||||
{
|
||||
var login = new UserLoginInfo((string)row["LoginProvider"], (string)row["ProviderKey"], (string)row["LoginProvider"]);
|
||||
logins.Add(login);
|
||||
}
|
||||
|
||||
return logins;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,86 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that represents the UserRoles table in the MySQL Database
|
||||
/// </summary>
|
||||
public class UserRolesTable
|
||||
{
|
||||
private Database _database;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that takes a MySQLDatabase instance
|
||||
/// </summary>
|
||||
/// <param name="database"></param>
|
||||
public UserRolesTable(Database database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of user's roles
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id</param>
|
||||
/// <returns></returns>
|
||||
public List<string> FindByUserId(string userId)
|
||||
{
|
||||
List<string> roles = new List<string>();
|
||||
string commandText = "Select Roles.Name from UserRoles, Roles where UserRoles.UserId = @userId and UserRoles.RoleId = Roles.Id";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@userId", userId);
|
||||
|
||||
var rows = _database.ExecuteCMD(commandText, parameters).Rows;
|
||||
foreach(DataRow row in rows)
|
||||
{
|
||||
roles.Add((string)row["Name"]);
|
||||
}
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all roles from a user in the UserRoles table
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id</param>
|
||||
/// <returns></returns>
|
||||
public int Delete(string userId)
|
||||
{
|
||||
string commandText = "Delete from UserRoles where UserId = @userId";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("UserId", userId);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
public int DeleteUserFromRole(string userId, string roleId)
|
||||
{
|
||||
string commandText = "Delete from UserRoles where UserId = @userId and RoleId = @roleId";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("userId", userId);
|
||||
parameters.Add("roleId", roleId);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a new role for a user in the UserRoles table
|
||||
/// </summary>
|
||||
/// <param name="user">The User</param>
|
||||
/// <param name="roleId">The Role's id</param>
|
||||
/// <returns></returns>
|
||||
public int Insert(IdentityUser user, string roleId)
|
||||
{
|
||||
string commandText = "Insert into UserRoles (UserId, RoleId) values (@userId, @roleId)";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("userId", user.Id);
|
||||
parameters.Add("roleId", roleId);
|
||||
|
||||
return (int)_database.ExecuteNonQuery(commandText, parameters);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,616 +0,0 @@
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using MySqlConnector;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
public class UserStore :
|
||||
IUserStore<ApplicationUser>,
|
||||
IUserRoleStore<ApplicationUser>,
|
||||
IUserLoginStore<ApplicationUser>,
|
||||
IUserClaimStore<ApplicationUser>,
|
||||
IUserPasswordStore<ApplicationUser>,
|
||||
IUserSecurityStampStore<ApplicationUser>,
|
||||
IQueryableUserStore<ApplicationUser>,
|
||||
IUserEmailStore<ApplicationUser>,
|
||||
IUserPhoneNumberStore<ApplicationUser>,
|
||||
IUserTwoFactorStore<ApplicationUser>,
|
||||
IUserLockoutStore<ApplicationUser>
|
||||
{
|
||||
private Database database;
|
||||
|
||||
private UserTable<ApplicationUser> userTable;
|
||||
private RoleTable roleTable;
|
||||
private UserRolesTable userRolesTable;
|
||||
private UserLoginsTable userLoginsTable;
|
||||
private UserClaimsTable userClaimsTable;
|
||||
|
||||
public UserStore()
|
||||
{
|
||||
database = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
userTable = new UserTable<ApplicationUser>(database);
|
||||
roleTable = new RoleTable(database);
|
||||
userRolesTable = new UserRolesTable(database);
|
||||
userLoginsTable = new UserLoginsTable(database);
|
||||
userClaimsTable = new UserClaimsTable(database);
|
||||
}
|
||||
|
||||
public UserStore(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
userTable = new UserTable<ApplicationUser>(database);
|
||||
roleTable = new RoleTable(database);
|
||||
userRolesTable = new UserRolesTable(database);
|
||||
userLoginsTable = new UserLoginsTable(database);
|
||||
userClaimsTable = new UserClaimsTable(database);
|
||||
}
|
||||
|
||||
public IQueryable<ApplicationUser> Users
|
||||
{
|
||||
get
|
||||
{
|
||||
List<ApplicationUser> users = userTable.GetUsers();
|
||||
return users.AsQueryable();
|
||||
}
|
||||
}
|
||||
|
||||
public Task AddClaimsAsync(ApplicationUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
if (claims == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
foreach (Claim claim in claims)
|
||||
{
|
||||
userClaimsTable.Insert(claim, user.Id);
|
||||
}
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
public Task AddLoginAsync(ApplicationUser user, UserLoginInfo login, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
if (login == null)
|
||||
{
|
||||
throw new ArgumentNullException("login");
|
||||
}
|
||||
|
||||
userLoginsTable.Insert(user, login);
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
public Task AddToRoleAsync(ApplicationUser user, string roleName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(roleName))
|
||||
{
|
||||
throw new ArgumentException("Argument cannot be null or empty: roleName.");
|
||||
}
|
||||
|
||||
string roleId = roleTable.GetRoleId(roleName);
|
||||
if (!string.IsNullOrEmpty(roleId))
|
||||
{
|
||||
userRolesTable.Insert(user, roleId);
|
||||
}
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> CreateAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
userTable.Insert(user);
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> DeleteAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user != null)
|
||||
{
|
||||
userTable.Delete(user);
|
||||
}
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (database != null)
|
||||
{
|
||||
database = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ApplicationUser?> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken)
|
||||
{
|
||||
if (String.IsNullOrEmpty(normalizedEmail))
|
||||
{
|
||||
throw new ArgumentNullException("email");
|
||||
}
|
||||
|
||||
ApplicationUser result = userTable.GetUserByEmail(normalizedEmail) as ApplicationUser;
|
||||
if (result != null)
|
||||
{
|
||||
return Task.FromResult<ApplicationUser>(result);
|
||||
}
|
||||
|
||||
return Task.FromResult<ApplicationUser>(null);
|
||||
}
|
||||
|
||||
public Task<ApplicationUser?> FindByIdAsync(string userId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrEmpty(userId))
|
||||
{
|
||||
throw new ArgumentException("Null or empty argument: userId");
|
||||
}
|
||||
|
||||
ApplicationUser result = userTable.GetUserById(userId) as ApplicationUser;
|
||||
if (result != null)
|
||||
{
|
||||
return Task.FromResult<ApplicationUser>(result);
|
||||
}
|
||||
|
||||
return Task.FromResult<ApplicationUser>(null);
|
||||
}
|
||||
|
||||
public Task<ApplicationUser?> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken)
|
||||
{
|
||||
if (loginProvider == null || providerKey == null)
|
||||
{
|
||||
throw new ArgumentNullException("login");
|
||||
}
|
||||
|
||||
UserLoginInfo login = new UserLoginInfo(loginProvider, providerKey, loginProvider);
|
||||
|
||||
var userId = userLoginsTable.FindUserIdByLogin(login);
|
||||
if (userId != null)
|
||||
{
|
||||
ApplicationUser user = userTable.GetUserById(userId) as ApplicationUser;
|
||||
if (user != null)
|
||||
{
|
||||
return Task.FromResult<ApplicationUser>(user);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult<ApplicationUser>(null);
|
||||
}
|
||||
|
||||
public Task<ApplicationUser?> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrEmpty(normalizedUserName))
|
||||
{
|
||||
throw new ArgumentException("Null or empty argument: normalizedUserName");
|
||||
}
|
||||
|
||||
List<ApplicationUser> result = userTable.GetUserByName(normalizedUserName) as List<ApplicationUser>;
|
||||
|
||||
// Should I throw if > 1 user?
|
||||
if (result != null && result.Count == 1)
|
||||
{
|
||||
return Task.FromResult<ApplicationUser>(result[0]);
|
||||
}
|
||||
|
||||
return Task.FromResult<ApplicationUser>(null);
|
||||
}
|
||||
|
||||
public Task<int> GetAccessFailedCountAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(user.AccessFailedCount);
|
||||
}
|
||||
|
||||
public Task<IList<Claim>> GetClaimsAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
ClaimsIdentity identity = userClaimsTable.FindByUserId(user.Id);
|
||||
|
||||
return Task.FromResult<IList<Claim>>(identity.Claims.ToList());
|
||||
}
|
||||
|
||||
public Task<string?> GetEmailAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(user.Email);
|
||||
}
|
||||
|
||||
public Task<bool> GetEmailConfirmedAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(user.EmailConfirmed);
|
||||
}
|
||||
|
||||
public Task<bool> GetLockoutEnabledAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(user.LockoutEnabled);
|
||||
}
|
||||
|
||||
public Task<DateTimeOffset?> GetLockoutEndDateAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user.LockoutEnd.HasValue)
|
||||
{
|
||||
return Task.FromResult((DateTimeOffset?)user.LockoutEnd.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Task.FromResult((DateTimeOffset?)new DateTimeOffset());
|
||||
}
|
||||
}
|
||||
|
||||
public Task<IList<UserLoginInfo>> GetLoginsAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
List<UserLoginInfo> logins = userLoginsTable.FindByUserId(user.Id);
|
||||
if (logins != null)
|
||||
{
|
||||
return Task.FromResult<IList<UserLoginInfo>>(logins);
|
||||
}
|
||||
|
||||
return Task.FromResult<IList<UserLoginInfo>>(null);
|
||||
}
|
||||
|
||||
public Task<string?> GetNormalizedEmailAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(user.NormalizedEmail);
|
||||
}
|
||||
|
||||
public Task<string?> GetNormalizedUserNameAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user != null)
|
||||
{
|
||||
return Task.FromResult<string?>(userTable.GetUserName(user.Id));
|
||||
}
|
||||
|
||||
return Task.FromResult<string?>(null);
|
||||
}
|
||||
|
||||
public Task<string?> GetPasswordHashAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user != null)
|
||||
{
|
||||
return Task.FromResult<string?>(userTable.GetPasswordHash(user.Id));
|
||||
}
|
||||
|
||||
return Task.FromResult<string?>(null);
|
||||
}
|
||||
|
||||
public Task<string?> GetPhoneNumberAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(user.PhoneNumber);
|
||||
}
|
||||
|
||||
public Task<bool> GetPhoneNumberConfirmedAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(user.PhoneNumberConfirmed);
|
||||
}
|
||||
|
||||
public Task<IList<string>> GetRolesAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
List<string> roles = userRolesTable.FindByUserId(user.Id);
|
||||
{
|
||||
if (roles != null)
|
||||
{
|
||||
return Task.FromResult<IList<string>>(roles);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult<IList<string>>(null);
|
||||
}
|
||||
|
||||
public Task<string?> GetSecurityStampAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(user.SecurityStamp);
|
||||
}
|
||||
|
||||
public Task<bool> GetTwoFactorEnabledAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(user.TwoFactorEnabled);
|
||||
}
|
||||
|
||||
public Task<string> GetUserIdAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user != null)
|
||||
{
|
||||
return Task.FromResult<string>(userTable.GetUserId(user.NormalizedUserName));
|
||||
}
|
||||
|
||||
return Task.FromResult<string>(null);
|
||||
}
|
||||
|
||||
public Task<string?> GetUserNameAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user != null)
|
||||
{
|
||||
//return Task.FromResult<string?>(userTable.GetUserName(user.Id));
|
||||
return Task.FromResult(user.UserName);
|
||||
}
|
||||
|
||||
return Task.FromResult<string?>(null);
|
||||
}
|
||||
|
||||
public Task<IList<ApplicationUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IList<ApplicationUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> HasPasswordAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
var hasPassword = !string.IsNullOrEmpty(userTable.GetPasswordHash(user.Id));
|
||||
|
||||
return Task.FromResult<bool>(Boolean.Parse(hasPassword.ToString()));
|
||||
}
|
||||
|
||||
public Task<int> IncrementAccessFailedCountAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
user.AccessFailedCount++;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(user.AccessFailedCount);
|
||||
}
|
||||
|
||||
public Task<bool> IsInRoleAsync(ApplicationUser user, string roleName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(roleName))
|
||||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
List<string> roles = userRolesTable.FindByUserId(user.Id);
|
||||
{
|
||||
if (roles != null)
|
||||
{
|
||||
foreach (string role in roles)
|
||||
{
|
||||
if (role.ToUpper() == roleName.ToUpper())
|
||||
{
|
||||
return Task.FromResult<bool>(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult<bool>(false);
|
||||
}
|
||||
|
||||
public Task RemoveClaimsAsync(ApplicationUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
if (claims == null)
|
||||
{
|
||||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
|
||||
foreach (Claim claim in claims)
|
||||
{
|
||||
userClaimsTable.Delete(user, claim);
|
||||
}
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
public Task RemoveFromRoleAsync(ApplicationUser user, string roleName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
if (roleName == null)
|
||||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
IdentityRole? role = roleTable.GetRoleByName(roleName);
|
||||
|
||||
if (role != null)
|
||||
{
|
||||
userRolesTable.DeleteUserFromRole(user.Id, role.Id);
|
||||
}
|
||||
|
||||
return Task.FromResult<Object>(null);
|
||||
}
|
||||
|
||||
public Task RemoveLoginAsync(ApplicationUser user, string loginProvider, string providerKey, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
if (loginProvider == null || providerKey == null)
|
||||
{
|
||||
throw new ArgumentNullException("login");
|
||||
}
|
||||
|
||||
UserLoginInfo login = new UserLoginInfo(loginProvider, providerKey, loginProvider);
|
||||
|
||||
userLoginsTable.Delete(user, login);
|
||||
|
||||
return Task.FromResult<Object>(null);
|
||||
}
|
||||
|
||||
public Task ReplaceClaimAsync(ApplicationUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
if (claim == null || newClaim == null)
|
||||
{
|
||||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
|
||||
userClaimsTable.Delete(user, claim);
|
||||
userClaimsTable.Insert(newClaim, user.Id);
|
||||
|
||||
return Task.FromResult<Object>(null);
|
||||
}
|
||||
|
||||
public Task ResetAccessFailedCountAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
user.AccessFailedCount = 0;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetEmailAsync(ApplicationUser user, string? email, CancellationToken cancellationToken)
|
||||
{
|
||||
user.Email = email;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetEmailConfirmedAsync(ApplicationUser user, bool confirmed, CancellationToken cancellationToken)
|
||||
{
|
||||
user.EmailConfirmed = confirmed;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetLockoutEnabledAsync(ApplicationUser user, bool enabled, CancellationToken cancellationToken)
|
||||
{
|
||||
user.LockoutEnabled = enabled;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetLockoutEndDateAsync(ApplicationUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken)
|
||||
{
|
||||
user.LockoutEnd = lockoutEnd;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetNormalizedEmailAsync(ApplicationUser user, string? normalizedEmail, CancellationToken cancellationToken)
|
||||
{
|
||||
user.NormalizedEmail = normalizedEmail;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetNormalizedUserNameAsync(ApplicationUser user, string? normalizedName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
user.NormalizedUserName = normalizedName;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task SetPasswordHashAsync(ApplicationUser user, string? passwordHash, CancellationToken cancellationToken)
|
||||
{
|
||||
user.PasswordHash = passwordHash;
|
||||
|
||||
return Task.FromResult<Object>(null);
|
||||
}
|
||||
|
||||
public Task SetPhoneNumberAsync(ApplicationUser user, string? phoneNumber, CancellationToken cancellationToken)
|
||||
{
|
||||
user.PhoneNumber = phoneNumber;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetPhoneNumberConfirmedAsync(ApplicationUser user, bool confirmed, CancellationToken cancellationToken)
|
||||
{
|
||||
user.PhoneNumberConfirmed = confirmed;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetSecurityStampAsync(ApplicationUser user, string stamp, CancellationToken cancellationToken)
|
||||
{
|
||||
user.SecurityStamp = stamp;
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetTwoFactorEnabledAsync(ApplicationUser user, bool enabled, CancellationToken cancellationToken)
|
||||
{
|
||||
user.TwoFactorEnabled = enabled;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SetUserNameAsync(ApplicationUser user, string? userName, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
user.UserName = userName;
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<IdentityResult> UpdateAsync(ApplicationUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
userTable.Update(user);
|
||||
|
||||
return Task.FromResult<IdentityResult>(IdentityResult.Success);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,441 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that represents the Users table in the MySQL Database
|
||||
/// </summary>
|
||||
public class UserTable<TUser>
|
||||
where TUser :ApplicationUser
|
||||
{
|
||||
private Database _database;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that takes a MySQLDatabase instance
|
||||
/// </summary>
|
||||
/// <param name="database"></param>
|
||||
public UserTable(Database database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the user's name given a user id
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public string? GetUserName(string userId)
|
||||
{
|
||||
string commandText = "Select NormalizedUserName from Users where Id = @id";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@id", userId } };
|
||||
|
||||
DataTable table = _database.ExecuteCMD(commandText, parameters);
|
||||
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (string)table.Rows[0][0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a User ID given a user name
|
||||
/// </summary>
|
||||
/// <param name="userName">The user's name</param>
|
||||
/// <returns></returns>
|
||||
public string? GetUserId(string normalizedUserName)
|
||||
{
|
||||
string commandText = "Select Id from Users where NormalizedUserName = @name";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@name", normalizedUserName } };
|
||||
|
||||
DataTable table = _database.ExecuteCMD(commandText, parameters);
|
||||
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (string)table.Rows[0][0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an TUser given the user's id
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id</param>
|
||||
/// <returns></returns>
|
||||
public TUser GetUserById(string userId)
|
||||
{
|
||||
TUser user = null;
|
||||
string commandText = "Select * from Users where Id = @id";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@id", userId } };
|
||||
|
||||
var rows = _database.ExecuteCMDDict(commandText, parameters);
|
||||
if (rows != null && rows.Count == 1)
|
||||
{
|
||||
Dictionary<string, object> row = rows[0];
|
||||
user = (TUser)Activator.CreateInstance(typeof(TUser));
|
||||
user.Id = (string)row["Id"];
|
||||
user.UserName = (string?)row["UserName"];
|
||||
user.PasswordHash = (string?)(string.IsNullOrEmpty((string?)row["PasswordHash"]) ? null : row["PasswordHash"]);
|
||||
user.SecurityStamp = (string?)(string.IsNullOrEmpty((string?)row["SecurityStamp"]) ? null : row["SecurityStamp"]);
|
||||
user.ConcurrencyStamp = (string?)(string.IsNullOrEmpty((string?)row["ConcurrencyStamp"]) ? null : row["ConcurrencyStamp"]);
|
||||
user.Email = (string?)(string.IsNullOrEmpty((string?)row["Email"]) ? null : row["Email"]);
|
||||
user.EmailConfirmed = row["EmailConfirmed"] == "1" ? true:false;
|
||||
user.PhoneNumber = (string?)(string.IsNullOrEmpty((string?)row["PhoneNumber"]) ? null : row["PhoneNumber"]);
|
||||
user.PhoneNumberConfirmed = row["PhoneNumberConfirmed"] == "1" ? true : false;
|
||||
user.NormalizedEmail = (string?)(string.IsNullOrEmpty((string?)row["NormalizedEmail"]) ? null : row["NormalizedEmail"]);
|
||||
user.NormalizedUserName = (string?)(string.IsNullOrEmpty((string?)row["NormalizedUserName"]) ? null : row["NormalizedUserName"]);
|
||||
user.LockoutEnabled = row["LockoutEnabled"] == "1" ? true : false;
|
||||
user.LockoutEnd = string.IsNullOrEmpty((string?)row["LockoutEnd"]) ? DateTime.Now : DateTime.Parse((string?)row["LockoutEnd"]);
|
||||
user.AccessFailedCount = string.IsNullOrEmpty((string?)row["AccessFailedCount"]) ? 0 : int.Parse((string?)row["AccessFailedCount"]);
|
||||
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
||||
user.SecurityProfile = GetSecurityProfile(user);
|
||||
user.UserPreferences = GetPreferences(user);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of TUser instances given a user name
|
||||
/// </summary>
|
||||
/// <param name="normalizedUserName">User's name</param>
|
||||
/// <returns></returns>
|
||||
public List<TUser> GetUserByName(string normalizedUserName)
|
||||
{
|
||||
List<TUser> users = new List<TUser>();
|
||||
string commandText = "Select * from Users where NormalizedEmail = @name";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@name", normalizedUserName } };
|
||||
|
||||
var rows = _database.ExecuteCMDDict(commandText, parameters);
|
||||
foreach(Dictionary<string, object> row in rows)
|
||||
{
|
||||
TUser user = (TUser)Activator.CreateInstance(typeof(TUser));
|
||||
user.Id = (string)row["Id"];
|
||||
user.UserName = (string?)row["UserName"];
|
||||
user.PasswordHash = (string?)(string.IsNullOrEmpty((string?)row["PasswordHash"]) ? null : row["PasswordHash"]);
|
||||
user.SecurityStamp = (string?)(string.IsNullOrEmpty((string?)row["SecurityStamp"]) ? null : row["SecurityStamp"]);
|
||||
user.ConcurrencyStamp = (string?)(string.IsNullOrEmpty((string?)row["ConcurrencyStamp"]) ? null : row["ConcurrencyStamp"]);
|
||||
user.Email = (string?)(string.IsNullOrEmpty((string?)row["Email"]) ? null : row["Email"]);
|
||||
user.EmailConfirmed = row["EmailConfirmed"] == "1" ? true:false;
|
||||
user.PhoneNumber = (string?)(string.IsNullOrEmpty((string?)row["PhoneNumber"]) ? null : row["PhoneNumber"]);
|
||||
user.PhoneNumberConfirmed = row["PhoneNumberConfirmed"] == "1" ? true : false;
|
||||
user.NormalizedEmail = (string?)(string.IsNullOrEmpty((string?)row["NormalizedEmail"]) ? null : row["NormalizedEmail"]);
|
||||
user.NormalizedUserName = (string?)(string.IsNullOrEmpty((string?)row["NormalizedUserName"]) ? null : row["NormalizedUserName"]);
|
||||
user.LockoutEnabled = row["LockoutEnabled"] == "1" ? true : false;
|
||||
user.LockoutEnd = string.IsNullOrEmpty((string?)row["LockoutEnd"]) ? DateTime.Now : DateTime.Parse((string?)row["LockoutEnd"]);
|
||||
user.AccessFailedCount = string.IsNullOrEmpty((string?)row["AccessFailedCount"]) ? 0 : int.Parse((string?)row["AccessFailedCount"]);
|
||||
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
||||
user.SecurityProfile = GetSecurityProfile(user);
|
||||
user.UserPreferences = GetPreferences(user);
|
||||
users.Add(user);
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
public List<TUser> GetUsers()
|
||||
{
|
||||
List<TUser> users = new List<TUser>();
|
||||
string commandText = "Select * from Users order by NormalizedUserName";
|
||||
|
||||
var rows = _database.ExecuteCMDDict(commandText);
|
||||
foreach(Dictionary<string, object> row in rows)
|
||||
{
|
||||
TUser user = (TUser)Activator.CreateInstance(typeof(TUser));
|
||||
user.Id = (string)row["Id"];
|
||||
user.UserName = (string?)row["UserName"];
|
||||
user.PasswordHash = (string?)(string.IsNullOrEmpty((string?)row["PasswordHash"]) ? null : row["PasswordHash"]);
|
||||
user.SecurityStamp = (string?)(string.IsNullOrEmpty((string?)row["SecurityStamp"]) ? null : row["SecurityStamp"]);
|
||||
user.ConcurrencyStamp = (string?)(string.IsNullOrEmpty((string?)row["ConcurrencyStamp"]) ? null : row["ConcurrencyStamp"]);
|
||||
user.Email = (string?)(string.IsNullOrEmpty((string?)row["Email"]) ? null : row["Email"]);
|
||||
user.EmailConfirmed = row["EmailConfirmed"] == "1" ? true:false;
|
||||
user.PhoneNumber = (string?)(string.IsNullOrEmpty((string?)row["PhoneNumber"]) ? null : row["PhoneNumber"]);
|
||||
user.PhoneNumberConfirmed = row["PhoneNumberConfirmed"] == "1" ? true : false;
|
||||
user.NormalizedEmail = (string?)(string.IsNullOrEmpty((string?)row["NormalizedEmail"]) ? null : row["NormalizedEmail"]);
|
||||
user.NormalizedUserName = (string?)(string.IsNullOrEmpty((string?)row["NormalizedUserName"]) ? null : row["NormalizedUserName"]);
|
||||
user.LockoutEnabled = row["LockoutEnabled"] == "1" ? true : false;
|
||||
user.LockoutEnd = string.IsNullOrEmpty((string?)row["LockoutEnd"]) ? DateTime.Now : DateTime.Parse((string?)row["LockoutEnd"]);
|
||||
user.AccessFailedCount = string.IsNullOrEmpty((string?)row["AccessFailedCount"]) ? 0 : int.Parse((string?)row["AccessFailedCount"]);
|
||||
user.TwoFactorEnabled = row["TwoFactorEnabled"] == "1" ? true:false;
|
||||
user.SecurityProfile = GetSecurityProfile(user);
|
||||
user.UserPreferences = GetPreferences(user);
|
||||
users.Add(user);
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
public TUser GetUserByEmail(string email)
|
||||
{
|
||||
List<TUser> users = GetUserByName(email);
|
||||
if (users.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return users[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the user's password hash
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id</param>
|
||||
/// <returns></returns>
|
||||
public string GetPasswordHash(string userId)
|
||||
{
|
||||
string commandText = "Select PasswordHash from Users where Id = @id";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@id", userId);
|
||||
|
||||
DataTable table = _database.ExecuteCMD(commandText, parameters);
|
||||
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (string)table.Rows[0][0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the user's password hash
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="passwordHash"></param>
|
||||
/// <returns></returns>
|
||||
public int SetPasswordHash(string userId, string passwordHash)
|
||||
{
|
||||
string commandText = "Update Users set PasswordHash = @pwdHash where Id = @id";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@pwdHash", passwordHash);
|
||||
parameters.Add("@id", userId);
|
||||
|
||||
return _database.ExecuteCMD(commandText, parameters).Rows.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the user's security stamp
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public string GetSecurityStamp(string userId)
|
||||
{
|
||||
string commandText = "Select SecurityStamp from Users where Id = @id";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>() { { "@id", userId } };
|
||||
DataTable table = _database.ExecuteCMD(commandText, parameters);
|
||||
|
||||
if (table.Rows.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (string)table.Rows[0][0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a new user in the Users table
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
public int Insert(TUser user)
|
||||
{
|
||||
string commandText = @"Insert into Users (UserName, Id, PasswordHash, SecurityStamp, ConcurrencyStamp, Email, EmailConfirmed, PhoneNumber, PhoneNumberConfirmed, NormalizedEmail, NormalizedUserName, AccessFailedCount, LockoutEnabled, LockoutEnd, TwoFactorEnabled) values (@name, @id, @pwdHash, @SecStamp, @concurrencystamp, @email ,@emailconfirmed ,@phonenumber, @phonenumberconfirmed, @normalizedemail, @normalizedusername, @accesscount, @lockoutenabled, @lockoutenddate, @twofactorenabled);";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@name", user.UserName);
|
||||
parameters.Add("@id", user.Id);
|
||||
parameters.Add("@pwdHash", user.PasswordHash);
|
||||
parameters.Add("@SecStamp", user.SecurityStamp);
|
||||
parameters.Add("@concurrencystamp", user.ConcurrencyStamp);
|
||||
parameters.Add("@email", user.Email);
|
||||
parameters.Add("@emailconfirmed", user.EmailConfirmed);
|
||||
parameters.Add("@phonenumber", user.PhoneNumber);
|
||||
parameters.Add("@phonenumberconfirmed", user.PhoneNumberConfirmed);
|
||||
parameters.Add("@normalizedemail", user.NormalizedEmail);
|
||||
parameters.Add("@normalizedusername", user.NormalizedUserName);
|
||||
parameters.Add("@accesscount", user.AccessFailedCount);
|
||||
parameters.Add("@lockoutenabled", user.LockoutEnabled);
|
||||
parameters.Add("@lockoutenddate", user.LockoutEnd);
|
||||
parameters.Add("@twofactorenabled", user.TwoFactorEnabled);
|
||||
|
||||
// set default security profile
|
||||
SetSecurityProfile(user, new SecurityProfileViewModel());
|
||||
|
||||
// set default preferences
|
||||
SetPreferences(user, new List<UserPreferenceViewModel>());
|
||||
|
||||
return _database.ExecuteCMD(commandText, parameters).Rows.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a user from the Users table
|
||||
/// </summary>
|
||||
/// <param name="userId">The user's id</param>
|
||||
/// <returns></returns>
|
||||
private int Delete(string userId)
|
||||
{
|
||||
string commandText = "Delete from Users where Id = @userId; Delete from User_Settings where Id = @userId;";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@userId", userId);
|
||||
|
||||
return _database.ExecuteCMD(commandText, parameters).Rows.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a user from the Users table
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
public int Delete(TUser user)
|
||||
{
|
||||
return Delete(user.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a user in the Users table
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
public int Update(TUser user)
|
||||
{
|
||||
string commandText = @"Update Users set UserName = @userName, PasswordHash = @pwdHash, SecurityStamp = @secStamp, ConcurrencyStamp = @concurrencystamp, Email = @email, EmailConfirmed = @emailconfirmed, PhoneNumber = @phonenumber, PhoneNumberConfirmed = @phonenumberconfirmed, NormalizedEmail = @normalizedemail, NormalizedUserName = @normalizedusername, AccessFailedCount = @accesscount, LockoutEnabled = @lockoutenabled, LockoutEnd = @lockoutenddate, TwoFactorEnabled=@twofactorenabled WHERE Id = @userId;";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("@userId", user.Id);
|
||||
parameters.Add("@userName", user.UserName);
|
||||
parameters.Add("@pwdHash", user.PasswordHash);
|
||||
parameters.Add("@SecStamp", user.SecurityStamp);
|
||||
parameters.Add("@concurrencystamp", user.ConcurrencyStamp);
|
||||
parameters.Add("@email", user.Email);
|
||||
parameters.Add("@emailconfirmed", user.EmailConfirmed);
|
||||
parameters.Add("@phonenumber", user.PhoneNumber);
|
||||
parameters.Add("@phonenumberconfirmed", user.PhoneNumberConfirmed);
|
||||
parameters.Add("@normalizedemail", user.NormalizedEmail);
|
||||
parameters.Add("@normalizedusername", user.NormalizedUserName);
|
||||
parameters.Add("@accesscount", user.AccessFailedCount);
|
||||
parameters.Add("@lockoutenabled", user.LockoutEnabled);
|
||||
parameters.Add("@lockoutenddate", user.LockoutEnd);
|
||||
parameters.Add("@twofactorenabled", user.TwoFactorEnabled);
|
||||
|
||||
// set the security profile
|
||||
SetSecurityProfile(user, user.SecurityProfile);
|
||||
|
||||
// set preferences
|
||||
SetPreferences(user, user.UserPreferences);
|
||||
|
||||
return _database.ExecuteCMD(commandText, parameters).Rows.Count;
|
||||
}
|
||||
|
||||
private SecurityProfileViewModel GetSecurityProfile(TUser user)
|
||||
{
|
||||
string sql = "SELECT SecurityProfile FROM Users WHERE Id=@Id;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("Id", user.Id);
|
||||
|
||||
List<Dictionary<string, object>> data = _database.ExecuteCMDDict(sql, dbDict);
|
||||
if (data.Count == 0)
|
||||
{
|
||||
// no saved profile - return the default one
|
||||
return new SecurityProfileViewModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
string? securityProfileString = (string?)data[0]["SecurityProfile"];
|
||||
if (securityProfileString != null && securityProfileString != "null")
|
||||
{
|
||||
SecurityProfileViewModel securityProfile = Newtonsoft.Json.JsonConvert.DeserializeObject<SecurityProfileViewModel>(securityProfileString);
|
||||
return securityProfile;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new SecurityProfileViewModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int SetSecurityProfile(TUser user, SecurityProfileViewModel securityProfile)
|
||||
{
|
||||
string commandText = "UPDATE Users SET SecurityProfile=@SecurityProfile WHERE Id=@Id;";
|
||||
Dictionary<string, object> parameters = new Dictionary<string, object>();
|
||||
parameters.Add("Id", user.Id);
|
||||
parameters.Add("SecurityProfile", Newtonsoft.Json.JsonConvert.SerializeObject(securityProfile));
|
||||
|
||||
return _database.ExecuteCMD(commandText, parameters).Rows.Count;
|
||||
}
|
||||
|
||||
public List<UserPreferenceViewModel> GetPreferences(TUser user)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT `Setting`, `Value` FROM User_Settings WHERE Id=@id;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", user.Id);
|
||||
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<UserPreferenceViewModel> userPrefs = new List<UserPreferenceViewModel>();
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
UserPreferenceViewModel userPref = new UserPreferenceViewModel();
|
||||
userPref.Setting = (string)row["Setting"];
|
||||
userPref.Value = (string)row["Value"];
|
||||
userPrefs.Add(userPref);
|
||||
}
|
||||
|
||||
return userPrefs;
|
||||
}
|
||||
|
||||
public int SetPreferences(TUser user, List<UserPreferenceViewModel> model)
|
||||
{
|
||||
if (model != null)
|
||||
{
|
||||
List<UserPreferenceViewModel> userPreferences = GetPreferences(user);
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
foreach (UserPreferenceViewModel modelItem in model)
|
||||
{
|
||||
bool prefItemFound = false;
|
||||
foreach (UserPreferenceViewModel existing in userPreferences)
|
||||
{
|
||||
if (existing.Setting.ToLower() == modelItem.Setting.ToLower())
|
||||
{
|
||||
prefItemFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string sql = "INSERT INTO User_Settings (`Id`, `Setting`, `Value`) VALUES (@id, @setting, @value);";
|
||||
if (prefItemFound == true)
|
||||
{
|
||||
sql = "UPDATE User_Settings SET `Value`=@value WHERE `Id`=@id AND `Setting`=@setting";
|
||||
}
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", user.Id);
|
||||
dbDict.Add("setting", modelItem.Setting);
|
||||
dbDict.Add("value", modelItem.Value);
|
||||
db.ExecuteNonQuery(sql, dbDict);
|
||||
}
|
||||
|
||||
return model.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,100 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
public class ExternalLoginConfirmationViewModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[Display(Name = "Email")]
|
||||
public string Email { get; set; }
|
||||
}
|
||||
|
||||
public class ManageUserViewModel
|
||||
{
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Current password")]
|
||||
public string OldPassword { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "New password")]
|
||||
public string NewPassword { get; set; }
|
||||
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Confirm new password")]
|
||||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
|
||||
public string ConfirmPassword { get; set; }
|
||||
}
|
||||
|
||||
public class LoginViewModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[Display(Name = "Email")]
|
||||
public string Email { get; set; }
|
||||
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Password")]
|
||||
public string Password { get; set; }
|
||||
|
||||
[Display(Name = "Remember me?")]
|
||||
public bool RememberMe { get; set; }
|
||||
}
|
||||
|
||||
public class RegisterViewModel
|
||||
{
|
||||
[Required]
|
||||
[DataType(DataType.Text)]
|
||||
[Display(Name = "User name")]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[Display(Name = "Email")]
|
||||
public string Email { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Password")]
|
||||
public string Password { get; set; }
|
||||
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Confirm password")]
|
||||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
|
||||
public string ConfirmPassword { get; set; }
|
||||
}
|
||||
|
||||
public class ResetPasswordViewModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[Display(Name = "Email")]
|
||||
public string Email { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Password")]
|
||||
public string Password { get; set; }
|
||||
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Confirm password")]
|
||||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
|
||||
public string ConfirmPassword { get; set; }
|
||||
|
||||
public string Code { get; set; }
|
||||
}
|
||||
|
||||
public class ForgotPasswordViewModel
|
||||
{
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
[Display(Name = "Email")]
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class AddPhoneNumberViewModel
|
||||
{
|
||||
[Required]
|
||||
[Phone]
|
||||
[Display(Name = "Phone number")]
|
||||
public string PhoneNumber { get; set; }
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class ChangePasswordViewModel
|
||||
{
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Current password")]
|
||||
public string OldPassword { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 10)]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "New password")]
|
||||
public string NewPassword { get; set; }
|
||||
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Confirm new password")]
|
||||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
|
||||
public string ConfirmPassword { get; set; }
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class DisplayRecoveryCodesViewModel
|
||||
{
|
||||
[Required]
|
||||
public IEnumerable<string> Codes { get; set; }
|
||||
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class IndexViewModel
|
||||
{
|
||||
public bool HasPassword { get; set; }
|
||||
|
||||
public IList<UserLoginInfo> Logins { get; set; }
|
||||
|
||||
public string PhoneNumber { get; set; }
|
||||
|
||||
public bool TwoFactor { get; set; }
|
||||
|
||||
public bool BrowserRemembered { get; set; }
|
||||
|
||||
public string AuthenticatorKey { get; set; }
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class ManageLoginsViewModel
|
||||
{
|
||||
public IList<UserLoginInfo> CurrentLogins { get; set; }
|
||||
|
||||
public IList<AuthenticationScheme> OtherLogins { get; set; }
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
namespace Authentication
|
||||
{
|
||||
public class ProfileBasicViewModel
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
public string UserName { get; set; }
|
||||
public string EmailAddress { get; set; }
|
||||
public List<String> Roles { get; set; }
|
||||
public SecurityProfileViewModel SecurityProfile { get; set; }
|
||||
public List<UserPreferenceViewModel> UserPreferences { get; set; }
|
||||
public string HighestRole {
|
||||
get
|
||||
{
|
||||
string _highestRole = "";
|
||||
foreach (string role in Roles)
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case "Admin":
|
||||
// there is no higher
|
||||
_highestRole = role;
|
||||
break;
|
||||
case "Gamer":
|
||||
// only one high is Admin, so check for that
|
||||
if (_highestRole != "Admin")
|
||||
{
|
||||
_highestRole = role;
|
||||
}
|
||||
break;
|
||||
case "Player":
|
||||
// make sure _highestRole isn't already set to Gamer or Admin
|
||||
if (_highestRole != "Admin" && _highestRole != "Gamer")
|
||||
{
|
||||
_highestRole = role;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_highestRole = "Player";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _highestRole;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class RemoveLoginViewModel
|
||||
{
|
||||
public string LoginProvider { get; set; }
|
||||
public string ProviderKey { get; set; }
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication
|
||||
{
|
||||
public class SecurityProfileViewModel
|
||||
{
|
||||
public AgeRestrictionItem AgeRestrictionPolicy { get; set; } = new AgeRestrictionItem{
|
||||
MaximumAgeRestriction = gaseous_server.Classes.Metadata.AgeGroups.AgeRestrictionGroupings.Adult,
|
||||
IncludeUnrated = true
|
||||
};
|
||||
|
||||
public class AgeRestrictionItem
|
||||
{
|
||||
public gaseous_server.Classes.Metadata.AgeGroups.AgeRestrictionGroupings MaximumAgeRestriction { get; set; }
|
||||
public bool IncludeUnrated { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class SendCodeViewModel
|
||||
{
|
||||
public string SelectedProvider { get; set; }
|
||||
|
||||
public ICollection<SelectListItem> Providers { get; set; }
|
||||
|
||||
public string ReturnUrl { get; set; }
|
||||
|
||||
public bool RememberMe { get; set; }
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class SetPasswordViewModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "New password")]
|
||||
public string NewPassword { get; set; }
|
||||
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Confirm new password")]
|
||||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
|
||||
public string ConfirmPassword { get; set; }
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class UseRecoveryCodeViewModel
|
||||
{
|
||||
[Required]
|
||||
public string Code { get; set; }
|
||||
|
||||
public string ReturnUrl { get; set; }
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
namespace Authentication;
|
||||
|
||||
public class UserPreferenceViewModel
|
||||
{
|
||||
public string Setting { get; set; }
|
||||
|
||||
public string Value { get; set; }
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
namespace Authentication
|
||||
{
|
||||
public class UserViewModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string EmailAddress { get; set; }
|
||||
public bool LockoutEnabled { get; set; }
|
||||
public DateTimeOffset? LockoutEnd { get; set; }
|
||||
public List<string> Roles { get; set; }
|
||||
public SecurityProfileViewModel SecurityProfile { get; set; }
|
||||
public string HighestRole {
|
||||
get
|
||||
{
|
||||
string _highestRole = "";
|
||||
foreach (string role in Roles)
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case "Admin":
|
||||
// there is no higher
|
||||
_highestRole = role;
|
||||
break;
|
||||
case "Gamer":
|
||||
// only one high is Admin, so check for that
|
||||
if (_highestRole != "Admin")
|
||||
{
|
||||
_highestRole = role;
|
||||
}
|
||||
break;
|
||||
case "Player":
|
||||
// make sure _highestRole isn't already set to Gamer or Admin
|
||||
if (_highestRole != "Admin" && _highestRole != "Gamer")
|
||||
{
|
||||
_highestRole = role;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_highestRole = "Player";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _highestRole;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class VerifyAuthenticatorCodeViewModel
|
||||
{
|
||||
[Required]
|
||||
public string Code { get; set; }
|
||||
|
||||
public string ReturnUrl { get; set; }
|
||||
|
||||
[Display(Name = "Remember this browser?")]
|
||||
public bool RememberBrowser { get; set; }
|
||||
|
||||
[Display(Name = "Remember me?")]
|
||||
public bool RememberMe { get; set; }
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class VerifyCodeViewModel
|
||||
{
|
||||
[Required]
|
||||
public string Provider { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Code { get; set; }
|
||||
|
||||
public string ReturnUrl { get; set; }
|
||||
|
||||
[Display(Name = "Remember this browser?")]
|
||||
public bool RememberBrowser { get; set; }
|
||||
|
||||
[Display(Name = "Remember me?")]
|
||||
public bool RememberMe { get; set; }
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Authentication;
|
||||
|
||||
public class VerifyPhoneNumberViewModel
|
||||
{
|
||||
[Required]
|
||||
public string Code { get; set; }
|
||||
|
||||
[Required]
|
||||
[Phone]
|
||||
[Display(Name = "Phone number")]
|
||||
public string PhoneNumber { get; set; }
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using gaseous_tools;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
|
@@ -4,32 +4,24 @@ using System.IO.Compression;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using Authentication;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Controllers;
|
||||
using gaseous_server.Models;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class Collections
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
|
||||
public Collections(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager)
|
||||
public Collections()
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
|
||||
}
|
||||
|
||||
public static List<CollectionItem> GetCollections() {
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM RomCollections ORDER BY `Name`";
|
||||
|
||||
DataTable data = db.ExecuteCMD(sql);
|
||||
@@ -44,7 +36,7 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
|
||||
public static CollectionItem GetCollection(long Id) {
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM RomCollections WHERE Id = @id ORDER BY `Name`";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", Id);
|
||||
@@ -65,7 +57,7 @@ namespace gaseous_server.Classes
|
||||
|
||||
public static CollectionItem NewCollection(CollectionItem item)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "INSERT INTO RomCollections (`Name`, Description, Platforms, Genres, Players, PlayerPerspectives, Themes, MinimumRating, MaximumRating, MaximumRomsPerPlatform, MaximumBytesPerPlatform, MaximumCollectionSizeInBytes, FolderStructure, IncludeBIOSFiles, AlwaysInclude, BuiltStatus) VALUES (@name, @description, @platforms, @genres, @players, @playerperspectives, @themes, @minimumrating, @maximumrating, @maximumromsperplatform, @maximumbytesperplatform, @maximumcollectionsizeinbytes, @folderstructure, @includebiosfiles, @alwaysinclude, @builtstatus); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("name", item.Name);
|
||||
@@ -96,7 +88,7 @@ namespace gaseous_server.Classes
|
||||
|
||||
public static CollectionItem EditCollection(long Id, CollectionItem item, bool ForceRebuild = true)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "UPDATE RomCollections SET `Name`=@name, Description=@description, Platforms=@platforms, Genres=@genres, Players=@players, PlayerPerspectives=@playerperspectives, Themes=@themes, MinimumRating=@minimumrating, MaximumRating=@maximumrating, MaximumRomsPerPlatform=@maximumromsperplatform, MaximumBytesPerPlatform=@maximumbytesperplatform, MaximumCollectionSizeInBytes=@maximumcollectionsizeinbytes, FolderStructure=@folderstructure, IncludeBIOSFiles=@includebiosfiles, AlwaysInclude=@alwaysinclude, BuiltStatus=@builtstatus WHERE Id=@id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", Id);
|
||||
@@ -151,7 +143,7 @@ namespace gaseous_server.Classes
|
||||
|
||||
public static void DeleteCollection(long Id)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "DELETE FROM RomCollections WHERE Id=@id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", Id);
|
||||
@@ -171,7 +163,7 @@ namespace gaseous_server.Classes
|
||||
if (collectionItem.BuildStatus != CollectionItem.CollectionBuildStatus.Building)
|
||||
{
|
||||
// set collection item to waitingforbuild
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "UPDATE RomCollections SET BuiltStatus=@bs WHERE Id=@id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", Id);
|
||||
@@ -220,11 +212,8 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
} else {
|
||||
// get all platforms to pull from
|
||||
Dictionary<string, List<Filters.FilterItem>> FilterDict = Filters.Filter(AgeGroups.AgeRestrictionGroupings.Adult, true);
|
||||
List<Classes.Filters.FilterItem> filteredPlatforms = (List<Classes.Filters.FilterItem>)FilterDict["platforms"];
|
||||
foreach (Filters.FilterItem filterItem in filteredPlatforms) {
|
||||
platforms.Add(Platforms.GetPlatform(filterItem.Id));
|
||||
}
|
||||
FilterController filterController = new FilterController();
|
||||
platforms.AddRange((List<Platform>)filterController.Filter()["platforms"]);
|
||||
}
|
||||
|
||||
// build collection
|
||||
@@ -277,7 +266,7 @@ namespace gaseous_server.Classes
|
||||
gameItem.InclusionStatus.PlatformId = alwaysIncludeItem.PlatformId;
|
||||
gameItem.InclusionStatus.GameId = alwaysIncludeItem.GameId;
|
||||
gameItem.InclusionStatus.InclusionState = alwaysIncludeItem.InclusionState;
|
||||
gameItem.Roms = Roms.GetRoms((long)gameItem.Id, (long)platform.Id).GameRomItems;
|
||||
gameItem.Roms = Roms.GetRoms((long)gameItem.Id, (long)platform.Id);
|
||||
|
||||
collectionPlatformItem.Games.Add(gameItem);
|
||||
}
|
||||
@@ -297,7 +286,7 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
CollectionContents.CollectionPlatformItem.CollectionGameItem collectionGameItem = new CollectionContents.CollectionPlatformItem.CollectionGameItem(game);
|
||||
|
||||
List<Roms.GameRomItem> gameRoms = Roms.GetRoms((long)game.Id, (long)platform.Id).GameRomItems;
|
||||
List<Roms.GameRomItem> gameRoms = Roms.GetRoms((long)game.Id, (long)platform.Id);
|
||||
|
||||
bool AddGame = false;
|
||||
|
||||
@@ -374,7 +363,7 @@ namespace gaseous_server.Classes
|
||||
|
||||
public static void CompileCollections(long CollectionId)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
CollectionItem collectionItem = GetCollection(CollectionId);
|
||||
if (collectionItem.BuildStatus == CollectionItem.CollectionBuildStatus.WaitingForBuild)
|
||||
@@ -427,7 +416,7 @@ namespace gaseous_server.Classes
|
||||
if (File.Exists(biosItem.biosPath))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Collections", "Copying BIOS file: " + biosItem.filename);
|
||||
File.Copy(biosItem.biosPath, Path.Combine(ZipBiosPath, biosItem.filename), true);
|
||||
File.Copy(biosItem.biosPath, Path.Combine(ZipBiosPath, biosItem.filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -499,7 +488,7 @@ namespace gaseous_server.Classes
|
||||
if (File.Exists(gameRomItem.Path))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Collections", "Copying ROM: " + gameRomItem.Name);
|
||||
File.Copy(gameRomItem.Path, Path.Combine(ZipGamePath, gameRomItem.Name), true);
|
||||
File.Copy(gameRomItem.Path, Path.Combine(ZipGamePath, gameRomItem.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,143 +0,0 @@
|
||||
using System.Data;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using IGDB.Models;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class Filters
|
||||
{
|
||||
public static Dictionary<string, List<FilterItem>> Filter(Metadata.AgeGroups.AgeRestrictionGroupings MaximumAgeRestriction, bool IncludeUnrated)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
Dictionary<string, List<FilterItem>> FilterSet = new Dictionary<string, List<FilterItem>>();
|
||||
|
||||
// platforms
|
||||
List<FilterItem> platforms = new List<FilterItem>();
|
||||
|
||||
string ageRestriction_Platform = "AgeGroup.AgeGroupId <= " + (int)MaximumAgeRestriction;
|
||||
string ageRestriction_Generic = "view_Games.AgeGroupId <= " + (int)MaximumAgeRestriction;
|
||||
if (IncludeUnrated == true)
|
||||
{
|
||||
ageRestriction_Platform += " OR AgeGroup.AgeGroupId IS NULL";
|
||||
ageRestriction_Generic += " OR view_Games.AgeGroupId IS NULL";
|
||||
}
|
||||
|
||||
string sql = "SELECT Platform.Id, Platform.`Name`, COUNT(Game.Id) AS GameCount FROM (SELECT DISTINCT Game.Id, Games_Roms.PlatformId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId WHERE (" + ageRestriction_Platform + ") GROUP BY Game.Id , Games_Roms.PlatformId HAVING RomCount > 0) Game JOIN Platform ON Game.PlatformId = Platform.Id GROUP BY Platform.`Name`;";
|
||||
|
||||
DataTable dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterItem platformItem = new FilterItem(dr);
|
||||
platforms.Add(platformItem);
|
||||
|
||||
}
|
||||
FilterSet.Add("platforms", platforms);
|
||||
|
||||
// genres
|
||||
List<FilterItem> genres = new List<FilterItem>();
|
||||
dbResponse = GetGenericFilterItem(db, "Genre", ageRestriction_Platform);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterItem genreItem = new FilterItem(dr);
|
||||
genres.Add(genreItem);
|
||||
}
|
||||
FilterSet.Add("genres", genres);
|
||||
|
||||
// game modes
|
||||
List<FilterItem> gameModes = new List<FilterItem>();
|
||||
dbResponse = GetGenericFilterItem(db, "GameMode", ageRestriction_Platform);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterItem gameModeItem = new FilterItem(dr);
|
||||
gameModes.Add(gameModeItem);
|
||||
}
|
||||
FilterSet.Add("gamemodes", gameModes);
|
||||
|
||||
// player perspectives
|
||||
List<FilterItem> playerPerspectives = new List<FilterItem>();
|
||||
dbResponse = GetGenericFilterItem(db, "PlayerPerspective", ageRestriction_Platform);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterItem playerPerspectiveItem = new FilterItem(dr);
|
||||
playerPerspectives.Add(playerPerspectiveItem);
|
||||
}
|
||||
FilterSet.Add("playerperspectives", playerPerspectives);
|
||||
|
||||
// themes
|
||||
List<FilterItem> themes = new List<FilterItem>();
|
||||
dbResponse = GetGenericFilterItem(db, "Theme", ageRestriction_Platform);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterItem themeItem = new FilterItem(dr);
|
||||
themes.Add(themeItem);
|
||||
}
|
||||
FilterSet.Add("themes", themes);
|
||||
|
||||
// age groups
|
||||
List<FilterItem> agegroupings = new List<FilterItem>();
|
||||
sql = "SELECT Game.AgeGroupId, COUNT(Game.Id) AS GameCount FROM (SELECT DISTINCT Game.Id, AgeGroup.AgeGroupId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId WHERE (" + ageRestriction_Platform + ") GROUP BY Game.Id HAVING RomCount > 0) Game GROUP BY Game.AgeGroupId ORDER BY Game.AgeGroupId DESC";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
FilterItem filterAgeGrouping = new FilterItem();
|
||||
if (dr["AgeGroupId"] == DBNull.Value)
|
||||
{
|
||||
filterAgeGrouping.Id = (int)(long)AgeGroups.AgeRestrictionGroupings.Unclassified;
|
||||
filterAgeGrouping.Name = AgeGroups.AgeRestrictionGroupings.Unclassified.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
int ageGroupLong = (int)dr["AgeGroupId"];
|
||||
AgeGroups.AgeRestrictionGroupings ageGroup = (AgeGroups.AgeRestrictionGroupings)ageGroupLong;
|
||||
filterAgeGrouping.Id = ageGroupLong;
|
||||
filterAgeGrouping.Name = ageGroup.ToString();
|
||||
}
|
||||
filterAgeGrouping.GameCount = (int)(long)dr["GameCount"];
|
||||
agegroupings.Add(filterAgeGrouping);
|
||||
}
|
||||
FilterSet.Add("agegroupings", agegroupings);
|
||||
|
||||
return FilterSet;
|
||||
}
|
||||
|
||||
private static DataTable GetGenericFilterItem(Database db, string Name, string AgeRestriction)
|
||||
{
|
||||
//string sql = "SELECT DISTINCT <ITEMNAME>.Id, <ITEMNAME>.`Name`, COUNT(view_Games.Id) AS GameCount FROM <ITEMNAME> LEFT JOIN Relation_Game_<ITEMNAME>s ON Relation_Game_<ITEMNAME>s.<ITEMNAME>sId = <ITEMNAME>.Id LEFT JOIN view_Games ON view_Games.Id = Relation_Game_<ITEMNAME>s.GameId WHERE (" + AgeRestriction_Generic + ") GROUP BY <ITEMNAME>.Id HAVING GameCount > 0 ORDER BY <ITEMNAME>.`Name`;";
|
||||
|
||||
string sql = "SELECT <ITEMNAME>.Id, <ITEMNAME>.`Name`, COUNT(Game.Id) AS GameCount FROM (SELECT DISTINCT Game.Id, AgeGroup.AgeGroupId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId WHERE (" + AgeRestriction + ") GROUP BY Game.Id HAVING RomCount > 0) Game JOIN Relation_Game_<ITEMNAME>s ON Game.Id = Relation_Game_<ITEMNAME>s.GameId JOIN <ITEMNAME> ON Relation_Game_<ITEMNAME>s.<ITEMNAME>sId = <ITEMNAME>.Id GROUP BY <ITEMNAME>.`Name` ORDER BY <ITEMNAME>.`Name`;";
|
||||
sql = sql.Replace("<ITEMNAME>", Name);
|
||||
DataTable dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
return dbResponse;
|
||||
}
|
||||
|
||||
public class FilterItem
|
||||
{
|
||||
public FilterItem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public FilterItem(DataRow dr)
|
||||
{
|
||||
this.Id = (long)dr["Id"];
|
||||
this.Name = (string)dr["Name"];
|
||||
this.GameCount = (int)(long)dr["GameCount"];
|
||||
}
|
||||
|
||||
public long Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public int GameCount { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,195 +0,0 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using IGDB.Models;
|
||||
using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow;
|
||||
|
||||
namespace gaseous_server
|
||||
{
|
||||
public static class GameLibrary
|
||||
{
|
||||
// exceptions
|
||||
public class PathExists : Exception
|
||||
{
|
||||
public PathExists(string path) : base("The library path " + path + " already exists.")
|
||||
{}
|
||||
}
|
||||
|
||||
public class PathNotFound : Exception
|
||||
{
|
||||
public PathNotFound(string path) : base("The path " + path + " does not exist.")
|
||||
{}
|
||||
}
|
||||
|
||||
public class LibraryNotFound : Exception
|
||||
{
|
||||
public LibraryNotFound(int LibraryId) : base("Library id " + LibraryId + " does not exist.")
|
||||
{}
|
||||
}
|
||||
|
||||
public class CannotDeleteDefaultLibrary : Exception
|
||||
{
|
||||
public CannotDeleteDefaultLibrary() : base("Unable to delete the default library.")
|
||||
{}
|
||||
}
|
||||
|
||||
// code
|
||||
public static LibraryItem GetDefaultLibrary
|
||||
{
|
||||
get
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM GameLibraries WHERE DefaultLibrary=1 LIMIT 1";
|
||||
DataTable data = db.ExecuteCMD(sql);
|
||||
DataRow row = data.Rows[0];
|
||||
LibraryItem library = new LibraryItem((int)row["Id"], (string)row["Name"], (string)row["Path"], (long)row["DefaultPlatform"], Convert.ToBoolean((int)row["DefaultLibrary"]));
|
||||
|
||||
if (!Directory.Exists(library.Path))
|
||||
{
|
||||
Directory.CreateDirectory(library.Path);
|
||||
}
|
||||
|
||||
return library;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<LibraryItem> GetLibraries
|
||||
{
|
||||
get
|
||||
{
|
||||
List<LibraryItem> libraryItems = new List<LibraryItem>();
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM GameLibraries";
|
||||
DataTable data = db.ExecuteCMD(sql);
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
LibraryItem library = new LibraryItem((int)row["Id"], (string)row["Name"], (string)row["Path"], (long)row["DefaultPlatform"], Convert.ToBoolean((int)row["DefaultLibrary"]));
|
||||
libraryItems.Add(library);
|
||||
|
||||
if (library.IsDefaultLibrary == true)
|
||||
{
|
||||
// check directory exists
|
||||
if (!Directory.Exists(library.Path))
|
||||
{
|
||||
Directory.CreateDirectory(library.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return libraryItems;
|
||||
}
|
||||
}
|
||||
|
||||
public static LibraryItem AddLibrary(string Name, string Path, long DefaultPlatformId)
|
||||
{
|
||||
string PathName = Common.NormalizePath(Path);
|
||||
|
||||
// check path isn't already in place
|
||||
foreach (LibraryItem item in GetLibraries)
|
||||
{
|
||||
if (Common.NormalizePath(PathName) == Common.NormalizePath(item.Path))
|
||||
{
|
||||
// already existing path!
|
||||
throw new PathExists(PathName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!System.IO.Path.Exists(PathName))
|
||||
{
|
||||
throw new PathNotFound(PathName);
|
||||
}
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "INSERT INTO GameLibraries (Name, Path, DefaultPlatform, DefaultLibrary) VALUES (@name, @path, @defaultplatform, 0); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("name", Name);
|
||||
dbDict.Add("path", PathName);
|
||||
dbDict.Add("defaultplatform", DefaultPlatformId);
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
int newLibraryId = (int)(long)data.Rows[0][0];
|
||||
|
||||
return GetLibrary(newLibraryId);
|
||||
}
|
||||
|
||||
public static void DeleteLibrary(int LibraryId)
|
||||
{
|
||||
if (GetLibrary(LibraryId).IsDefaultLibrary == false)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "DELETE FROM Games_Roms WHERE LibraryId=@id; DELETE FROM GameLibraries WHERE Id=@id;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", LibraryId);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CannotDeleteDefaultLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
public static LibraryItem GetLibrary(int LibraryId)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM GameLibraries WHERE Id=@id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", LibraryId);
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
if (data.Rows.Count > 0)
|
||||
{
|
||||
DataRow row = data.Rows[0];
|
||||
LibraryItem library = new LibraryItem((int)row["Id"], (string)row["Name"], (string)row["Path"], (long)row["DefaultPlatform"], Convert.ToBoolean((int)row["DefaultLibrary"]));
|
||||
return library;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new LibraryNotFound(LibraryId);
|
||||
}
|
||||
}
|
||||
|
||||
public class LibraryItem
|
||||
{
|
||||
public LibraryItem(int Id, string Name, string Path, long DefaultPlatformId, bool IsDefaultLibrary)
|
||||
{
|
||||
_Id = Id;
|
||||
_Name = Name;
|
||||
_Path = Path;
|
||||
_DefaultPlatformId = DefaultPlatformId;
|
||||
_IsDefaultLibrary = IsDefaultLibrary;
|
||||
|
||||
if (!Directory.Exists(Path))
|
||||
{
|
||||
Directory.CreateDirectory(Path);
|
||||
}
|
||||
}
|
||||
|
||||
int _Id = 0;
|
||||
string _Name = "";
|
||||
string _Path = "";
|
||||
long _DefaultPlatformId = 0;
|
||||
bool _IsDefaultLibrary = false;
|
||||
|
||||
public int Id => _Id;
|
||||
public string Name => _Name;
|
||||
public string Path => _Path;
|
||||
public long DefaultPlatformId => _DefaultPlatformId;
|
||||
public string? DefaultPlatformName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_DefaultPlatformId != 0)
|
||||
{
|
||||
Platform platform = Platforms.GetPlatform(_DefaultPlatformId);
|
||||
return platform.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool IsDefaultLibrary => _IsDefaultLibrary;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,19 +1,18 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Policy;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using NuGet.Common;
|
||||
using NuGet.LibraryModel;
|
||||
using MySqlX.XDevAPI;
|
||||
using Org.BouncyCastle.Utilities.IO.Pem;
|
||||
using static gaseous_server.Classes.Metadata.Games;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class ImportGames : QueueItemStatus
|
||||
public class ImportGames
|
||||
{
|
||||
public ImportGames(string ImportPath)
|
||||
{
|
||||
@@ -23,19 +22,8 @@ namespace gaseous_server.Classes
|
||||
string[] importContents_Directories = Directory.GetDirectories(ImportPath);
|
||||
|
||||
// import files first
|
||||
int importCount = 1;
|
||||
foreach (string importContent in importContents_Files) {
|
||||
SetStatus(importCount, importContents_Files.Length, "Importing file: " + importContent);
|
||||
|
||||
ImportGame.ImportGameFile(importContent, null);
|
||||
|
||||
importCount += 1;
|
||||
}
|
||||
ClearStatus();
|
||||
|
||||
// import sub directories
|
||||
foreach (string importDir in importContents_Directories) {
|
||||
Classes.ImportGames importGames = new Classes.ImportGames(importDir);
|
||||
ImportGame.ImportGameFile(importContent, null, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -48,11 +36,11 @@ namespace gaseous_server.Classes
|
||||
|
||||
}
|
||||
|
||||
public class ImportGame : QueueItemStatus
|
||||
public class ImportGame
|
||||
{
|
||||
public static void ImportGameFile(string GameFileImportPath, IGDB.Models.Platform? OverridePlatform)
|
||||
public static void ImportGameFile(string GameFileImportPath, IGDB.Models.Platform? OverridePlatform, bool IsDirectory = false)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
|
||||
@@ -61,6 +49,8 @@ namespace gaseous_server.Classes
|
||||
Logging.Log(Logging.LogType.Debug, "Import Game", "Skipping item " + GameFileImportPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsDirectory == false)
|
||||
{
|
||||
FileInfo fi = new FileInfo(GameFileImportPath);
|
||||
Common.hashObject hash = new Common.hashObject(GameFileImportPath);
|
||||
@@ -77,25 +67,9 @@ namespace gaseous_server.Classes
|
||||
DataTable importDB = db.ExecuteCMD(sql, dbDict);
|
||||
if ((Int64)importDB.Rows[0]["count"] > 0)
|
||||
{
|
||||
// import source was the import directory
|
||||
if (GameFileImportPath.StartsWith(Config.LibraryConfiguration.LibraryImportDirectory))
|
||||
if (!GameFileImportPath.StartsWith(Config.LibraryConfiguration.LibraryImportDirectory))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Import Game", " " + GameFileImportPath + " already in database - moving to " + Config.LibraryConfiguration.LibraryImportDuplicatesDirectory);
|
||||
|
||||
string targetPathWithFileName = GameFileImportPath.Replace(Config.LibraryConfiguration.LibraryImportDirectory, Config.LibraryConfiguration.LibraryImportDuplicatesDirectory);
|
||||
string targetPath = Path.GetDirectoryName(targetPathWithFileName);
|
||||
|
||||
if (!Directory.Exists(targetPath))
|
||||
{
|
||||
Directory.CreateDirectory(targetPath);
|
||||
}
|
||||
File.Move(GameFileImportPath, targetPathWithFileName, true);
|
||||
}
|
||||
|
||||
// import source was the upload directory
|
||||
if (GameFileImportPath.StartsWith(Config.LibraryConfiguration.LibraryUploadDirectory))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Import Game", " " + GameFileImportPath + " already in database - skipping import");
|
||||
Logging.Log(Logging.LogType.Warning, "Import Game", " " + GameFileImportPath + " already in database - skipping");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -124,7 +98,7 @@ namespace gaseous_server.Classes
|
||||
IGDB.Models.Game determinedGame = SearchForGame(discoveredSignature.Game.Name, discoveredSignature.Flags.IGDBPlatformId);
|
||||
|
||||
// add to database
|
||||
StoreROM(GameLibrary.GetDefaultLibrary, hash, determinedGame, determinedPlatform, discoveredSignature, GameFileImportPath);
|
||||
StoreROM(hash, determinedGame, determinedPlatform, discoveredSignature, GameFileImportPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -151,6 +125,7 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Models.Signatures_Games GetFileSignature(Common.hashObject hash, FileInfo fi, string GameFileImportPath)
|
||||
{
|
||||
@@ -162,8 +137,6 @@ namespace gaseous_server.Classes
|
||||
// extract the zip file and search the contents
|
||||
string ExtractPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, Path.GetRandomFileName());
|
||||
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
|
||||
try
|
||||
{
|
||||
ZipFile.ExtractToDirectory(GameFileImportPath, ExtractPath);
|
||||
|
||||
// loop through contents until we find the first signature match
|
||||
@@ -193,11 +166,6 @@ namespace gaseous_server.Classes
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Get Signature", "Error processing zip file: " + GameFileImportPath, ex);
|
||||
}
|
||||
|
||||
if (Directory.Exists(ExtractPath)) { Directory.Delete(ExtractPath, true); }
|
||||
}
|
||||
@@ -423,9 +391,9 @@ namespace gaseous_server.Classes
|
||||
return SearchCandidates;
|
||||
}
|
||||
|
||||
public static long StoreROM(GameLibrary.LibraryItem library, Common.hashObject hash, IGDB.Models.Game determinedGame, IGDB.Models.Platform determinedPlatform, Models.Signatures_Games discoveredSignature, string GameFileImportPath, long UpdateId = 0)
|
||||
public static long StoreROM(Common.hashObject hash, IGDB.Models.Game determinedGame, IGDB.Models.Platform determinedPlatform, Models.Signatures_Games discoveredSignature, string GameFileImportPath, long UpdateId = 0)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
string sql = "";
|
||||
|
||||
@@ -433,10 +401,10 @@ namespace gaseous_server.Classes
|
||||
|
||||
if (UpdateId == 0)
|
||||
{
|
||||
sql = "INSERT INTO Games_Roms (PlatformId, GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, Path, MetadataSource, MetadataGameName, MetadataVersion, LibraryId) VALUES (@platformid, @gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @Attributes, @romtype, @romtypemedia, @medialabel, @path, @metadatasource, @metadatagamename, @metadataversion, @libraryid); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
sql = "INSERT INTO Games_Roms (PlatformId, GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, Path, MetadataSource, MetadataGameName, MetadataVersion) VALUES (@platformid, @gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @Attributes, @romtype, @romtypemedia, @medialabel, @path, @metadatasource, @metadatagamename, @metadataversion); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
} else
|
||||
{
|
||||
sql = "UPDATE Games_Roms SET PlatformId=@platformid, GameId=@gameid, Name=@name, Size=@size, DevelopmentStatus=@developmentstatus, Attributes=@Attributes, RomType=@romtype, RomTypeMedia=@romtypemedia, MediaLabel=@medialabel, MetadataSource=@metadatasource, MetadataGameName=@metadatagamename, MetadataVersion=@metadataversion WHERE Id=@id;";
|
||||
sql = "UPDATE Games_Roms SET PlatformId=platformid, GameId=@gameid, Name=@name, Size=@size, DevelopmentStatus=@developmentstatus, Attributes=@Attributes, RomType=@romtype, RomTypeMedia=@romtypemedia, MediaLabel=@medialabel, MetadataSource=@metadatasource, MetadataGameName=@metadatagamename, MetadataVersion=@metadataversion WHERE Id=@id;";
|
||||
dbDict.Add("id", UpdateId);
|
||||
}
|
||||
dbDict.Add("platformid", Common.ReturnValueIfNull(determinedPlatform.Id, 0));
|
||||
@@ -450,7 +418,6 @@ namespace gaseous_server.Classes
|
||||
dbDict.Add("metadatasource", discoveredSignature.Rom.SignatureSource);
|
||||
dbDict.Add("metadatagamename", discoveredSignature.Game.Name);
|
||||
dbDict.Add("metadataversion", 2);
|
||||
dbDict.Add("libraryid", library.Id);
|
||||
|
||||
if (discoveredSignature.Rom.Attributes != null)
|
||||
{
|
||||
@@ -483,10 +450,7 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
|
||||
// move to destination
|
||||
if (library.IsDefaultLibrary == true)
|
||||
{
|
||||
MoveGameFile(romId);
|
||||
}
|
||||
|
||||
return romId;
|
||||
}
|
||||
@@ -510,7 +474,7 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
gameSlug = game.Slug;
|
||||
}
|
||||
string DestinationPath = Path.Combine(GameLibrary.GetDefaultLibrary.Path, gameSlug, platformSlug);
|
||||
string DestinationPath = Path.Combine(Config.LibraryConfiguration.LibraryDataDirectory, gameSlug, platformSlug);
|
||||
if (!Directory.Exists(DestinationPath))
|
||||
{
|
||||
Directory.CreateDirectory(DestinationPath);
|
||||
@@ -548,7 +512,7 @@ namespace gaseous_server.Classes
|
||||
File.Move(romPath, DestinationPath);
|
||||
|
||||
// update the db
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "UPDATE Games_Roms SET Path=@path WHERE Id=@id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", RomId);
|
||||
@@ -568,16 +532,12 @@ namespace gaseous_server.Classes
|
||||
|
||||
public static void OrganiseLibrary()
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Organise Library", "Starting default library organisation");
|
||||
|
||||
GameLibrary.LibraryItem library = GameLibrary.GetDefaultLibrary;
|
||||
Logging.Log(Logging.LogType.Information, "Organise Library", "Starting library organisation");
|
||||
|
||||
// move rom files to their new location
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM Games_Roms WHERE LibraryId = @libraryid";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("libraryid", library.Id);
|
||||
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM Games_Roms";
|
||||
DataTable romDT = db.ExecuteCMD(sql);
|
||||
|
||||
if (romDT.Rows.Count > 0)
|
||||
{
|
||||
@@ -590,12 +550,12 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
|
||||
// clean up empty directories
|
||||
DeleteOrphanedDirectories(GameLibrary.GetDefaultLibrary.Path);
|
||||
DeleteOrphanedDirectories(Config.LibraryConfiguration.LibraryDataDirectory);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Organise Library", "Finsihed default library organisation");
|
||||
Logging.Log(Logging.LogType.Information, "Organise Library", "Finsihed library organisation");
|
||||
}
|
||||
|
||||
public static void DeleteOrphanedDirectories(string startLocation)
|
||||
private static void DeleteOrphanedDirectories(string startLocation)
|
||||
{
|
||||
foreach (var directory in Directory.GetDirectories(startLocation))
|
||||
{
|
||||
@@ -608,24 +568,18 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
}
|
||||
|
||||
public void LibraryScan()
|
||||
public static void LibraryScan()
|
||||
{
|
||||
foreach (GameLibrary.LibraryItem library in GameLibrary.GetLibraries)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Starting library scan. Library " + library.Name);
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Starting library scan");
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Looking for duplicate library files to clean up");
|
||||
string duplicateSql = "DELETE r1 FROM Games_Roms r1 INNER JOIN Games_Roms r2 WHERE r1.Id > r2.Id AND r1.MD5 = r2.MD5 AND r1.LibraryId=@libraryid AND r2.LibraryId=@libraryid;";
|
||||
Dictionary<string, object> dupDict = new Dictionary<string, object>();
|
||||
dupDict.Add("libraryid", library.Id);
|
||||
db.ExecuteCMD(duplicateSql, dupDict);
|
||||
string duplicateSql = "DELETE r1 FROM Games_Roms r1 INNER JOIN Games_Roms r2 WHERE r1.Id > r2.Id AND r1.MD5 = r2.MD5;";
|
||||
db.ExecuteCMD(duplicateSql);
|
||||
|
||||
string sql = "SELECT * FROM Games_Roms WHERE LibraryId=@libraryid ORDER BY `name`";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("libraryid", library.Id);
|
||||
DataTable dtRoms = db.ExecuteCMD(sql, dbDict);
|
||||
string sql = "SELECT * FROM Games_Roms ORDER BY `name`";
|
||||
DataTable dtRoms = db.ExecuteCMD(sql);
|
||||
|
||||
// clean out database entries in the import folder
|
||||
if (dtRoms.Rows.Count > 0)
|
||||
@@ -635,28 +589,25 @@ namespace gaseous_server.Classes
|
||||
long romId = (long)dtRoms.Rows[i]["Id"];
|
||||
string romPath = (string)dtRoms.Rows[i]["Path"];
|
||||
|
||||
if (!romPath.StartsWith(library.Path))
|
||||
if (!romPath.StartsWith(Config.LibraryConfiguration.LibraryDataDirectory))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Deleting database entry for files with incorrect directory " + romPath);
|
||||
string deleteSql = "DELETE FROM Games_Roms WHERE Id=@id AND LibraryId=@libraryid";
|
||||
string deleteSql = "DELETE FROM Games_Roms WHERE Id=@id";
|
||||
Dictionary<string, object> deleteDict = new Dictionary<string, object>();
|
||||
deleteDict.Add("Id", romId);
|
||||
deleteDict.Add("libraryid", library.Id);
|
||||
db.ExecuteCMD(deleteSql, deleteDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sql = "SELECT * FROM Games_Roms ORDER BY `name`";
|
||||
dtRoms = db.ExecuteCMD(sql, dbDict);
|
||||
dtRoms = db.ExecuteCMD(sql);
|
||||
|
||||
// search for files in the library that aren't in the database
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Looking for orphaned library files to add");
|
||||
string[] LibraryFiles = Directory.GetFiles(library.Path, "*.*", SearchOption.AllDirectories);
|
||||
int StatusCount = 0;
|
||||
string[] LibraryFiles = Directory.GetFiles(Config.LibraryConfiguration.LibraryDataDirectory, "*.*", SearchOption.AllDirectories);
|
||||
foreach (string LibraryFile in LibraryFiles)
|
||||
{
|
||||
SetStatus(StatusCount, LibraryFiles.Length, "Processing file " + LibraryFile);
|
||||
if (!Common.SkippableFiles.Contains<string>(Path.GetFileName(LibraryFile), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Common.hashObject LibraryFileHash = new Common.hashObject(LibraryFile);
|
||||
@@ -688,46 +639,23 @@ namespace gaseous_server.Classes
|
||||
|
||||
// get discovered platform
|
||||
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
|
||||
|
||||
IGDB.Models.Game determinedGame = new Game();
|
||||
try
|
||||
{
|
||||
if (determinedPlatform == null)
|
||||
{
|
||||
if (library.DefaultPlatformId == 0)
|
||||
{
|
||||
determinedPlatform = new IGDB.Models.Platform();
|
||||
determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
|
||||
}
|
||||
else
|
||||
{
|
||||
determinedPlatform = Platforms.GetPlatform(library.DefaultPlatformId);
|
||||
determinedGame = SearchForGame(sig.Game.Name, library.DefaultPlatformId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
determinedGame = SearchForGame(sig.Game.Name, (long)determinedPlatform.Id);
|
||||
}
|
||||
|
||||
StoreROM(library, hash, determinedGame, determinedPlatform, sig, LibraryFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Library Scan", " An error occurred while matching orphaned file: " + LibraryFile + ". Skipping.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
StatusCount += 1;
|
||||
}
|
||||
ClearStatus();
|
||||
IGDB.Models.Game determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
|
||||
|
||||
sql = "SELECT * FROM Games_Roms WHERE LibraryId=@libraryid ORDER BY `name`";
|
||||
dtRoms = db.ExecuteCMD(sql, dbDict);
|
||||
StoreROM(hash, determinedGame, determinedPlatform, sig, LibraryFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sql = "SELECT * FROM Games_Roms ORDER BY `name`";
|
||||
dtRoms = db.ExecuteCMD(sql);
|
||||
|
||||
// check all roms to see if their local file still exists
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Checking library files exist on disk");
|
||||
StatusCount = 0;
|
||||
if (dtRoms.Rows.Count > 0)
|
||||
{
|
||||
for (var i = 0; i < dtRoms.Rows.Count; i++)
|
||||
@@ -736,81 +664,29 @@ namespace gaseous_server.Classes
|
||||
string romPath = (string)dtRoms.Rows[i]["Path"];
|
||||
gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType romMetadataSource = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(int)dtRoms.Rows[i]["MetadataSource"];
|
||||
|
||||
SetStatus(StatusCount, dtRoms.Rows.Count, "Processing file " + romPath);
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Processing ROM at path " + romPath);
|
||||
|
||||
if (File.Exists(romPath))
|
||||
{
|
||||
if (library.IsDefaultLibrary == true)
|
||||
// file exists, so lets check to make sure the signature was matched, and update if a signature can be found
|
||||
if (
|
||||
romMetadataSource == gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType.None ||
|
||||
(int)dtRoms.Rows[i]["MetadataVersion"] == 1
|
||||
)
|
||||
{
|
||||
if (romPath != ComputeROMPath(romId))
|
||||
{
|
||||
MoveGameFile(romId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// file doesn't exist where it's supposed to be! delete it from the db
|
||||
Logging.Log(Logging.LogType.Warning, "Library Scan", " Deleting orphaned database entry for " + romPath);
|
||||
|
||||
string deleteSql = "DELETE FROM Games_Roms WHERE Id = @id AND LibraryId = @libraryid";
|
||||
Dictionary<string, object> deleteDict = new Dictionary<string, object>();
|
||||
deleteDict.Add("id", romId);
|
||||
deleteDict.Add("libraryid", library.Id);
|
||||
db.ExecuteCMD(deleteSql, deleteDict);
|
||||
}
|
||||
|
||||
StatusCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Library scan completed");
|
||||
}
|
||||
}
|
||||
|
||||
public void Rematcher(bool ForceExecute = false)
|
||||
{
|
||||
// rescan all titles with an unknown platform or title and see if we can get a match
|
||||
Logging.Log(Logging.LogType.Information, "Rematch Scan", "Rematch scan starting");
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
if (ForceExecute == false)
|
||||
{
|
||||
sql = "SELECT * FROM Games_Roms WHERE ((PlatformId = 0 OR GameId = 0) AND MetadataSource = 0) AND (LastMatchAttemptDate IS NULL OR LastMatchAttemptDate < @lastmatchattemptdate) LIMIT 100;";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql = "SELECT * FROM Games_Roms WHERE ((PlatformId = 0 OR GameId = 0) AND MetadataSource = 0);";
|
||||
}
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("lastmatchattemptdate", DateTime.UtcNow.AddDays(-7));
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
int StatusCount = -0;
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
SetStatus(StatusCount, data.Rows.Count, "Running rematcher");
|
||||
|
||||
// get library
|
||||
GameLibrary.LibraryItem library = GameLibrary.GetLibrary((int)row["LibraryId"]);
|
||||
|
||||
// get rom info
|
||||
long romId = (long)row["Id"];
|
||||
string romPath = (string)row["Path"];
|
||||
Common.hashObject hash = new Common.hashObject
|
||||
{
|
||||
md5hash = (string)row["MD5"],
|
||||
sha1hash = (string)row["SHA1"]
|
||||
md5hash = (string)dtRoms.Rows[i]["MD5"],
|
||||
sha1hash = (string)dtRoms.Rows[i]["SHA1"]
|
||||
};
|
||||
FileInfo fi = new FileInfo(romPath);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Rematch Scan", "Running rematch against " + romPath);
|
||||
|
||||
// determine rom signature
|
||||
Models.Signatures_Games sig = GetFileSignature(hash, fi, romPath);
|
||||
if (sig.Rom.SignatureSource != gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType.None)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", " Update signature found for " + romPath);
|
||||
|
||||
// determine rom platform
|
||||
// get discovered platform
|
||||
IGDB.Models.Platform determinedPlatform = Metadata.Platforms.GetPlatform(sig.Flags.IGDBPlatformId);
|
||||
if (determinedPlatform == null)
|
||||
{
|
||||
@@ -819,20 +695,29 @@ namespace gaseous_server.Classes
|
||||
|
||||
IGDB.Models.Game determinedGame = SearchForGame(sig.Game.Name, sig.Flags.IGDBPlatformId);
|
||||
|
||||
StoreROM(library, hash, determinedGame, determinedPlatform, sig, romPath, romId);
|
||||
|
||||
string attemptSql = "UPDATE Games_Roms SET LastMatchAttemptDate=@lastmatchattemptdate WHERE Id=@id;";
|
||||
Dictionary<string, object> dbLastAttemptDict = new Dictionary<string, object>();
|
||||
dbLastAttemptDict.Add("id", romId);
|
||||
dbLastAttemptDict.Add("lastmatchattemptdate", DateTime.UtcNow);
|
||||
db.ExecuteCMD(attemptSql, dbLastAttemptDict);
|
||||
|
||||
StatusCount += 1;
|
||||
StoreROM(hash, determinedGame, determinedPlatform, sig, romPath, romId);
|
||||
}
|
||||
}
|
||||
ClearStatus();
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Rematch Scan", "Rematch scan completed");
|
||||
ClearStatus();
|
||||
if (romPath != ComputeROMPath(romId))
|
||||
{
|
||||
MoveGameFile(romId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// file doesn't exist where it's supposed to be! delete it from the db
|
||||
Logging.Log(Logging.LogType.Warning, "Library Scan", " Deleting orphaned database entry for " + romPath);
|
||||
|
||||
string deleteSql = "DELETE FROM Games_Roms WHERE Id = @id";
|
||||
Dictionary<string, object> deleteDict = new Dictionary<string, object>();
|
||||
deleteDict.Add("id", romId);
|
||||
db.ExecuteCMD(deleteSql, deleteDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Library scan completed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,365 +0,0 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class Logging
|
||||
{
|
||||
private static DateTime lastDiskRetentionSweep = DateTime.UtcNow;
|
||||
public static bool WriteToDiskOnly { get; set; } = false;
|
||||
|
||||
static public void Log(LogType EventType, string ServerProcess, string Message, Exception? ExceptionValue = null, bool LogToDiskOnly = false)
|
||||
{
|
||||
LogItem logItem = new LogItem
|
||||
{
|
||||
EventTime = DateTime.UtcNow,
|
||||
EventType = EventType,
|
||||
Process = ServerProcess,
|
||||
Message = Message,
|
||||
ExceptionValue = Common.ReturnValueIfNull(ExceptionValue, "").ToString()
|
||||
};
|
||||
|
||||
bool AllowWrite = false;
|
||||
if (EventType == LogType.Debug)
|
||||
{
|
||||
if (Config.LoggingConfiguration.DebugLogging == true)
|
||||
{
|
||||
AllowWrite = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AllowWrite = true;
|
||||
}
|
||||
|
||||
if (AllowWrite == true)
|
||||
{
|
||||
// console output
|
||||
string TraceOutput = logItem.EventTime.ToString("yyyyMMdd HHmmss") + ": " + logItem.EventType.ToString() + ": " + logItem.Process + ": " + logItem.Message;
|
||||
if (logItem.ExceptionValue != null)
|
||||
{
|
||||
TraceOutput += Environment.NewLine + logItem.ExceptionValue.ToString();
|
||||
}
|
||||
switch(logItem.EventType) {
|
||||
case LogType.Information:
|
||||
Console.ForegroundColor = ConsoleColor.Blue;
|
||||
break;
|
||||
|
||||
case LogType.Warning:
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
break;
|
||||
|
||||
case LogType.Critical:
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
break;
|
||||
|
||||
case LogType.Debug:
|
||||
Console.ForegroundColor = ConsoleColor.Magenta;
|
||||
break;
|
||||
|
||||
}
|
||||
Console.WriteLine(TraceOutput);
|
||||
Console.ResetColor();
|
||||
|
||||
if (WriteToDiskOnly == true)
|
||||
{
|
||||
LogToDiskOnly = true;
|
||||
}
|
||||
|
||||
if (LogToDiskOnly == false)
|
||||
{
|
||||
if (Config.LoggingConfiguration.AlwaysLogToDisk == true)
|
||||
{
|
||||
LogToDisk(logItem, TraceOutput, null);
|
||||
}
|
||||
|
||||
string correlationId;
|
||||
try
|
||||
{
|
||||
if (CallContext.GetData("CorrelationId").ToString() == null)
|
||||
{
|
||||
correlationId = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
correlationId = CallContext.GetData("CorrelationId").ToString();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
correlationId = "";
|
||||
}
|
||||
|
||||
string callingProcess;
|
||||
try
|
||||
{
|
||||
if (CallContext.GetData("CallingProcess").ToString() == null)
|
||||
{
|
||||
callingProcess = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
callingProcess = CallContext.GetData("CallingProcess").ToString();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
callingProcess = "";
|
||||
}
|
||||
|
||||
string callingUser;
|
||||
try
|
||||
{
|
||||
if (CallContext.GetData("CallingUser").ToString() == null)
|
||||
{
|
||||
callingUser = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
callingUser = CallContext.GetData("CallingUser").ToString();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
callingUser = "";
|
||||
}
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRententionDate; INSERT INTO ServerLogs (EventTime, EventType, Process, Message, Exception, CorrelationId, CallingProcess, CallingUser) VALUES (@EventTime, @EventType, @Process, @Message, @Exception, @correlationid, @callingprocess, @callinguser);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("EventRententionDate", DateTime.UtcNow.AddDays(Config.LoggingConfiguration.LogRetention * -1));
|
||||
dbDict.Add("EventTime", logItem.EventTime);
|
||||
dbDict.Add("EventType", logItem.EventType);
|
||||
dbDict.Add("Process", logItem.Process);
|
||||
dbDict.Add("Message", logItem.Message);
|
||||
dbDict.Add("Exception", Common.ReturnValueIfNull(logItem.ExceptionValue, "").ToString());
|
||||
dbDict.Add("correlationid", correlationId);
|
||||
dbDict.Add("callingprocess", callingProcess);
|
||||
dbDict.Add("callinguser", callingUser);
|
||||
|
||||
try
|
||||
{
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogToDisk(logItem, TraceOutput, ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogToDisk(logItem, TraceOutput, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDiskRetentionSweep.AddMinutes(60) < DateTime.UtcNow)
|
||||
{
|
||||
// time to delete any old logs
|
||||
lastDiskRetentionSweep = DateTime.UtcNow;
|
||||
string[] files = Directory.GetFiles(Config.LogPath);
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
FileInfo fi = new FileInfo(file);
|
||||
if (fi.LastAccessTime < DateTime.Now.AddDays(Config.LoggingConfiguration.LogRetention * -1))
|
||||
{
|
||||
fi.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LogToDisk(LogItem logItem, string TraceOutput, Exception? exception)
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
// dump the error
|
||||
File.AppendAllText(Config.LogFilePath, logItem.EventTime.ToString("yyyyMMdd HHmmss") + ": " + logItem.EventType.ToString() + ": " + logItem.Process + ": " + logItem.Message + Environment.NewLine + exception.ToString());
|
||||
|
||||
|
||||
// something went wrong writing to the db
|
||||
File.AppendAllText(Config.LogFilePath, logItem.EventTime.ToString("yyyyMMdd HHmmss") + ": The following event was unable to be written to the log database:");
|
||||
}
|
||||
|
||||
File.AppendAllText(Config.LogFilePath, TraceOutput);
|
||||
}
|
||||
|
||||
static public List<LogItem> GetLogs(LogsViewModel model)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("StartIndex", model.StartIndex);
|
||||
dbDict.Add("PageNumber", (model.PageNumber - 1) * model.PageSize);
|
||||
dbDict.Add("PageSize", model.PageSize);
|
||||
string sql = "";
|
||||
|
||||
List<string> whereClauses = new List<string>();
|
||||
|
||||
// handle status criteria
|
||||
if (model.Status != null)
|
||||
{
|
||||
if (model.Status.Count > 0)
|
||||
{
|
||||
List<string> statusWhere = new List<string>();
|
||||
for (int i = 0; i < model.Status.Count; i++)
|
||||
{
|
||||
string valueName = "@eventtype" + i;
|
||||
statusWhere.Add(valueName);
|
||||
dbDict.Add(valueName, (int)model.Status[i]);
|
||||
}
|
||||
|
||||
whereClauses.Add("EventType IN (" + string.Join(",", statusWhere) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
// handle start date criteria
|
||||
if (model.StartDateTime != null)
|
||||
{
|
||||
dbDict.Add("startdate", model.StartDateTime);
|
||||
whereClauses.Add("EventTime >= @startdate");
|
||||
}
|
||||
|
||||
// handle end date criteria
|
||||
if (model.EndDateTime != null)
|
||||
{
|
||||
dbDict.Add("enddate", model.EndDateTime);
|
||||
whereClauses.Add("EventTime <= @enddate");
|
||||
}
|
||||
|
||||
// handle search text criteria
|
||||
if (model.SearchText != null)
|
||||
{
|
||||
if (model.SearchText.Length > 0)
|
||||
{
|
||||
dbDict.Add("messageSearch", model.SearchText);
|
||||
whereClauses.Add("MATCH(Message) AGAINST (@messageSearch)");
|
||||
}
|
||||
}
|
||||
|
||||
if (model.CorrelationId != null)
|
||||
{
|
||||
if (model.CorrelationId.Length > 0)
|
||||
{
|
||||
dbDict.Add("correlationId", model.CorrelationId);
|
||||
whereClauses.Add("CorrelationId = @correlationId");
|
||||
}
|
||||
}
|
||||
|
||||
if (model.CallingProcess != null)
|
||||
{
|
||||
if (model.CallingProcess.Length > 0)
|
||||
{
|
||||
dbDict.Add("callingProcess", model.CallingProcess);
|
||||
whereClauses.Add("CallingProcess = @callingProcess");
|
||||
}
|
||||
}
|
||||
|
||||
if (model.CallingUser != null)
|
||||
{
|
||||
if (model.CallingUser.Length > 0)
|
||||
{
|
||||
dbDict.Add("callingUser", model.CallingUser);
|
||||
whereClauses.Add("CallingUser = @callingUser");
|
||||
}
|
||||
}
|
||||
|
||||
// compile WHERE clause
|
||||
string whereClause = "";
|
||||
if (whereClauses.Count > 0)
|
||||
{
|
||||
whereClause = "(" + String.Join(" AND ", whereClauses) + ")";
|
||||
}
|
||||
|
||||
// execute query
|
||||
if (model.StartIndex == null)
|
||||
{
|
||||
if (whereClause.Length > 0)
|
||||
{
|
||||
whereClause = "WHERE " + whereClause;
|
||||
}
|
||||
|
||||
sql = "SELECT ServerLogs.Id, ServerLogs.EventTime, ServerLogs.EventType, ServerLogs.`Process`, ServerLogs.Message, ServerLogs.Exception, ServerLogs.CorrelationId, ServerLogs.CallingProcess, Users.Email FROM ServerLogs LEFT JOIN Users ON ServerLogs.CallingUser = Users.Id " + whereClause + " ORDER BY ServerLogs.Id DESC LIMIT @PageSize OFFSET @PageNumber;";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (whereClause.Length > 0)
|
||||
{
|
||||
whereClause = "AND " + whereClause;
|
||||
}
|
||||
|
||||
sql = "SELECT ServerLogs.Id, ServerLogs.EventTime, ServerLogs.EventType, ServerLogs.`Process`, ServerLogs.Message, ServerLogs.Exception, ServerLogs.CorrelationId, ServerLogs.CallingProcess, Users.Email FROM ServerLogs LEFT JOIN Users ON ServerLogs.CallingUser = Users.Id WHERE ServerLogs.Id < @StartIndex " + whereClause + " ORDER BY ServerLogs.Id DESC LIMIT @PageSize OFFSET @PageNumber;";
|
||||
}
|
||||
DataTable dataTable = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<LogItem> logs = new List<LogItem>();
|
||||
foreach (DataRow row in dataTable.Rows)
|
||||
{
|
||||
LogItem log = new LogItem
|
||||
{
|
||||
Id = (long)row["Id"],
|
||||
EventTime = DateTime.Parse(((DateTime)row["EventTime"]).ToString("yyyy-MM-ddThh:mm:ss") + 'Z'),
|
||||
EventType = (LogType)row["EventType"],
|
||||
Process = (string)row["Process"],
|
||||
Message = (string)row["Message"],
|
||||
ExceptionValue = (string)row["Exception"],
|
||||
CorrelationId = (string)Common.ReturnValueIfNull(row["CorrelationId"], ""),
|
||||
CallingProcess = (string)Common.ReturnValueIfNull(row["CallingProcess"], ""),
|
||||
CallingUser = (string)Common.ReturnValueIfNull(row["Email"], "")
|
||||
};
|
||||
|
||||
logs.Add(log);
|
||||
}
|
||||
|
||||
return logs;
|
||||
}
|
||||
|
||||
public enum LogType
|
||||
{
|
||||
Information = 0,
|
||||
Debug = 1,
|
||||
Warning = 2,
|
||||
Critical = 3
|
||||
}
|
||||
|
||||
public class LogItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public DateTime EventTime { get; set; }
|
||||
public LogType? EventType { get; set; }
|
||||
public string Process { get; set; } = "";
|
||||
public string CorrelationId { get; set; } = "";
|
||||
public string? CallingProcess { get; set; } = "";
|
||||
public string? CallingUser { get; set; } = "";
|
||||
private string _Message = "";
|
||||
public string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Message;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Message = value;
|
||||
}
|
||||
}
|
||||
public string? ExceptionValue { get; set; }
|
||||
}
|
||||
|
||||
public class LogsViewModel
|
||||
{
|
||||
public long? StartIndex { get; set; }
|
||||
public int PageNumber { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 100;
|
||||
public List<LogType> Status { get; set; } = new List<LogType>();
|
||||
public DateTime? StartDateTime { get; set; }
|
||||
public DateTime? EndDateTime { get; set; }
|
||||
public string? SearchText { get; set; }
|
||||
public string? CorrelationId { get; set; }
|
||||
public string? CallingProcess { get; set; }
|
||||
public string? CallingUser { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,74 +0,0 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using gaseous_server.Models;
|
||||
using Microsoft.VisualStudio.Web.CodeGeneration;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class Maintenance : QueueItemStatus
|
||||
{
|
||||
const int MaxFileAge = 30;
|
||||
|
||||
public void RunMaintenance()
|
||||
{
|
||||
// delete files and directories older than 7 days in PathsToClean
|
||||
List<string> PathsToClean = new List<string>();
|
||||
PathsToClean.Add(Config.LibraryConfiguration.LibraryUploadDirectory);
|
||||
PathsToClean.Add(Config.LibraryConfiguration.LibraryTempDirectory);
|
||||
|
||||
foreach (string PathToClean in PathsToClean)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Maintenance", "Removing files older than " + MaxFileAge + " days from " + PathToClean);
|
||||
|
||||
// get content
|
||||
// files first
|
||||
foreach (string filePath in Directory.GetFiles(PathToClean))
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(filePath);
|
||||
if (fileInfo.LastWriteTimeUtc.AddDays(MaxFileAge) < DateTime.UtcNow)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Maintenance", "Deleting file " + filePath);
|
||||
File.Delete(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
// now directories
|
||||
foreach (string dirPath in Directory.GetDirectories(PathToClean))
|
||||
{
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(dirPath);
|
||||
if (directoryInfo.LastWriteTimeUtc.AddDays(MaxFileAge) < DateTime.UtcNow)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Maintenance", "Deleting directory " + directoryInfo);
|
||||
Directory.Delete(dirPath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Maintenance", "Optimising database tables");
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SHOW TABLES;";
|
||||
DataTable tables = db.ExecuteCMD(sql);
|
||||
|
||||
int StatusCounter = 1;
|
||||
foreach (DataRow row in tables.Rows)
|
||||
{
|
||||
SetStatus(StatusCounter, tables.Rows.Count, "Optimising table " + row[0].ToString());
|
||||
|
||||
sql = "OPTIMIZE TABLE " + row[0].ToString();
|
||||
DataTable response = db.ExecuteCMD(sql);
|
||||
foreach (DataRow responseRow in response.Rows)
|
||||
{
|
||||
string retVal = "";
|
||||
for (int i = 0; i < responseRow.ItemArray.Length; i++)
|
||||
{
|
||||
retVal += responseRow.ItemArray[i] + "; ";
|
||||
}
|
||||
Logging.Log(Logging.LogType.Information, "Maintenance", "(" + StatusCounter + "/" + tables.Rows.Count + "): Optimise table " + row[0].ToString() + ": " + retVal);
|
||||
}
|
||||
|
||||
StatusCounter += 1;
|
||||
}
|
||||
ClearStatus();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,304 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using Microsoft.CodeAnalysis.Classification;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
public class AgeGroups
|
||||
{
|
||||
public AgeGroups()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static AgeGroup? GetAgeGroup(Game? game)
|
||||
{
|
||||
if (game == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
cacheStatus = Storage.GetCacheStatus("AgeGroup", (long)game.Id);
|
||||
|
||||
AgeGroup? RetVal = new AgeGroup();
|
||||
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
RetVal = _GetAgeGroup(game);
|
||||
Storage.NewCacheValue(RetVal, false);
|
||||
break;
|
||||
|
||||
case Storage.CacheStatus.Expired:
|
||||
RetVal = _GetAgeGroup(game);
|
||||
Storage.NewCacheValue(RetVal, true);
|
||||
break;
|
||||
|
||||
case Storage.CacheStatus.Current:
|
||||
RetVal = Storage.GetCacheValue<AgeGroup>(RetVal, "Id", game.Id);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
|
||||
public static AgeGroup? _GetAgeGroup(Game game)
|
||||
{
|
||||
// compile the maximum age group for the given game
|
||||
if (game != null)
|
||||
{
|
||||
if (game.AgeRatings != null)
|
||||
{
|
||||
if (game.AgeRatings.Ids != null)
|
||||
{
|
||||
// collect ratings values from metadata
|
||||
List<AgeRating> ageRatings = new List<AgeRating>();
|
||||
foreach (long ratingId in game.AgeRatings.Ids)
|
||||
{
|
||||
AgeRating? rating = AgeRatings.GetAgeRatings(ratingId);
|
||||
if (rating != null)
|
||||
{
|
||||
ageRatings.Add(rating);
|
||||
}
|
||||
}
|
||||
|
||||
// compile the ratings values into the ratings groups
|
||||
AgeRestrictionGroupings highestAgeGroup = AgeRestrictionGroupings.Unclassified;
|
||||
foreach (AgeRating ageRating in ageRatings)
|
||||
{
|
||||
foreach (KeyValuePair<AgeRestrictionGroupings, AgeGroupItem> ageGroupItem in AgeGroupingsFlat)
|
||||
{
|
||||
|
||||
PropertyInfo[] groupProps = typeof(AgeGroupItem).GetProperties();
|
||||
foreach (PropertyInfo property in groupProps)
|
||||
{
|
||||
if (RatingsBoards.Contains(property.Name))
|
||||
{
|
||||
List<AgeRatingTitle> ratingBoard = (List<AgeRatingTitle>)property.GetValue(ageGroupItem.Value);
|
||||
foreach (AgeRatingTitle ratingTitle in ratingBoard)
|
||||
{
|
||||
if (ageRating.Rating == ratingTitle)
|
||||
{
|
||||
if (highestAgeGroup < ageGroupItem.Key)
|
||||
{
|
||||
highestAgeGroup = ageGroupItem.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return the compiled ratings group
|
||||
AgeGroup ageGroup = new AgeGroup();
|
||||
ageGroup.Id = game.Id;
|
||||
ageGroup.GameId = game.Id;
|
||||
if (highestAgeGroup == 0)
|
||||
{
|
||||
ageGroup.AgeGroupId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ageGroup.AgeGroupId = highestAgeGroup;
|
||||
}
|
||||
|
||||
return ageGroup;
|
||||
}
|
||||
else
|
||||
{
|
||||
AgeGroup ageGroup = new AgeGroup();
|
||||
ageGroup.Id = game.Id;
|
||||
ageGroup.GameId = game.Id;
|
||||
ageGroup.AgeGroupId = null;
|
||||
|
||||
return ageGroup;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AgeGroup ageGroup = new AgeGroup();
|
||||
ageGroup.Id = game.Id;
|
||||
ageGroup.GameId = game.Id;
|
||||
ageGroup.AgeGroupId = null;
|
||||
|
||||
return ageGroup;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public class AgeGroup
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
public long? GameId { get; set; }
|
||||
public AgeRestrictionGroupings? AgeGroupId { get; set; }
|
||||
}
|
||||
|
||||
public static Dictionary<AgeRestrictionGroupings, List<AgeGroupItem>> AgeGroupings
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<AgeRestrictionGroupings, List<AgeGroupItem>>{
|
||||
{
|
||||
AgeRestrictionGroupings.Adult, new List<AgeGroupItem>{ Adult_Item, Mature_Item, Teen_Item, Child_Item }
|
||||
},
|
||||
{
|
||||
AgeRestrictionGroupings.Mature, new List<AgeGroupItem>{ Mature_Item, Teen_Item, Child_Item }
|
||||
},
|
||||
{
|
||||
AgeRestrictionGroupings.Teen, new List<AgeGroupItem>{ Teen_Item, Child_Item }
|
||||
},
|
||||
{
|
||||
AgeRestrictionGroupings.Child, new List<AgeGroupItem>{ Child_Item }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<AgeRestrictionGroupings, AgeGroupItem> AgeGroupingsFlat
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<AgeRestrictionGroupings, AgeGroupItem>{
|
||||
{
|
||||
AgeRestrictionGroupings.Adult, Adult_Item
|
||||
},
|
||||
{
|
||||
AgeRestrictionGroupings.Mature, Mature_Item
|
||||
},
|
||||
{
|
||||
AgeRestrictionGroupings.Teen, Teen_Item
|
||||
},
|
||||
{
|
||||
AgeRestrictionGroupings.Child, Child_Item
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum AgeRestrictionGroupings
|
||||
{
|
||||
Adult = 4,
|
||||
Mature = 3,
|
||||
Teen = 2,
|
||||
Child = 1,
|
||||
Unclassified = 0
|
||||
}
|
||||
|
||||
public static List<string> RatingsBoards
|
||||
{
|
||||
get
|
||||
{
|
||||
List<string> boards = new List<string>{
|
||||
"ACB", "CERO", "CLASS_IND", "ESRB", "GRAC", "PEGI", "USK"
|
||||
};
|
||||
|
||||
return boards;
|
||||
}
|
||||
}
|
||||
|
||||
readonly static AgeGroupItem Adult_Item = new AgeGroupItem{
|
||||
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_R18, AgeRatingTitle.ACB_RC },
|
||||
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_Z },
|
||||
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_Eighteen },
|
||||
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.RP, AgeRatingTitle.AO },
|
||||
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_Eighteen },
|
||||
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Eighteen},
|
||||
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_18}
|
||||
};
|
||||
|
||||
readonly static AgeGroupItem Mature_Item = new AgeGroupItem{
|
||||
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_M, AgeRatingTitle.ACB_MA15 },
|
||||
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_C, AgeRatingTitle.CERO_D },
|
||||
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_Sixteen },
|
||||
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.M },
|
||||
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_Fifteen },
|
||||
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Sixteen},
|
||||
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_16}
|
||||
};
|
||||
|
||||
readonly static AgeGroupItem Teen_Item = new AgeGroupItem{
|
||||
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_PG },
|
||||
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_B },
|
||||
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_Twelve, AgeRatingTitle.CLASS_IND_Fourteen },
|
||||
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.T },
|
||||
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_Twelve },
|
||||
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Twelve},
|
||||
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_12}
|
||||
};
|
||||
|
||||
readonly static AgeGroupItem Child_Item = new AgeGroupItem{
|
||||
ACB = new List<AgeRatingTitle>{ AgeRatingTitle.ACB_G },
|
||||
CERO = new List<AgeRatingTitle>{ AgeRatingTitle.CERO_A },
|
||||
CLASS_IND = new List<AgeRatingTitle>{ AgeRatingTitle.CLASS_IND_L, AgeRatingTitle.CLASS_IND_Ten },
|
||||
ESRB = new List<AgeRatingTitle>{ AgeRatingTitle.E, AgeRatingTitle.E10 },
|
||||
GRAC = new List<AgeRatingTitle>{ AgeRatingTitle.GRAC_All },
|
||||
PEGI = new List<AgeRatingTitle>{ AgeRatingTitle.Three, AgeRatingTitle.Seven},
|
||||
USK = new List<AgeRatingTitle>{ AgeRatingTitle.USK_0, AgeRatingTitle.USK_6}
|
||||
};
|
||||
|
||||
public class AgeGroupItem
|
||||
{
|
||||
public List<IGDB.Models.AgeRatingTitle> ACB { get; set; }
|
||||
public List<IGDB.Models.AgeRatingTitle> CERO { get; set; }
|
||||
public List<IGDB.Models.AgeRatingTitle> CLASS_IND { get; set; }
|
||||
public List<IGDB.Models.AgeRatingTitle> ESRB { get; set; }
|
||||
public List<IGDB.Models.AgeRatingTitle> GRAC { get; set; }
|
||||
public List<IGDB.Models.AgeRatingTitle> PEGI { get; set; }
|
||||
public List<IGDB.Models.AgeRatingTitle> USK { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
public List<long> AgeGroupItemValues
|
||||
{
|
||||
get
|
||||
{
|
||||
List<long> values = new List<long>();
|
||||
{
|
||||
foreach (AgeRatingTitle ageRatingTitle in ACB)
|
||||
{
|
||||
values.Add((long)ageRatingTitle);
|
||||
}
|
||||
foreach (AgeRatingTitle ageRatingTitle in CERO)
|
||||
{
|
||||
values.Add((long)ageRatingTitle);
|
||||
}
|
||||
foreach (AgeRatingTitle ageRatingTitle in CLASS_IND)
|
||||
{
|
||||
values.Add((long)ageRatingTitle);
|
||||
}
|
||||
foreach (AgeRatingTitle ageRatingTitle in ESRB)
|
||||
{
|
||||
values.Add((long)ageRatingTitle);
|
||||
}
|
||||
foreach (AgeRatingTitle ageRatingTitle in GRAC)
|
||||
{
|
||||
values.Add((long)ageRatingTitle);
|
||||
}
|
||||
foreach (AgeRatingTitle ageRatingTitle in PEGI)
|
||||
{
|
||||
values.Add((long)ageRatingTitle);
|
||||
}
|
||||
foreach (AgeRatingTitle ageRatingTitle in USK)
|
||||
{
|
||||
values.Add((long)ageRatingTitle);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using Microsoft.CodeAnalysis.Classification;
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -15,6 +16,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static AgeRating? GetAgeRatings(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -77,7 +84,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<AgeRating>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -111,8 +118,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<AgeRating> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get AgeRatings metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<AgeRating>(IGDBClient.Endpoints.AgeRating, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<AgeRating>(IGDBClient.Endpoints.AgeRating, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
@@ -148,44 +154,6 @@ namespace gaseous_server.Classes.Metadata
|
||||
public AgeRatingTitle RatingTitle { get; set; }
|
||||
public string[] Descriptions { get; set; }
|
||||
}
|
||||
|
||||
public static void PopulateAgeMap()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "DELETE FROM ClassificationMap;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
db.ExecuteNonQuery(sql);
|
||||
|
||||
// loop all age groups
|
||||
foreach(KeyValuePair<AgeGroups.AgeRestrictionGroupings, AgeGroups.AgeGroupItem> ageGrouping in AgeGroups.AgeGroupingsFlat)
|
||||
{
|
||||
AgeGroups.AgeGroupItem ageGroupItem = ageGrouping.Value;
|
||||
var properties = ageGroupItem.GetType().GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.GetGetMethod() != null)
|
||||
{
|
||||
List<string> AgeRatingCategories = new List<string>(Enum.GetNames(typeof(AgeRatingCategory)));
|
||||
if (AgeRatingCategories.Contains(prop.Name))
|
||||
{
|
||||
AgeRatingCategory ageRatingCategory = (AgeRatingCategory)Enum.Parse(typeof(AgeRatingCategory), prop.Name);
|
||||
List<AgeRatingTitle> ageRatingTitles = (List<AgeRatingTitle>)prop.GetValue(ageGroupItem);
|
||||
|
||||
foreach (AgeRatingTitle ageRatingTitle in ageRatingTitles)
|
||||
{
|
||||
dbDict.Clear();
|
||||
dbDict.Add("AgeGroupId", ageGrouping.Key);
|
||||
dbDict.Add("ClassificationBoardId", ageRatingCategory);
|
||||
dbDict.Add("RatingId", ageRatingTitle);
|
||||
|
||||
sql = "INSERT INTO ClassificationMap (AgeGroupId, ClassificationBoardId, RatingId) VALUES (@AgeGroupId, @ClassificationBoardId, @RatingId);";
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static AgeRatingContentDescription? GetAgeRatingContentDescriptions(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +82,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<AgeRatingContentDescription>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -97,8 +105,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<AgeRatingContentDescription> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get AgeRatingContentDescriptionContentDescriptions metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<AgeRatingContentDescription>(IGDBClient.Endpoints.AgeRatingContentDescriptions, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<AgeRatingContentDescription>(IGDBClient.Endpoints.AgeRatingContentDescriptions, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static AlternativeName? GetAlternativeNames(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +82,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<AlternativeName>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -97,8 +105,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<AlternativeName> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get AlternativeNames metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<AlternativeName>(IGDBClient.Endpoints.AlternativeNames, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<AlternativeName>(IGDBClient.Endpoints.AlternativeNames, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Artwork? GetArtwork(long? Id, string LogoPath)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -77,7 +85,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<Artwork>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -107,8 +115,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Artwork> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
{
|
||||
// get Artwork metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Artwork>(IGDBClient.Endpoints.Artworks, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Artwork>(IGDBClient.Endpoints.Artworks, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb, result.ImageId);
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Collection? GetCollections(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +82,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<Collection>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -97,8 +105,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Collection> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Collections metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Collection>(IGDBClient.Endpoints.Collections, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Collection>(IGDBClient.Endpoints.Collections, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,238 +0,0 @@
|
||||
using System.Net;
|
||||
using IGDB;
|
||||
using RestEase;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles all metadata API communications
|
||||
/// </summary>
|
||||
public class Communications
|
||||
{
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Configure metadata API communications
|
||||
/// </summary>
|
||||
public static MetadataSources MetadataSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return _MetadataSource;
|
||||
}
|
||||
set
|
||||
{
|
||||
_MetadataSource = value;
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case MetadataSources.IGDB:
|
||||
// set rate limiter avoidance values
|
||||
RateLimitAvoidanceWait = 1500;
|
||||
RateLimitAvoidanceThreshold = 3;
|
||||
RateLimitAvoidancePeriod = 1;
|
||||
|
||||
// set rate limiter recovery values
|
||||
RateLimitRecoveryWaitTime = 10000;
|
||||
|
||||
break;
|
||||
default:
|
||||
// leave all values at default
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static MetadataSources _MetadataSource = MetadataSources.None;
|
||||
|
||||
// rate limit avoidance - what can we do to ensure that rate limiting is avoided?
|
||||
// these values affect all communications
|
||||
|
||||
/// <summary>
|
||||
/// How long to wait to avoid hitting an API rate limiter
|
||||
/// </summary>
|
||||
private static int RateLimitAvoidanceWait = 2000;
|
||||
|
||||
/// <summary>
|
||||
/// How many API calls in the period are allowed before we start introducing a wait
|
||||
/// </summary>
|
||||
private static int RateLimitAvoidanceThreshold = 80;
|
||||
|
||||
/// <summary>
|
||||
/// A counter of API calls since the beginning of the period
|
||||
/// </summary>
|
||||
private static int RateLimitAvoidanceCallCount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// How large the period (in seconds) to measure API call counts against
|
||||
/// </summary>
|
||||
private static int RateLimitAvoidancePeriod = 60;
|
||||
|
||||
/// <summary>
|
||||
/// The start of the rate limit avoidance period
|
||||
/// </summary>
|
||||
private static DateTime RateLimitAvoidanceStartTime = DateTime.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// Used to determine if we're already in rate limit avoidance mode - always query "InRateLimitAvoidanceMode"
|
||||
/// for up to date mode status.
|
||||
/// This bool is used to track status changes and should not be relied upon for current status.
|
||||
/// </summary>
|
||||
private static bool InRateLimitAvoidanceModeStatus = false;
|
||||
|
||||
/// <summary>
|
||||
/// Determine if we're in rate limit avoidance mode.
|
||||
/// </summary>
|
||||
private static bool InRateLimitAvoidanceMode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RateLimitAvoidanceStartTime.AddSeconds(RateLimitAvoidancePeriod) <= DateTime.UtcNow)
|
||||
{
|
||||
// avoidance period has expired - reset
|
||||
RateLimitAvoidanceCallCount = 0;
|
||||
RateLimitAvoidanceStartTime = DateTime.UtcNow;
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're in the avoidance period
|
||||
if (RateLimitAvoidanceCallCount > RateLimitAvoidanceThreshold)
|
||||
{
|
||||
// the number of call counts indicates we should throttle things a bit
|
||||
if (InRateLimitAvoidanceModeStatus == false)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "API Connection", "Entered rate limit avoidance period, API calls will be throttled by " + RateLimitAvoidanceWait + " milliseconds.");
|
||||
InRateLimitAvoidanceModeStatus = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// still in full speed mode - no throttle required
|
||||
if (InRateLimitAvoidanceModeStatus == true)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "API Connection", "Exited rate limit avoidance period, API call rate is returned to full speed.");
|
||||
InRateLimitAvoidanceModeStatus = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rate limit handling - how long to wait to allow the server to recover and try again
|
||||
// these values affect ALL communications if a 429 response code is received
|
||||
|
||||
/// <summary>
|
||||
/// How long to wait (in milliseconds) if a 429 status code is received before trying again
|
||||
/// </summary>
|
||||
private static int RateLimitRecoveryWaitTime = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// The time when normal communications can attempt to be resumed
|
||||
/// </summary>
|
||||
private static DateTime RateLimitResumeTime = DateTime.UtcNow.AddMinutes(5 * -1);
|
||||
|
||||
// rate limit retry - how many times to retry before aborting
|
||||
private int RetryAttempts = 0;
|
||||
private int RetryAttemptsMax = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Supported metadata sources
|
||||
/// </summary>
|
||||
public enum MetadataSources
|
||||
{
|
||||
/// <summary>
|
||||
/// None - always returns null for metadata requests - should not really be using this source
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// IGDB - queries the IGDB service for metadata
|
||||
/// </summary>
|
||||
IGDB
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request data from the metadata API
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of object to return</typeparam>
|
||||
/// <param name="Endpoint">API endpoint segment to use</param>
|
||||
/// <param name="Fields">Fields to request from the API</param>
|
||||
/// <param name="Query">Selection criteria for data to request</param>
|
||||
/// <returns></returns>
|
||||
public async Task<T[]?> APIComm<T>(string Endpoint, string Fields, string Query)
|
||||
{
|
||||
switch (_MetadataSource)
|
||||
{
|
||||
case MetadataSources.None:
|
||||
return null;
|
||||
case MetadataSources.IGDB:
|
||||
return await IGDBAPI<T>(Endpoint, Fields, Query);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<T[]> IGDBAPI<T>(string Endpoint, string Fields, string Query)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Debug, "API Connection", "Accessing API for endpoint: " + Endpoint);
|
||||
|
||||
if (RateLimitResumeTime > DateTime.UtcNow)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "API Connection", "IGDB rate limit hit. Pausing API communications until " + RateLimitResumeTime.ToString() + ". Attempt " + RetryAttempts + " of " + RetryAttemptsMax + " retries.");
|
||||
Thread.Sleep(RateLimitRecoveryWaitTime);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (InRateLimitAvoidanceMode == true)
|
||||
{
|
||||
// sleep for a moment to help avoid hitting the rate limiter
|
||||
Thread.Sleep(RateLimitAvoidanceWait);
|
||||
}
|
||||
|
||||
// perform the actual API call
|
||||
var results = await igdb.QueryAsync<T>(Endpoint, query: Fields + " " + Query + ";");
|
||||
|
||||
// increment rate limiter avoidance call count
|
||||
RateLimitAvoidanceCallCount += 1;
|
||||
|
||||
return results;
|
||||
}
|
||||
catch (ApiException apiEx)
|
||||
{
|
||||
switch (apiEx.StatusCode)
|
||||
{
|
||||
case HttpStatusCode.TooManyRequests:
|
||||
if (RetryAttempts >= RetryAttemptsMax)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "API Connection", "IGDB rate limiter attempts expired. Aborting.", apiEx);
|
||||
throw;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "API Connection", "IGDB API rate limit hit while accessing endpoint " + Endpoint, apiEx);
|
||||
|
||||
RetryAttempts += 1;
|
||||
|
||||
return await IGDBAPI<T>(Endpoint, Fields, Query);
|
||||
}
|
||||
default:
|
||||
Logging.Log(Logging.LogType.Warning, "API Connection", "Exception when accessing endpoint " + Endpoint, apiEx);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "API Connection", "Exception when accessing endpoint " + Endpoint, ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
@@ -12,6 +13,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Company? GetCompanies(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +81,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<Company>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -105,8 +112,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Company> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Companies metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Company>(IGDBClient.Endpoints.Companies, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Company>(IGDBClient.Endpoints.Companies, query: fieldList + " " + WhereClause + ";");
|
||||
if (results.Length > 0)
|
||||
{
|
||||
var result = results.First();
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static CompanyLogo? GetCompanyLogo(long? Id, string LogoPath)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -80,7 +88,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<CompanyLogo>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -112,8 +120,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<CompanyLogo?> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
{
|
||||
// get CompanyLogo metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<CompanyLogo>(IGDBClient.Endpoints.CompanyLogos, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<CompanyLogo>(IGDBClient.Endpoints.CompanyLogos, query: fieldList + " " + WhereClause + ";");
|
||||
if (results.Length > 0)
|
||||
{
|
||||
var result = results.First();
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Cover? GetCover(long? Id, string LogoPath)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -77,7 +85,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<Cover>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -107,8 +115,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Cover> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
{
|
||||
// get Cover metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Cover>(IGDBClient.Endpoints.Covers, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Cover>(IGDBClient.Endpoints.Covers, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb, result.ImageId);
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static ExternalGame? GetExternalGames(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -77,7 +85,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<ExternalGame>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -100,8 +108,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<ExternalGame?> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get ExternalGames metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<ExternalGame>(IGDBClient.Endpoints.ExternalGames, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<ExternalGame>(IGDBClient.Endpoints.ExternalGames, query: fieldList + " " + WhereClause + ";");
|
||||
if (results.Length > 0)
|
||||
{
|
||||
var result = results.First();
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Franchise? GetFranchises(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +82,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<Franchise>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -97,8 +105,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Franchise> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get FranchiseContentDescriptions metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Franchise>(IGDBClient.Endpoints.Franchies, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Franchise>(IGDBClient.Endpoints.Franchies, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static GameMode? GetGame_Modes(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +82,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<GameMode>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -97,8 +105,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<GameMode> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game_Modes metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<GameMode>(IGDBClient.Endpoints.GameModes, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<GameMode>(IGDBClient.Endpoints.GameModes, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static GameVideo? GetGame_Videos(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +82,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<GameVideo>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -97,8 +105,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<GameVideo> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game_Videos metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<GameVideo>(IGDBClient.Endpoints.GameVideos, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<GameVideo>(IGDBClient.Endpoints.GameVideos, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
@@ -14,11 +15,11 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
}
|
||||
|
||||
public class InvalidGameId : Exception
|
||||
{
|
||||
public InvalidGameId(long Id) : base("Unable to find Game by id " + Id)
|
||||
{}
|
||||
}
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Game? GetGame(long Id, bool getAllMetadata, bool followSubGames, bool forceRefresh)
|
||||
{
|
||||
@@ -105,18 +106,15 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
UpdateSubClasses(returnValue, getAllMetadata, followSubGames);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
return returnValue;
|
||||
case Storage.CacheStatus.Current:
|
||||
returnValue = Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);
|
||||
UpdateSubClasses(returnValue, false, false);
|
||||
return returnValue;
|
||||
return Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);
|
||||
default:
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
@@ -124,59 +122,13 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
private static void UpdateSubClasses(Game Game, bool getAllMetadata, bool followSubGames)
|
||||
{
|
||||
// required metadata
|
||||
if (Game.Cover != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Cover GameCover = Covers.GetCover(Game.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Game Metadata", "Unable to fetch cover artwork.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Genres != null)
|
||||
if (getAllMetadata == true)
|
||||
{
|
||||
foreach (long GenreId in Game.Genres.Ids)
|
||||
{
|
||||
Genre GameGenre = Genres.GetGenres(GenreId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.GameModes != null)
|
||||
{
|
||||
foreach (long gameModeId in Game.GameModes.Ids)
|
||||
{
|
||||
GameMode gameMode = GameModes.GetGame_Modes(gameModeId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.MultiplayerModes != null)
|
||||
{
|
||||
foreach (long multiplayerModeId in Game.MultiplayerModes.Ids)
|
||||
{
|
||||
MultiplayerMode multiplayerMode = MultiplayerModes.GetGame_MultiplayerModes(multiplayerModeId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.PlayerPerspectives != null)
|
||||
{
|
||||
foreach (long PerspectiveId in Game.PlayerPerspectives.Ids)
|
||||
{
|
||||
PlayerPerspective GamePlayPerspective = PlayerPerspectives.GetGame_PlayerPerspectives(PerspectiveId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Themes != null)
|
||||
{
|
||||
foreach (long ThemeId in Game.Themes.Ids)
|
||||
{
|
||||
Theme GameTheme = Themes.GetGame_Themes(ThemeId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.AgeRatings != null)
|
||||
{
|
||||
foreach (long AgeRatingId in Game.AgeRatings.Ids)
|
||||
@@ -184,19 +136,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
AgeRating GameAgeRating = AgeRatings.GetAgeRatings(AgeRatingId);
|
||||
}
|
||||
}
|
||||
AgeGroups.GetAgeGroup(Game);
|
||||
|
||||
if (Game.ReleaseDates != null)
|
||||
{
|
||||
foreach (long ReleaseDateId in Game.ReleaseDates.Ids)
|
||||
{
|
||||
ReleaseDate GameReleaseDate = ReleaseDates.GetReleaseDates(ReleaseDateId);
|
||||
}
|
||||
}
|
||||
|
||||
// optional metadata - usually downloaded as needed
|
||||
if (getAllMetadata == true)
|
||||
{
|
||||
if (Game.AlternativeNames != null)
|
||||
{
|
||||
foreach (long AlternativeNameId in Game.AlternativeNames.Ids)
|
||||
@@ -208,16 +148,9 @@ namespace gaseous_server.Classes.Metadata
|
||||
if (Game.Artworks != null)
|
||||
{
|
||||
foreach (long ArtworkId in Game.Artworks.Ids)
|
||||
{
|
||||
try
|
||||
{
|
||||
Artwork GameArtwork = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Game Metadata", "Unable to fetch artwork id: " + ArtworkId, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (followSubGames)
|
||||
@@ -263,6 +196,14 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Genres != null)
|
||||
{
|
||||
foreach (long GenreId in Game.Genres.Ids)
|
||||
{
|
||||
Genre GameGenre = Genres.GetGenres(GenreId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.InvolvedCompanies != null)
|
||||
{
|
||||
foreach (long involvedCompanyId in Game.InvolvedCompanies.Ids)
|
||||
@@ -271,6 +212,22 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.GameModes != null)
|
||||
{
|
||||
foreach (long gameModeId in Game.GameModes.Ids)
|
||||
{
|
||||
GameMode gameMode = GameModes.GetGame_Modes(gameModeId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.MultiplayerModes != null)
|
||||
{
|
||||
foreach (long multiplayerModeId in Game.MultiplayerModes.Ids)
|
||||
{
|
||||
MultiplayerMode multiplayerMode = MultiplayerModes.GetGame_MultiplayerModes(multiplayerModeId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Platforms != null)
|
||||
{
|
||||
foreach (long PlatformId in Game.Platforms.Ids)
|
||||
@@ -279,18 +236,27 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.PlayerPerspectives != null)
|
||||
{
|
||||
foreach (long PerspectiveId in Game.PlayerPerspectives.Ids)
|
||||
{
|
||||
PlayerPerspective GamePlayPerspective = PlayerPerspectives.GetGame_PlayerPerspectives(PerspectiveId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Screenshots != null)
|
||||
{
|
||||
foreach (long ScreenshotId in Game.Screenshots.Ids)
|
||||
{
|
||||
try
|
||||
{
|
||||
Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Game Metadata", "Unable to fetch screenshot id: " + ScreenshotId, ex);
|
||||
}
|
||||
|
||||
if (Game.Themes != null)
|
||||
{
|
||||
foreach (long ThemeId in Game.Themes.Ids)
|
||||
{
|
||||
Theme GameTheme = Themes.GetGame_Themes(ThemeId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,178 +279,42 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Game> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Game>(IGDBClient.Endpoints.Games, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
// add artificial unknown platform mapping
|
||||
List<long> platformIds = new List<long>();
|
||||
platformIds.Add(0);
|
||||
if (result.Platforms != null)
|
||||
{
|
||||
if (result.Platforms.Ids != null)
|
||||
{
|
||||
platformIds.AddRange(result.Platforms.Ids.ToList());
|
||||
}
|
||||
}
|
||||
result.Platforms = new IdentitiesOrValues<Platform>(
|
||||
ids: platformIds.ToArray<long>()
|
||||
);
|
||||
|
||||
// get cover art from parent if this has no cover
|
||||
if (result.Cover == null)
|
||||
{
|
||||
if (result.ParentGame != null)
|
||||
{
|
||||
if (result.ParentGame.Id != null)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Game Metadata", "Game has no cover art, fetching cover art from parent game");
|
||||
Game parentGame = GetGame((long)result.ParentGame.Id, false, false, false);
|
||||
result.Cover = parentGame.Cover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get missing metadata from parent if this is a port
|
||||
if (result.Category == Category.Port)
|
||||
{
|
||||
if (result.Summary == null)
|
||||
{
|
||||
if (result.ParentGame != null)
|
||||
{
|
||||
if (result.ParentGame.Id != null)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Game Metadata", "Game has no summary, fetching summary from parent game");
|
||||
Game parentGame = GetGame((long)result.ParentGame.Id, false, false, false);
|
||||
result.Summary = parentGame.Summary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void AssignAllGamesToPlatformIdZero()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM Game;";
|
||||
DataTable gamesTable = db.ExecuteCMD(sql);
|
||||
foreach (DataRow gameRow in gamesTable.Rows)
|
||||
{
|
||||
sql = "DELETE FROM Relation_Game_Platforms WHERE PlatformsId = 0 AND GameId = @Id; INSERT INTO Relation_Game_Platforms (GameId, PlatformsId) VALUES (@Id, 0);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("Id", (long)gameRow["Id"]);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool AllowNoPlatformSearch = false;
|
||||
|
||||
public static Game[] SearchForGame(string SearchString, long PlatformId, SearchType searchType)
|
||||
{
|
||||
// search local first
|
||||
Logging.Log(Logging.LogType.Information, "Game Search", "Attempting local search of type '" + searchType.ToString() + "' for " + SearchString);
|
||||
Task<Game[]> games = _SearchForGameDatabase(SearchString, PlatformId, searchType);
|
||||
if (games.Result.Length == 0)
|
||||
{
|
||||
// fall back to online search
|
||||
Logging.Log(Logging.LogType.Information, "Game Search", "Falling back to remote search of type '" + searchType.ToString() + "' for " + SearchString);
|
||||
games = _SearchForGameRemote(SearchString, PlatformId, searchType);
|
||||
}
|
||||
Task<Game[]> games = _SearchForGame(SearchString, PlatformId, searchType);
|
||||
return games.Result;
|
||||
}
|
||||
|
||||
private static async Task<Game[]> _SearchForGameDatabase(string SearchString, long PlatformId, SearchType searchType)
|
||||
{
|
||||
string whereClause = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
|
||||
bool allowSearch = true;
|
||||
switch (searchType)
|
||||
{
|
||||
case SearchType.searchNoPlatform:
|
||||
whereClause = "MATCH(`Name`) AGAINST (@gamename)";
|
||||
dbDict.Add("platformid", PlatformId);
|
||||
dbDict.Add("gamename", SearchString);
|
||||
|
||||
allowSearch = AllowNoPlatformSearch;
|
||||
break;
|
||||
case SearchType.search:
|
||||
whereClause = "PlatformsId = @platformid AND MATCH(`Name`) AGAINST (@gamename)";
|
||||
dbDict.Add("platformid", PlatformId);
|
||||
dbDict.Add("gamename", SearchString);
|
||||
break;
|
||||
case SearchType.wherefuzzy:
|
||||
whereClause = "PlatformsId = @platformid AND `Name` LIKE @gamename";
|
||||
dbDict.Add("platformid", PlatformId);
|
||||
dbDict.Add("gamename", "%" + SearchString + "%");
|
||||
break;
|
||||
case SearchType.where:
|
||||
whereClause = "PlatformsId = @platformid AND `Name` = @gamename";
|
||||
dbDict.Add("platformid", PlatformId);
|
||||
dbDict.Add("gamename", SearchString);
|
||||
break;
|
||||
}
|
||||
|
||||
string sql = "SELECT Game.Id, Game.`Name`, Game.Slug, Relation_Game_Platforms.PlatformsId AS PlatformsId, Game.Summary FROM gaseous.Game JOIN Relation_Game_Platforms ON Game.Id = Relation_Game_Platforms.GameId WHERE " + whereClause + ";";
|
||||
|
||||
|
||||
// get Game metadata
|
||||
Game[]? results = new Game[0];
|
||||
if (allowSearch == true)
|
||||
{
|
||||
List<Game> searchResults = new List<Game>();
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
Game game = new Game{
|
||||
Id = (long)row["Id"],
|
||||
Name = (string)row["Name"],
|
||||
Slug = (string)row["Slug"],
|
||||
Summary = (string)row["Summary"]
|
||||
};
|
||||
searchResults.Add(game);
|
||||
}
|
||||
|
||||
results = searchResults.ToArray();
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static async Task<Game[]> _SearchForGameRemote(string SearchString, long PlatformId, SearchType searchType)
|
||||
private static async Task<Game[]> _SearchForGame(string SearchString, long PlatformId, SearchType searchType)
|
||||
{
|
||||
string searchBody = "";
|
||||
string searchFields = "fields id,name,slug,platforms,summary; ";
|
||||
bool allowSearch = true;
|
||||
searchBody += "fields id,name,slug,platforms,summary; ";
|
||||
switch (searchType)
|
||||
{
|
||||
case SearchType.searchNoPlatform:
|
||||
searchBody = "search \"" + SearchString + "\"; ";
|
||||
|
||||
allowSearch = AllowNoPlatformSearch;
|
||||
searchBody += "search \"" + SearchString + "\"; ";
|
||||
break;
|
||||
case SearchType.search:
|
||||
searchBody = "search \"" + SearchString + "\"; where platforms = (" + PlatformId + ");";
|
||||
searchBody += "search \"" + SearchString + "\"; ";
|
||||
searchBody += "where platforms = (" + PlatformId + ");";
|
||||
break;
|
||||
case SearchType.wherefuzzy:
|
||||
searchBody = "where platforms = (" + PlatformId + ") & name ~ *\"" + SearchString + "\"*;";
|
||||
searchBody += "where platforms = (" + PlatformId + ") & name ~ *\"" + SearchString + "\"*;";
|
||||
break;
|
||||
case SearchType.where:
|
||||
searchBody = "where platforms = (" + PlatformId + ") & name ~ \"" + SearchString + "\";";
|
||||
searchBody += "where platforms = (" + PlatformId + ") & name ~ \"" + SearchString + "\";";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// get Game metadata
|
||||
Communications comms = new Communications();
|
||||
Game[]? results = new Game[0];
|
||||
if (allowSearch == true)
|
||||
{
|
||||
results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody);
|
||||
}
|
||||
var results = await igdb.QueryAsync<Game>(IGDBClient.Endpoints.Games, query: searchBody);
|
||||
|
||||
return results;
|
||||
}
|
||||
@@ -496,42 +326,5 @@ namespace gaseous_server.Classes.Metadata
|
||||
search = 2,
|
||||
searchNoPlatform = 3
|
||||
}
|
||||
|
||||
public class MinimalGameItem
|
||||
{
|
||||
public MinimalGameItem(Game gameObject)
|
||||
{
|
||||
this.Id = gameObject.Id;
|
||||
this.Name = gameObject.Name;
|
||||
this.TotalRating = gameObject.TotalRating;
|
||||
this.TotalRatingCount = gameObject.TotalRatingCount;
|
||||
this.Cover = gameObject.Cover;
|
||||
this.Artworks = gameObject.Artworks;
|
||||
this.FirstReleaseDate = gameObject.FirstReleaseDate;
|
||||
|
||||
// compile age ratings
|
||||
this.AgeRatings = new List<AgeRating>();
|
||||
if (gameObject.AgeRatings != null)
|
||||
{
|
||||
foreach (long ageRatingId in gameObject.AgeRatings.Ids)
|
||||
{
|
||||
AgeRating? rating = Classes.Metadata.AgeRatings.GetAgeRatings(ageRatingId);
|
||||
if (rating != null)
|
||||
{
|
||||
this.AgeRatings.Add(rating);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long? Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public double? TotalRating { get; set; }
|
||||
public int? TotalRatingCount { get; set; }
|
||||
public DateTimeOffset? FirstReleaseDate { get; set; }
|
||||
public IGDB.IdentityOrValue<IGDB.Models.Cover> Cover { get; set; }
|
||||
public IGDB.IdentitiesOrValues<IGDB.Models.Artwork> Artworks { get; set; }
|
||||
public List<IGDB.Models.AgeRating> AgeRatings { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Genre? GetGenres(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +82,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<Genre>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -97,8 +105,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Genre> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Genres metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Genre>(IGDBClient.Endpoints.Genres, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Genre>(IGDBClient.Endpoints.Genres, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
@@ -12,6 +13,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static InvolvedCompany? GetInvolvedCompanies(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +81,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<InvolvedCompany>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -107,8 +114,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
// get InvolvedCompanies metadata
|
||||
try
|
||||
{
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<InvolvedCompany>(IGDBClient.Endpoints.InvolvedCompanies, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<InvolvedCompany>(IGDBClient.Endpoints.InvolvedCompanies, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static MultiplayerMode? GetGame_MultiplayerModes(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -74,7 +82,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<MultiplayerMode>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -97,8 +105,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<MultiplayerMode> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game_MultiplayerModes metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<MultiplayerMode>(IGDBClient.Endpoints.MultiplayerModes, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<MultiplayerMode>(IGDBClient.Endpoints.MultiplayerModes, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static PlatformLogo? GetPlatformLogo(long? Id, string LogoPath)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -80,7 +88,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<PlatformLogo>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -112,8 +120,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<PlatformLogo?> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
{
|
||||
// get PlatformLogo metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<PlatformLogo>(IGDBClient.Endpoints.PlatformLogos, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<PlatformLogo>(IGDBClient.Endpoints.PlatformLogos, query: fieldList + " " + WhereClause + ";");
|
||||
if (results.Length > 0)
|
||||
{
|
||||
var result = results.First();
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
@@ -13,6 +14,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static PlatformVersion? GetPlatformVersion(long Id, Platform ParentPlatform)
|
||||
{
|
||||
if (Id == 0)
|
||||
@@ -79,7 +86,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<PlatformVersion>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
return returnValue;
|
||||
@@ -107,8 +114,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<PlatformVersion?> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get PlatformVersion metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<PlatformVersion>(IGDBClient.Endpoints.PlatformVersions, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<PlatformVersion>(IGDBClient.Endpoints.PlatformVersions, query: fieldList + " " + WhereClause + ";");
|
||||
if (results.Length > 0)
|
||||
{
|
||||
var result = results.First();
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Net;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
@@ -15,6 +16,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Platform? GetPlatform(long Id, bool forceRefresh = false)
|
||||
{
|
||||
if (Id == 0)
|
||||
@@ -162,26 +169,11 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Platform> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get platform metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Platform>(IGDBClient.Endpoints.Platforms, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Platform>(IGDBClient.Endpoints.Platforms, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void AssignAllPlatformsToGameIdZero()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM Platform;";
|
||||
DataTable platformsTable = db.ExecuteCMD(sql);
|
||||
foreach (DataRow platformRow in platformsTable.Rows)
|
||||
{
|
||||
sql = "DELETE FROM Relation_Game_Platforms WHERE GameId = 0 AND PlatformsId = @Id; INSERT INTO Relation_Game_Platforms (GameId, PlatformsId) VALUES (0, @Id);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("Id", (long)platformRow["Id"]);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static PlayerPerspective? GetGame_PlayerPerspectives(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -76,7 +84,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<PlayerPerspective>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -99,8 +107,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<PlayerPerspective> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game_PlayerPerspectives metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<PlayerPerspective>(IGDBClient.Endpoints.PlayerPerspectives, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<PlayerPerspective>(IGDBClient.Endpoints.PlayerPerspectives, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,108 +0,0 @@
|
||||
using System;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
public class ReleaseDates
|
||||
{
|
||||
const string fieldList = "fields category,checksum,created_at,date,game,human,m,platform,region,status,updated_at,y;";
|
||||
|
||||
public ReleaseDates()
|
||||
{
|
||||
}
|
||||
|
||||
public static ReleaseDate? GetReleaseDates(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<ReleaseDate> RetVal = _GetReleaseDates(SearchUsing.id, Id);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static ReleaseDate GetReleaseDates(string Slug)
|
||||
{
|
||||
Task<ReleaseDate> RetVal = _GetReleaseDates(SearchUsing.slug, Slug);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<ReleaseDate> _GetReleaseDates(SearchUsing searchUsing, object searchValue)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
if (searchUsing == SearchUsing.id)
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("ReleaseDate", (long)searchValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("ReleaseDate", (string)searchValue);
|
||||
}
|
||||
|
||||
// set up where clause
|
||||
string WhereClause = "";
|
||||
switch (searchUsing)
|
||||
{
|
||||
case SearchUsing.id:
|
||||
WhereClause = "where id = " + searchValue;
|
||||
break;
|
||||
case SearchUsing.slug:
|
||||
WhereClause = "where slug = " + searchValue;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid search type");
|
||||
}
|
||||
|
||||
ReleaseDate returnValue = new ReleaseDate();
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
break;
|
||||
case Storage.CacheStatus.Expired:
|
||||
try
|
||||
{
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<ReleaseDate>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
case Storage.CacheStatus.Current:
|
||||
returnValue = Storage.GetCacheValue<ReleaseDate>(returnValue, "id", (long)searchValue);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private enum SearchUsing
|
||||
{
|
||||
id,
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<ReleaseDate> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get ReleaseDates metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<ReleaseDate>(IGDBClient.Endpoints.ReleaseDates, fieldList, WhereClause);
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Screenshot? GetScreenshot(long? Id, string LogoPath)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -78,7 +86,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
returnValue = Storage.GetCacheValue<Screenshot>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
break;
|
||||
@@ -108,8 +116,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Screenshot> GetObjectFromServer(string WhereClause, string LogoPath)
|
||||
{
|
||||
// get Screenshot metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Screenshot>(IGDBClient.Endpoints.Screenshots, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Screenshot>(IGDBClient.Endpoints.Screenshots, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
//GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb, result.ImageId);
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
@@ -16,15 +17,33 @@ namespace gaseous_server.Classes.Metadata
|
||||
Expired
|
||||
}
|
||||
|
||||
private static Dictionary<string, MemoryCacheObject> ObjectCache = new Dictionary<string, MemoryCacheObject>();
|
||||
|
||||
public static CacheStatus GetCacheStatus(string Endpoint, string Slug)
|
||||
{
|
||||
CacheClean();
|
||||
if (ObjectCache.ContainsKey(Endpoint + Slug))
|
||||
{
|
||||
return CacheStatus.Current;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _GetCacheStatus(Endpoint, "slug", Slug);
|
||||
}
|
||||
}
|
||||
|
||||
public static CacheStatus GetCacheStatus(string Endpoint, long Id)
|
||||
{
|
||||
CacheClean();
|
||||
if (ObjectCache.ContainsKey(Endpoint + Id))
|
||||
{
|
||||
return CacheStatus.Current;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _GetCacheStatus(Endpoint, "id", Id);
|
||||
}
|
||||
}
|
||||
|
||||
public static CacheStatus GetCacheStatus(DataRow Row)
|
||||
{
|
||||
@@ -48,7 +67,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
|
||||
private static CacheStatus _GetCacheStatus(string Endpoint, string SearchField, object SearchValue)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
string sql = "SELECT lastUpdated FROM " + Endpoint + " WHERE " + SearchField + " = @" + SearchField;
|
||||
|
||||
@@ -134,9 +153,6 @@ namespace gaseous_server.Classes.Metadata
|
||||
newDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(newObjectValue);
|
||||
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(newDict["Ids"]);
|
||||
objectDict[key.Key] = newObjectValue;
|
||||
|
||||
StoreRelations(ObjectTypeName, key.Key, (long)objectDict["Id"], newObjectValue);
|
||||
|
||||
break;
|
||||
case "int32[]":
|
||||
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(objectValue);
|
||||
@@ -159,7 +175,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
|
||||
// execute sql
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
db.ExecuteCMD(sql, objectDict);
|
||||
}
|
||||
|
||||
@@ -167,7 +183,22 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
string Endpoint = EndpointType.GetType().Name;
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
if (ObjectCache.ContainsKey(Endpoint + SearchValue))
|
||||
{
|
||||
MemoryCacheObject cacheObject = ObjectCache[Endpoint + SearchValue];
|
||||
if (cacheObject.ExpiryTime < DateTime.UtcNow)
|
||||
{
|
||||
// object has expired, remove it
|
||||
ObjectCache.Remove(Endpoint + SearchValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// object is valid, return it
|
||||
return (T)cacheObject.Object;
|
||||
}
|
||||
}
|
||||
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
string sql = "SELECT * FROM " + Endpoint + " WHERE " + SearchField + " = @" + SearchField;
|
||||
|
||||
@@ -185,7 +216,9 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
DataRow dataRow = dt.Rows[0];
|
||||
object returnObject = BuildCacheObject<T>(EndpointType, dataRow);
|
||||
|
||||
ObjectCache.Add(Endpoint + SearchValue, new MemoryCacheObject{
|
||||
Object = returnObject
|
||||
});
|
||||
return (T)returnObject;
|
||||
}
|
||||
}
|
||||
@@ -369,15 +402,6 @@ namespace gaseous_server.Classes.Metadata
|
||||
case "[igdb.models.startdatecategory":
|
||||
property.SetValue(EndpointType, (StartDateCategory)dataRow[property.Name]);
|
||||
break;
|
||||
case "[igdb.models.releasedateregion":
|
||||
property.SetValue(EndpointType, (ReleaseDateRegion)dataRow[property.Name]);
|
||||
break;
|
||||
case "[igdb.models.releasedatecategory":
|
||||
property.SetValue(EndpointType, (ReleaseDateCategory)dataRow[property.Name]);
|
||||
break;
|
||||
case "[gaseous_server.classes.metadata.agegroups+agerestrictiongroupings":
|
||||
property.SetValue(EndpointType, (AgeGroups.AgeRestrictionGroupings)dataRow[property.Name]);
|
||||
break;
|
||||
default:
|
||||
property.SetValue(EndpointType, dataRow[property.Name]);
|
||||
break;
|
||||
@@ -395,36 +419,19 @@ namespace gaseous_server.Classes.Metadata
|
||||
return EndpointType;
|
||||
}
|
||||
|
||||
private static void StoreRelations(string PrimaryTable, string SecondaryTable, long ObjectId, string Relations)
|
||||
private static void CacheClean()
|
||||
{
|
||||
string TableName = "Relation_" + PrimaryTable + "_" + SecondaryTable;
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM information_schema.tables WHERE table_schema = '" + Config.DatabaseConfiguration.DatabaseName + "' AND table_name = '" + TableName + "';";
|
||||
DataTable data = db.ExecuteCMD(sql);
|
||||
if (data.Rows.Count == 0)
|
||||
if (ObjectCache == null)
|
||||
{
|
||||
// table doesn't exist, create it
|
||||
sql = "CREATE TABLE `" + Config.DatabaseConfiguration.DatabaseName + "`.`" + TableName + "` (`" + PrimaryTable + "Id` BIGINT NOT NULL, `" + SecondaryTable + "Id` BIGINT NOT NULL, PRIMARY KEY (`" + PrimaryTable + "Id`, `" + SecondaryTable + "Id`), INDEX `idx_PrimaryColumn` (`" + PrimaryTable + "Id` ASC) VISIBLE);";
|
||||
db.ExecuteCMD(sql);
|
||||
ObjectCache = new Dictionary<string, MemoryCacheObject>();
|
||||
}
|
||||
else
|
||||
Dictionary<string, MemoryCacheObject> workCache = ObjectCache;
|
||||
foreach (KeyValuePair<string, MemoryCacheObject> objectCache in workCache)
|
||||
{
|
||||
// clean existing records for this object
|
||||
sql = "DELETE FROM " + TableName + " WHERE `" + PrimaryTable + "Id` = @objectid";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("objectid", ObjectId);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
if (objectCache.Value.ExpiryTime < DateTime.UtcNow)
|
||||
{
|
||||
ObjectCache.Remove(objectCache.Key);
|
||||
}
|
||||
|
||||
// insert data
|
||||
long[] RelationValues = Newtonsoft.Json.JsonConvert.DeserializeObject<long[]>(Relations);
|
||||
foreach (long RelationValue in RelationValues)
|
||||
{
|
||||
sql = "INSERT INTO " + TableName + " (`" + PrimaryTable + "Id`, `" + SecondaryTable + "Id`) VALUES (@objectid, @relationvalue);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("objectid", ObjectId);
|
||||
dbDict.Add("relationvalue", RelationValue);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
@@ -13,6 +15,12 @@ namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Theme? GetGame_Themes(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
@@ -77,7 +85,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
gaseous_tools.Logging.Log(gaseous_tools.Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||
return Storage.GetCacheValue<Theme>(returnValue, "id", (long)searchValue);
|
||||
}
|
||||
case Storage.CacheStatus.Current:
|
||||
@@ -99,8 +107,7 @@ namespace gaseous_server.Classes.Metadata
|
||||
private static async Task<Theme> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game_Themes metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Theme>(IGDBClient.Endpoints.Themes, fieldList, WhereClause);
|
||||
var results = await igdb.QueryAsync<Theme>(IGDBClient.Endpoints.Themes, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
|
@@ -1,74 +1,51 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using gaseous_server.Models;
|
||||
using gaseous_tools;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class MetadataManagement : QueueItemStatus
|
||||
public class MetadataManagement
|
||||
{
|
||||
public void RefreshMetadata(bool forceRefresh = false)
|
||||
public static void RefreshMetadata(bool forceRefresh = false)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
DataTable dt = new DataTable();
|
||||
|
||||
// disabling forceRefresh
|
||||
forceRefresh = false;
|
||||
|
||||
// update platforms
|
||||
sql = "SELECT Id, `Name` FROM Platform;";
|
||||
dt = db.ExecuteCMD(sql);
|
||||
|
||||
int StatusCounter = 1;
|
||||
foreach (DataRow dr in dt.Rows)
|
||||
{
|
||||
SetStatus(StatusCounter, dt.Rows.Count, "Refreshing metadata for platform " + dr["name"]);
|
||||
|
||||
try
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Metadata Refresh", "(" + StatusCounter + "/" + dt.Rows.Count + "): Refreshing metadata for platform " + dr["name"] + " (" + dr["id"] + ")");
|
||||
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);
|
||||
}
|
||||
|
||||
StatusCounter += 1;
|
||||
}
|
||||
ClearStatus();
|
||||
|
||||
// update games
|
||||
if (forceRefresh == true)
|
||||
{
|
||||
// when forced, only update games with ROMs for
|
||||
sql = "SELECT Id, `Name` FROM view_GamesWithRoms;";
|
||||
}
|
||||
else
|
||||
{
|
||||
// when run normally, update all games (since this will honour cache timeouts)
|
||||
sql = "SELECT Id, `Name` FROM Game;";
|
||||
}
|
||||
dt = db.ExecuteCMD(sql);
|
||||
|
||||
StatusCounter = 1;
|
||||
foreach (DataRow dr in dt.Rows)
|
||||
{
|
||||
SetStatus(StatusCounter, dt.Rows.Count, "Refreshing metadata for game " + dr["name"]);
|
||||
|
||||
try
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Metadata Refresh", "(" + StatusCounter + "/" + dt.Rows.Count + "): Refreshing metadata for game " + dr["name"] + " (" + dr["id"] + ")");
|
||||
Metadata.Games.GetGame((long)dr["id"], true, false, forceRefresh);
|
||||
Logging.Log(Logging.LogType.Information, "Metadata Refresh", "Refreshing metadata for game " + dr["name"] + " (" + dr["id"] + ")");
|
||||
Metadata.Games.GetGame((long)dr["id"], true, true, forceRefresh);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Metadata Refresh", "An error occurred while refreshing metadata for " + dr["name"], ex);
|
||||
}
|
||||
|
||||
StatusCounter += 1;
|
||||
}
|
||||
ClearStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,41 +0,0 @@
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class QueueItemStatus
|
||||
{
|
||||
internal ProcessQueue.QueueItem? CallingQueueItem = null;
|
||||
|
||||
private int _CurrentItemNumber = 0;
|
||||
private int _MaxItemsNumber = 0;
|
||||
private string _StatusText = "";
|
||||
|
||||
public int CurrentItemNumber => _CurrentItemNumber;
|
||||
public int MaxItemsNumber => _MaxItemsNumber;
|
||||
public string StatusText => _StatusText;
|
||||
|
||||
public void SetStatus(int CurrentItemNumber, int MaxItemsNumber, string StatusText)
|
||||
{
|
||||
this._CurrentItemNumber = CurrentItemNumber;
|
||||
this._MaxItemsNumber = MaxItemsNumber;
|
||||
this._StatusText = StatusText;
|
||||
|
||||
if (CallingQueueItem != null)
|
||||
{
|
||||
CallingQueueItem.CurrentState = _CurrentItemNumber + " of " + _MaxItemsNumber + ": " + _StatusText;
|
||||
CallingQueueItem.CurrentStateProgress = _CurrentItemNumber + " of " + _MaxItemsNumber;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearStatus()
|
||||
{
|
||||
this._CurrentItemNumber = 0;
|
||||
this._MaxItemsNumber = 0;
|
||||
this._StatusText = "";
|
||||
|
||||
if (CallingQueueItem != null)
|
||||
{
|
||||
CallingQueueItem.CurrentState = "";
|
||||
CallingQueueItem.CurrentStateProgress = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,440 +0,0 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using gaseous_signature_parser.models.RomSignatureObject;
|
||||
using Microsoft.VisualBasic;
|
||||
using IGDB.Models;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class RomMediaGroup
|
||||
{
|
||||
public class InvalidMediaGroupId : Exception
|
||||
{
|
||||
public InvalidMediaGroupId(long Id) : base("Unable to find media group by id " + Id)
|
||||
{}
|
||||
}
|
||||
|
||||
public static GameRomMediaGroupItem CreateMediaGroup(long GameId, long PlatformId, List<long> RomIds)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "INSERT INTO RomMediaGroup (Status, PlatformId, GameId) VALUES (@status, @platformid, @gameid); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("status", GameRomMediaGroupItem.GroupBuildStatus.WaitingForBuild);
|
||||
dbDict.Add("gameid", GameId);
|
||||
dbDict.Add("platformid", PlatformId);
|
||||
DataTable mgInsert = db.ExecuteCMD(sql, dbDict);
|
||||
long mgId = (long)mgInsert.Rows[0][0];
|
||||
foreach (long RomId in RomIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
Roms.GameRomItem gameRomItem = Roms.GetRom(RomId);
|
||||
if (gameRomItem.PlatformId == PlatformId)
|
||||
{
|
||||
sql = "INSERT INTO RomMediaGroup_Members (GroupId, RomId) VALUES (@groupid, @romid);";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("groupid", mgId);
|
||||
dbDict.Add("romid", RomId);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Media Group", "Unable to add ROM id " + RomId + " to group. ROM platform is different from group platform.");
|
||||
}
|
||||
}
|
||||
catch (Roms.InvalidRomId irid)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Media Group", "Unable to add ROM id " + RomId + " to group. ROM doesn't exist", irid);
|
||||
}
|
||||
}
|
||||
|
||||
StartMediaGroupBuild(mgId);
|
||||
|
||||
return GetMediaGroup(mgId);
|
||||
}
|
||||
|
||||
public static GameRomMediaGroupItem GetMediaGroup(long Id)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM RomMediaGroup WHERE Id=@id;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", Id);
|
||||
|
||||
DataTable dataTable = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
if (dataTable.Rows.Count == 0)
|
||||
{
|
||||
throw new InvalidMediaGroupId(Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameRomMediaGroupItem mediaGroupItem = BuildMediaGroupFromRow(dataTable.Rows[0]);
|
||||
return mediaGroupItem;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<GameRomMediaGroupItem> GetMediaGroupsFromGameId(long GameId)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM RomMediaGroup WHERE GameId=@gameid;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("gameid", GameId);
|
||||
|
||||
DataTable dataTable = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
List<GameRomMediaGroupItem> mediaGroupItems = new List<GameRomMediaGroupItem>();
|
||||
|
||||
foreach (DataRow row in dataTable.Rows)
|
||||
{
|
||||
mediaGroupItems.Add(BuildMediaGroupFromRow(row));
|
||||
}
|
||||
|
||||
mediaGroupItems.Sort((x, y) => x.PlatformName.CompareTo(y.PlatformName));
|
||||
|
||||
return mediaGroupItems;
|
||||
}
|
||||
|
||||
public static GameRomMediaGroupItem EditMediaGroup(long Id, List<long> RomIds)
|
||||
{
|
||||
GameRomMediaGroupItem mg = GetMediaGroup(Id);
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
|
||||
// delete roms from group
|
||||
sql = "DELETE FROM RomMediaGroup_Members WHERE GroupId=@groupid;";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("groupid", Id);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
// add roms to group
|
||||
foreach (long RomId in RomIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
Roms.GameRomItem gameRomItem = Roms.GetRom(RomId);
|
||||
if (gameRomItem.PlatformId == mg.PlatformId)
|
||||
{
|
||||
sql = "INSERT INTO RomMediaGroup_Members (GroupId, RomId) VALUES (@groupid, @romid);";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("groupid", Id);
|
||||
dbDict.Add("romid", RomId);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Media Group", "Unable to add ROM id " + RomId + " to group. ROM platform is different from group platform.");
|
||||
}
|
||||
}
|
||||
catch (Roms.InvalidRomId irid)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Media Group", "Unable to add ROM id " + RomId + " to group. ROM doesn't exist", irid);
|
||||
}
|
||||
}
|
||||
|
||||
// set group to rebuild
|
||||
sql = "UPDATE RomMediaGroup SET Status=1 WHERE GroupId=@groupid;";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("groupid", Id);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
string MediaGroupZipPath = Path.Combine(Config.LibraryConfiguration.LibraryMediaGroupDirectory, Id + ".zip");
|
||||
if (File.Exists(MediaGroupZipPath))
|
||||
{
|
||||
File.Delete(MediaGroupZipPath);
|
||||
}
|
||||
|
||||
StartMediaGroupBuild(Id);
|
||||
|
||||
// return to caller
|
||||
return GetMediaGroup(Id);
|
||||
}
|
||||
|
||||
public static void DeleteMediaGroup(long Id)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "DELETE FROM RomMediaGroup WHERE Id=@id;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", Id);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
string MediaGroupZipPath = Path.Combine(Config.LibraryConfiguration.LibraryMediaGroupDirectory, Id + ".zip");
|
||||
if (File.Exists(MediaGroupZipPath))
|
||||
{
|
||||
File.Delete(MediaGroupZipPath);
|
||||
}
|
||||
}
|
||||
|
||||
internal static GameRomMediaGroupItem BuildMediaGroupFromRow(DataRow row)
|
||||
{
|
||||
GameRomMediaGroupItem mediaGroupItem = new GameRomMediaGroupItem();
|
||||
mediaGroupItem.Id = (long)row["Id"];
|
||||
mediaGroupItem.Status = (GameRomMediaGroupItem.GroupBuildStatus)row["Status"];
|
||||
mediaGroupItem.PlatformId = (long)row["PlatformId"];
|
||||
mediaGroupItem.GameId = (long)row["GameId"];
|
||||
mediaGroupItem.RomIds = new List<long>();
|
||||
|
||||
// get members
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM RomMediaGroup_Members WHERE GroupId=@id;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", mediaGroupItem.Id);
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
foreach (DataRow dataRow in data.Rows)
|
||||
{
|
||||
mediaGroupItem.RomIds.Add((long)dataRow["RomId"]);
|
||||
}
|
||||
|
||||
return mediaGroupItem;
|
||||
}
|
||||
|
||||
public static void StartMediaGroupBuild(long Id)
|
||||
{
|
||||
GameRomMediaGroupItem mediaGroupItem = GetMediaGroup(Id);
|
||||
|
||||
if (mediaGroupItem.Status != GameRomMediaGroupItem.GroupBuildStatus.Building)
|
||||
{
|
||||
// set collection item to waitingforbuild
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "UPDATE RomMediaGroup SET Status=@bs WHERE Id=@id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", Id);
|
||||
dbDict.Add("bs", GameRomMediaGroupItem.GroupBuildStatus.WaitingForBuild);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
// start background task
|
||||
ProcessQueue.QueueItem queueItem = new ProcessQueue.QueueItem(ProcessQueue.QueueItemType.MediaGroupCompiler, 1, false, true);
|
||||
queueItem.Options = Id;
|
||||
queueItem.ForceExecute();
|
||||
ProcessQueue.QueueItems.Add(queueItem);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CompileMediaGroup(long Id)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
GameRomMediaGroupItem mediaGroupItem = GetMediaGroup(Id);
|
||||
if (mediaGroupItem.Status == GameRomMediaGroupItem.GroupBuildStatus.WaitingForBuild)
|
||||
{
|
||||
Game GameObject = Games.GetGame(mediaGroupItem.GameId, false, false, false);
|
||||
Platform PlatformObject = Platforms.GetPlatform(mediaGroupItem.PlatformId, false);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Media Group", "Beginning build of media group: " + GameObject.Name + " for platform " + PlatformObject.Name);
|
||||
|
||||
// set starting
|
||||
string sql = "UPDATE RomMediaGroup SET Status=@bs WHERE Id=@id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", mediaGroupItem.Id);
|
||||
dbDict.Add("bs", GameRomMediaGroupItem.GroupBuildStatus.Building);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMediaGroupDirectory, mediaGroupItem.Id + ".zip");
|
||||
string ZipFileTempPath = Path.Combine(Config.LibraryConfiguration.LibraryTempDirectory, mediaGroupItem.Id.ToString());
|
||||
|
||||
try
|
||||
{
|
||||
// clean up if needed
|
||||
if (File.Exists(ZipFilePath))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Media Group", "Deleting existing build of media group: " + GameObject.Name + " for platform " + PlatformObject.Name);
|
||||
File.Delete(ZipFilePath);
|
||||
}
|
||||
|
||||
if (Directory.Exists(ZipFileTempPath))
|
||||
{
|
||||
Directory.Delete(ZipFileTempPath, true);
|
||||
}
|
||||
|
||||
// gather media group files
|
||||
Directory.CreateDirectory(ZipFileTempPath);
|
||||
List<Roms.GameRomItem> romItems = new List<Roms.GameRomItem>();
|
||||
List<string> M3UFileContents = new List<string>();
|
||||
foreach (long RomId in mediaGroupItem.RomIds)
|
||||
{
|
||||
Roms.GameRomItem rom = Roms.GetRom(RomId);
|
||||
if (File.Exists(rom.Path))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Media Group", "Copying ROM: " + rom.Name);
|
||||
File.Copy(rom.Path, Path.Combine(ZipFileTempPath, Path.GetFileName(rom.Path)));
|
||||
|
||||
romItems.Add(rom);
|
||||
}
|
||||
}
|
||||
|
||||
// build m3u
|
||||
romItems.Sort((a, b) =>
|
||||
{
|
||||
if (a.MediaDetail != null)
|
||||
{
|
||||
if (a.MediaDetail.Number != null && a.MediaDetail.Side != null)
|
||||
{
|
||||
var firstCompare = a.MediaDetail.Number.ToString().CompareTo(b.MediaDetail.Number.ToString());
|
||||
return firstCompare != 0 ? firstCompare : a.MediaDetail.Side.CompareTo(b.MediaDetail.Side);
|
||||
}
|
||||
else if (a.MediaDetail.Number != null && a.MediaDetail.Side == null)
|
||||
{
|
||||
return a.MediaDetail.Number.ToString().CompareTo(b.MediaDetail.Number.ToString());
|
||||
}
|
||||
else if (a.MediaDetail.Number == null && a.MediaDetail.Side != null)
|
||||
{
|
||||
return a.MediaDetail.Side.ToString().CompareTo(b.MediaDetail.Side.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
return a.Name.CompareTo(b.Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return a.Name.CompareTo(b.Name);
|
||||
}
|
||||
}
|
||||
);
|
||||
foreach (Roms.GameRomItem romItem in romItems)
|
||||
{
|
||||
string M3UFileContent = "";
|
||||
M3UFileContent += romItem.Name;
|
||||
if (romItem.MediaLabel.Length == 0)
|
||||
{
|
||||
if (romItem.RomTypeMedia.Length > 0)
|
||||
{
|
||||
M3UFileContent += "|" + romItem.RomTypeMedia;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
M3UFileContent += "|" + romItem.MediaLabel;
|
||||
}
|
||||
M3UFileContents.Add(M3UFileContent);
|
||||
}
|
||||
|
||||
File.WriteAllText(Path.Combine(ZipFileTempPath, GameObject.Name + ".m3u"), String.Join(Environment.NewLine, M3UFileContents));
|
||||
|
||||
// compress to zip
|
||||
Logging.Log(Logging.LogType.Information, "Media Group", "Compressing media group");
|
||||
if (!Directory.Exists(Config.LibraryConfiguration.LibraryMediaGroupDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(Config.LibraryConfiguration.LibraryMediaGroupDirectory);
|
||||
}
|
||||
ZipFile.CreateFromDirectory(ZipFileTempPath, ZipFilePath, CompressionLevel.SmallestSize, false);
|
||||
|
||||
// clean up
|
||||
if (Directory.Exists(ZipFileTempPath))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Media Group", "Cleaning up");
|
||||
Directory.Delete(ZipFileTempPath, true);
|
||||
}
|
||||
|
||||
// set completed
|
||||
dbDict["bs"] = GameRomMediaGroupItem.GroupBuildStatus.Completed;
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// clean up
|
||||
if (Directory.Exists(ZipFileTempPath))
|
||||
{
|
||||
Directory.Delete(ZipFileTempPath, true);
|
||||
}
|
||||
|
||||
if (File.Exists(ZipFilePath))
|
||||
{
|
||||
File.Delete(ZipFilePath);
|
||||
}
|
||||
|
||||
// set failed
|
||||
dbDict["bs"] = GameRomMediaGroupItem.GroupBuildStatus.Failed;
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
Logging.Log(Logging.LogType.Critical, "Media Group", "Media Group building has failed", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GameRomMediaGroupItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long GameId { get; set; }
|
||||
public long PlatformId { get; set; }
|
||||
public string PlatformName {
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Platforms.GetPlatform(PlatformId, false).Name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
public List<long> RomIds { get; set; }
|
||||
private GroupBuildStatus _Status { get; set; }
|
||||
public GroupBuildStatus Status {
|
||||
get
|
||||
{
|
||||
if (_Status == GroupBuildStatus.Completed)
|
||||
{
|
||||
if (File.Exists(MediaGroupZipPath))
|
||||
{
|
||||
return GroupBuildStatus.Completed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GroupBuildStatus.NoStatus;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return _Status;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
_Status = value;
|
||||
}
|
||||
}
|
||||
public long? Size {
|
||||
get
|
||||
{
|
||||
if (Status == GroupBuildStatus.Completed)
|
||||
{
|
||||
if (File.Exists(MediaGroupZipPath))
|
||||
{
|
||||
FileInfo fi = new FileInfo(MediaGroupZipPath);
|
||||
return fi.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
internal string MediaGroupZipPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(Config.LibraryConfiguration.LibraryMediaGroupDirectory, Id + ".zip");
|
||||
}
|
||||
}
|
||||
public enum GroupBuildStatus
|
||||
{
|
||||
NoStatus = 0,
|
||||
WaitingForBuild = 1,
|
||||
Building = 2,
|
||||
Completed = 3,
|
||||
Failed = 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,79 +1,46 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using gaseous_signature_parser.models.RomSignatureObject;
|
||||
using static gaseous_server.Classes.RomMediaGroup;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using IGDB.Models;
|
||||
using gaseous_tools;
|
||||
|
||||
namespace gaseous_server.Classes
|
||||
{
|
||||
public class Roms
|
||||
{
|
||||
public class InvalidRomId : Exception
|
||||
public static List<GameRomItem> GetRoms(long GameId, long PlatformId = -1)
|
||||
{
|
||||
public InvalidRomId(long Id) : base("Unable to find ROM by id " + Id)
|
||||
{}
|
||||
}
|
||||
|
||||
public static GameRomObject GetRoms(long GameId, long PlatformId = -1, int pageNumber = 0, int pageSize = 0)
|
||||
{
|
||||
GameRomObject GameRoms = new GameRomObject();
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", GameId);
|
||||
|
||||
if (PlatformId == -1) {
|
||||
sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id ORDER BY Platform.`Name`, Games_Roms.`Name`";
|
||||
sql = "SELECT * FROM Games_Roms WHERE GameId = @id ORDER BY `Name`";
|
||||
} else {
|
||||
sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid ORDER BY Platform.`Name`, Games_Roms.`Name`";
|
||||
sql = "SELECT * FROM Games_Roms WHERE GameId = @id AND PlatformId = @platformid ORDER BY `Name`";
|
||||
dbDict.Add("platformid", PlatformId);
|
||||
}
|
||||
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
if (romDT.Rows.Count > 0)
|
||||
{
|
||||
// set count of roms
|
||||
GameRoms.Count = romDT.Rows.Count;
|
||||
|
||||
// setup platforms list
|
||||
Dictionary<long, string> platformDict = new Dictionary<long, string>();
|
||||
|
||||
int pageOffset = pageSize * (pageNumber - 1);
|
||||
for (int i = 0; i < romDT.Rows.Count; i++)
|
||||
List<GameRomItem> romItems = new List<GameRomItem>();
|
||||
foreach (DataRow romDR in romDT.Rows)
|
||||
{
|
||||
GameRomItem gameRomItem = BuildRom(romDT.Rows[i]);
|
||||
|
||||
if ((i >= pageOffset && i < pageOffset + pageSize) || pageSize == 0)
|
||||
{
|
||||
GameRoms.GameRomItems.Add(gameRomItem);
|
||||
romItems.Add(BuildRom(romDR));
|
||||
}
|
||||
|
||||
if (!platformDict.ContainsKey(gameRomItem.PlatformId))
|
||||
{
|
||||
platformDict.Add(gameRomItem.PlatformId, gameRomItem.Platform);
|
||||
}
|
||||
}
|
||||
|
||||
// get rom media groups
|
||||
GameRoms.MediaGroups = Classes.RomMediaGroup.GetMediaGroupsFromGameId(GameId);
|
||||
|
||||
// sort the platforms
|
||||
GameRoms.Platforms = platformDict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value).ToList<KeyValuePair<long, string>>();
|
||||
|
||||
return GameRoms;
|
||||
return romItems;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Games.InvalidGameId(GameId);
|
||||
throw new Exception("Unknown Game Id");
|
||||
}
|
||||
}
|
||||
|
||||
public static GameRomItem GetRom(long RomId)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.Id = @id";
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM Games_Roms WHERE Id = @id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", RomId);
|
||||
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||
@@ -86,7 +53,7 @@ namespace gaseous_server.Classes
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidRomId(RomId);
|
||||
throw new Exception("Unknown ROM Id");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +65,7 @@ namespace gaseous_server.Classes
|
||||
// ensure metadata for gameid is present
|
||||
IGDB.Models.Game game = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "UPDATE Games_Roms SET PlatformId=@platformid, GameId=@gameid WHERE Id = @id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", RomId);
|
||||
@@ -114,20 +81,17 @@ namespace gaseous_server.Classes
|
||||
public static void DeleteRom(long RomId)
|
||||
{
|
||||
GameRomItem rom = GetRom(RomId);
|
||||
if (rom.Library.IsDefaultLibrary == true)
|
||||
{
|
||||
if (File.Exists(rom.Path))
|
||||
{
|
||||
File.Delete(rom.Path);
|
||||
}
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "DELETE FROM Games_Roms WHERE Id = @id";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", RomId);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
|
||||
private static GameRomItem BuildRom(DataRow romDR)
|
||||
{
|
||||
@@ -135,7 +99,7 @@ namespace gaseous_server.Classes
|
||||
{
|
||||
Id = (long)romDR["id"],
|
||||
PlatformId = (long)romDR["platformid"],
|
||||
Platform = (string)romDR["platformname"],
|
||||
Platform = Classes.Metadata.Platforms.GetPlatform((long)romDR["platformid"]),
|
||||
GameId = (long)romDR["gameid"],
|
||||
Name = (string)romDR["name"],
|
||||
Size = (long)romDR["size"],
|
||||
@@ -149,8 +113,7 @@ namespace gaseous_server.Classes
|
||||
MediaLabel = (string)romDR["medialabel"],
|
||||
Path = (string)romDR["path"],
|
||||
Source = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(Int32)romDR["metadatasource"],
|
||||
SignatureSourceGameTitle = (string)Common.ReturnValueIfNull(romDR["MetadataGameName"], ""),
|
||||
Library = GameLibrary.GetLibrary((int)romDR["LibraryId"])
|
||||
SignatureSourceGameTitle = (string)Common.ReturnValueIfNull(romDR["MetadataGameName"], "")
|
||||
};
|
||||
|
||||
// check for a web emulator and update the romItem
|
||||
@@ -168,19 +131,11 @@ namespace gaseous_server.Classes
|
||||
return romItem;
|
||||
}
|
||||
|
||||
public class GameRomObject
|
||||
{
|
||||
public List<GameRomMediaGroupItem> MediaGroups { get; set; } = new List<GameRomMediaGroupItem>();
|
||||
public List<GameRomItem> GameRomItems { get; set; } = new List<GameRomItem>();
|
||||
public int Count { get; set; }
|
||||
public List<KeyValuePair<long, string>> Platforms { get; set; }
|
||||
}
|
||||
|
||||
public class GameRomItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long PlatformId { get; set; }
|
||||
public string Platform { get; set; }
|
||||
public IGDB.Models.Platform Platform { get; set; }
|
||||
//public Dictionary<string, object>? Emulator { get; set; }
|
||||
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
|
||||
public long GameId { get; set; }
|
||||
@@ -194,111 +149,10 @@ namespace gaseous_server.Classes
|
||||
public List<KeyValuePair<string, object>>? Attributes { get; set;}
|
||||
public int RomType { get; set; }
|
||||
public string? RomTypeMedia { get; set; }
|
||||
public MediaType? MediaDetail {
|
||||
get
|
||||
{
|
||||
if (RomTypeMedia != null)
|
||||
{
|
||||
return new MediaType(Source, RomTypeMedia);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
public string? MediaLabel { get; set; }
|
||||
public string? Path { get; set; }
|
||||
public RomSignatureObject.Game.Rom.SignatureSourceType Source { get; set; }
|
||||
public gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType Source { get; set; }
|
||||
public string? SignatureSourceGameTitle { get; set;}
|
||||
public GameLibrary.LibraryItem Library { get; set; }
|
||||
}
|
||||
|
||||
public class MediaType
|
||||
{
|
||||
public MediaType(RomSignatureObject.Game.Rom.SignatureSourceType Source, string MediaTypeString)
|
||||
{
|
||||
switch (Source)
|
||||
{
|
||||
case RomSignatureObject.Game.Rom.SignatureSourceType.TOSEC:
|
||||
string[] typeString = MediaTypeString.Split(" ");
|
||||
|
||||
string inType = "";
|
||||
foreach (string typeStringVal in typeString)
|
||||
{
|
||||
if (inType == "")
|
||||
{
|
||||
switch (typeStringVal.ToLower())
|
||||
{
|
||||
case "disk":
|
||||
Media = RomSignatureObject.Game.Rom.RomTypes.Disk;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "disc":
|
||||
Media = RomSignatureObject.Game.Rom.RomTypes.Disc;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "file":
|
||||
Media = RomSignatureObject.Game.Rom.RomTypes.File;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "part":
|
||||
Media = RomSignatureObject.Game.Rom.RomTypes.Part;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "tape":
|
||||
Media = RomSignatureObject.Game.Rom.RomTypes.Tape;
|
||||
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "of":
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
case "side":
|
||||
inType = typeStringVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (inType.ToLower())
|
||||
{
|
||||
case "disk":
|
||||
case "disc":
|
||||
case "file":
|
||||
case "part":
|
||||
case "tape":
|
||||
Number = int.Parse(typeStringVal);
|
||||
break;
|
||||
case "of":
|
||||
Count = int.Parse(typeStringVal);
|
||||
break;
|
||||
case "side":
|
||||
Side = typeStringVal;
|
||||
break;
|
||||
}
|
||||
inType = "";
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public RomSignatureObject.Game.Rom.RomTypes? Media { get; set; }
|
||||
|
||||
public int? Number { get; set; }
|
||||
|
||||
public int? Count { get; set; }
|
||||
|
||||
public string? Side { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +1,19 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using gaseous_server.Classes;
|
||||
using MySql.Data.MySqlClient;
|
||||
using gaseous_signature_parser.models.RomSignatureObject;
|
||||
using gaseous_tools;
|
||||
using MySqlX.XDevAPI;
|
||||
using System.Data;
|
||||
|
||||
namespace gaseous_server.SignatureIngestors.XML
|
||||
{
|
||||
public class XMLIngestor : QueueItemStatus
|
||||
public class XMLIngestor
|
||||
{
|
||||
public void Import(string SearchPath, gaseous_signature_parser.parser.SignatureParser XMLType)
|
||||
{
|
||||
// connect to database
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
// process provided files
|
||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - XML", "Importing from " + SearchPath);
|
||||
@@ -31,14 +33,6 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
{
|
||||
string XMLFile = PathContents[i];
|
||||
|
||||
SetStatus(i + 1, PathContents.Length, "Processing signature file: " + XMLFile);
|
||||
|
||||
if (Common.SkippableFiles.Contains(Path.GetFileName(XMLFile), StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - XML", "Skipping file: " + XMLFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// check xml file md5
|
||||
Common.hashObject hashObject = new Common.hashObject(XMLFile);
|
||||
sql = "SELECT * FROM Signatures_Sources WHERE SourceMD5=@sourcemd5";
|
||||
@@ -68,11 +62,6 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
{
|
||||
sql = "SELECT * FROM Signatures_Sources WHERE SourceMD5=@sourcemd5";
|
||||
dbDict = new Dictionary<string, object>();
|
||||
string sourceUriStr = "";
|
||||
if (Object.Url != null)
|
||||
{
|
||||
sourceUriStr = Object.Url.ToString();
|
||||
}
|
||||
dbDict.Add("name", Common.ReturnValueIfNull(Object.Name, ""));
|
||||
dbDict.Add("description", Common.ReturnValueIfNull(Object.Description, ""));
|
||||
dbDict.Add("category", Common.ReturnValueIfNull(Object.Category, ""));
|
||||
@@ -80,7 +69,7 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
dbDict.Add("author", Common.ReturnValueIfNull(Object.Author, ""));
|
||||
dbDict.Add("email", Common.ReturnValueIfNull(Object.Email, ""));
|
||||
dbDict.Add("homepage", Common.ReturnValueIfNull(Object.Homepage, ""));
|
||||
dbDict.Add("uri", sourceUriStr);
|
||||
dbDict.Add("uri", Common.ReturnValueIfNull(Object.Url, ""));
|
||||
dbDict.Add("sourcetype", Common.ReturnValueIfNull(Object.SourceType, ""));
|
||||
dbDict.Add("sourcemd5", Object.SourceMd5);
|
||||
dbDict.Add("sourcesha1", Object.SourceSHA1);
|
||||
@@ -223,13 +212,12 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
dbDict.Add("romtypemedia", Common.ReturnValueIfNull(romObject.RomTypeMedia, ""));
|
||||
dbDict.Add("medialabel", Common.ReturnValueIfNull(romObject.MediaLabel, ""));
|
||||
dbDict.Add("metadatasource", romObject.SignatureSource);
|
||||
dbDict.Add("ingestorversion", 2);
|
||||
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
if (sigDB.Rows.Count == 0)
|
||||
{
|
||||
// entry not present, insert it
|
||||
sql = "INSERT INTO Signatures_Roms (GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, MetadataSource, IngestorVersion) VALUES (@gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @attributes, @romtype, @romtypemedia, @medialabel, @metadatasource, @ingestorversion); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
sql = "INSERT INTO Signatures_Roms (GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, MetadataSource) VALUES (@gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @attributes, @romtype, @romtypemedia, @medialabel, @metadatasource); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
|
||||
@@ -256,7 +244,5 @@ namespace gaseous_server.SignatureIngestors.XML
|
||||
}
|
||||
}
|
||||
}
|
||||
ClearStatus();
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,20 +2,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize(Roles = "Admin,Gamer,Player")]
|
||||
[Route("api/v1/[controller]")]
|
||||
public class BackgroundTasksController : Controller
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public List<ProcessQueue.QueueItem> GetQueue()
|
||||
@@ -23,13 +17,10 @@ namespace gaseous_server.Controllers
|
||||
return ProcessQueue.QueueItems;
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{TaskType}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public ActionResult<ProcessQueue.QueueItem> ForceRun(ProcessQueue.QueueItemType TaskType, Boolean ForceRun)
|
||||
{
|
||||
foreach (ProcessQueue.QueueItem qi in ProcessQueue.QueueItems)
|
@@ -3,21 +3,14 @@ using System.Collections.Generic;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
[Route("api/v1/[controller]")]
|
||||
public class BiosController : Controller
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public List<Classes.Bios.BiosItem> GetBios()
|
||||
@@ -25,8 +18,6 @@ namespace gaseous_server.Controllers
|
||||
return Classes.Bios.GetBios();
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{PlatformId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
@@ -35,11 +26,7 @@ namespace gaseous_server.Controllers
|
||||
return Classes.Bios.GetBios(PlatformId, AvailableOnly);
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpHead]
|
||||
[Route("zip/{PlatformId}")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
@@ -50,7 +37,7 @@ namespace gaseous_server.Controllers
|
||||
{
|
||||
IGDB.Models.Platform platform = Classes.Metadata.Platforms.GetPlatform(PlatformId);
|
||||
|
||||
string biosPath = Path.Combine(Config.LibraryConfiguration.LibraryBIOSDirectory, platform.Slug);
|
||||
string biosPath = Path.Combine(gaseous_tools.Config.LibraryConfiguration.LibraryBIOSDirectory, platform.Slug);
|
||||
|
||||
string tempFile = Path.GetTempFileName();
|
||||
|
||||
@@ -72,11 +59,7 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpHead]
|
||||
[Route("{PlatformId}/{BiosName}")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
@@ -4,24 +4,18 @@ using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
[Route("api/v1/[controller]")]
|
||||
public class CollectionsController : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all ROM collections
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public List<Classes.Collections.CollectionItem> GetCollections()
|
||||
@@ -35,8 +29,6 @@ namespace gaseous_server.Controllers
|
||||
/// <param name="CollectionId"></param>
|
||||
/// <param name="Build">Set to true to begin the collection build process</param>
|
||||
/// <returns></returns>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{CollectionId}")]
|
||||
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
|
||||
@@ -63,8 +55,6 @@ namespace gaseous_server.Controllers
|
||||
/// </summary>
|
||||
/// <param name="CollectionId"></param>
|
||||
/// <returns></returns>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{CollectionId}/Roms")]
|
||||
[ProducesResponseType(typeof(List<Classes.Collections.CollectionContents.CollectionPlatformItem>), StatusCodes.Status200OK)]
|
||||
@@ -87,11 +77,8 @@ namespace gaseous_server.Controllers
|
||||
/// </summary>
|
||||
/// <param name="Item"></param>
|
||||
/// <returns></returns>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[Route("Preview")]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[ProducesResponseType(typeof(List<Classes.Collections.CollectionContents.CollectionPlatformItem>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GetCollectionRomsPreview(Classes.Collections.CollectionItem Item)
|
||||
@@ -111,8 +98,6 @@ namespace gaseous_server.Controllers
|
||||
/// </summary>
|
||||
/// <param name="CollectionId"></param>
|
||||
/// <returns></returns>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{CollectionId}/Roms/Zip")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
@@ -123,7 +108,7 @@ namespace gaseous_server.Controllers
|
||||
{
|
||||
Classes.Collections.CollectionItem collectionItem = Classes.Collections.GetCollection(CollectionId);
|
||||
|
||||
string ZipFilePath = Path.Combine(Config.LibraryConfiguration.LibraryCollectionsDirectory, CollectionId + ".zip");
|
||||
string ZipFilePath = Path.Combine(gaseous_tools.Config.LibraryConfiguration.LibraryCollectionsDirectory, CollectionId + ".zip");
|
||||
|
||||
if (System.IO.File.Exists(ZipFilePath))
|
||||
{
|
||||
@@ -146,10 +131,7 @@ namespace gaseous_server.Controllers
|
||||
/// </summary>
|
||||
/// <param name="Item"></param>
|
||||
/// <returns></returns>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public ActionResult NewCollection(Classes.Collections.CollectionItem Item)
|
||||
@@ -170,11 +152,8 @@ namespace gaseous_server.Controllers
|
||||
/// <param name="CollectionId"></param>
|
||||
/// <param name="Item"></param>
|
||||
/// <returns></returns>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPatch]
|
||||
[Route("{CollectionId}")]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult EditCollection(long CollectionId, Classes.Collections.CollectionItem Item)
|
||||
@@ -195,10 +174,7 @@ namespace gaseous_server.Controllers
|
||||
/// <param name="CollectionId"></param>
|
||||
/// <param name="Item"></param>
|
||||
/// <returns></returns>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPatch]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[Route("{CollectionId}/AlwaysInclude")]
|
||||
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
@@ -232,10 +208,7 @@ namespace gaseous_server.Controllers
|
||||
/// Deletes the specified ROM collection
|
||||
/// </summary>
|
||||
/// <param name="CollectionId"></param>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpDelete]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[Route("{CollectionId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
84
gaseous-server/Controllers/FilterController.cs
Normal file
84
gaseous-server/Controllers/FilterController.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[Route("api/v1/[controller]")]
|
||||
[ApiController]
|
||||
public class FilterController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||
public Dictionary<string, object> Filter()
|
||||
{
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
Dictionary<string, object> FilterSet = new Dictionary<string, object>();
|
||||
|
||||
// platforms
|
||||
List<Platform> platforms = new List<Platform>();
|
||||
string sql = "SELECT Platform.Id, Platform.Abbreviation, Platform.AlternativeName, Platform.`Name`, Platform.PlatformLogo, (SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.PlatformId = Platform.Id) AS RomCount FROM Platform HAVING RomCount > 0 ORDER BY `Name`";
|
||||
DataTable dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
platforms.Add(Classes.Metadata.Platforms.GetPlatform((long)dr["id"]));
|
||||
}
|
||||
FilterSet.Add("platforms", platforms);
|
||||
|
||||
// genres
|
||||
List<Genre> genres = new List<Genre>();
|
||||
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM Genre AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.Genres, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
genres.Add(Classes.Metadata.Genres.GetGenres((long)dr["id"]));
|
||||
}
|
||||
FilterSet.Add("genres", genres);
|
||||
|
||||
// game modes
|
||||
List<GameMode> gameModes = new List<GameMode>();
|
||||
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM GameMode AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.GameModes, CAST(t1.Id AS char), '$') ORDER BY t1.Id";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
gameModes.Add(Classes.Metadata.GameModes.GetGame_Modes((long)dr["id"]));
|
||||
}
|
||||
FilterSet.Add("gamemodes", gameModes);
|
||||
|
||||
// player perspectives
|
||||
List<PlayerPerspective> playerPerspectives = new List<PlayerPerspective>();
|
||||
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM PlayerPerspective AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.PlayerPerspectives, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
playerPerspectives.Add(Classes.Metadata.PlayerPerspectives.GetGame_PlayerPerspectives((long)dr["id"]));
|
||||
}
|
||||
FilterSet.Add("playerperspectives", playerPerspectives);
|
||||
|
||||
// themes
|
||||
List<Theme> themes = new List<Theme>();
|
||||
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM Theme AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.Themes, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
themes.Add(Classes.Metadata.Themes.GetGame_Themes((long)dr["id"]));
|
||||
}
|
||||
FilterSet.Add("themes", themes);
|
||||
|
||||
return FilterSet;
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,25 +6,21 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using static gaseous_server.Classes.Metadata.AgeRatings;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
[Route("api/v1/[controller]")]
|
||||
[ApiController]
|
||||
public class GamesController : Controller
|
||||
public class GamesController : ControllerBase
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||
public ActionResult Game(
|
||||
@@ -39,7 +35,7 @@ namespace gaseous_server.Controllers
|
||||
bool sortdescending = false)
|
||||
{
|
||||
|
||||
return Ok(GetGames(name, platform, genre, gamemode, playerperspective, theme, minrating, maxrating, "Adult", true, true, sortdescending));
|
||||
return Ok(GetGames(name, platform, genre, gamemode, playerperspective, theme, minrating, maxrating, sortdescending));
|
||||
}
|
||||
|
||||
public static List<Game> GetGames(
|
||||
@@ -51,9 +47,6 @@ namespace gaseous_server.Controllers
|
||||
string theme = "",
|
||||
int minrating = -1,
|
||||
int maxrating = -1,
|
||||
string ratinggroup = "Adult",
|
||||
bool includenullrating = true,
|
||||
bool sortbynamethe = false,
|
||||
bool sortdescending = false)
|
||||
{
|
||||
string whereClause = "";
|
||||
@@ -106,7 +99,7 @@ namespace gaseous_server.Controllers
|
||||
|
||||
if (genre.Length > 0)
|
||||
{
|
||||
tempVal = "Relation_Game_Genres.GenresId IN (";
|
||||
tempVal = "(";
|
||||
string[] genreClauseItems = genre.Split(",");
|
||||
for (int i = 0; i < genreClauseItems.Length; i++)
|
||||
{
|
||||
@@ -115,7 +108,7 @@ namespace gaseous_server.Controllers
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string genreLabel = "@Genre" + i;
|
||||
tempVal += genreLabel;
|
||||
tempVal += "JSON_CONTAINS(Game.Genres, " + genreLabel + ", '$')";
|
||||
whereParams.Add(genreLabel, genreClauseItems[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
@@ -124,7 +117,7 @@ namespace gaseous_server.Controllers
|
||||
|
||||
if (gamemode.Length > 0)
|
||||
{
|
||||
tempVal = "Relation_Game_GameModes.GameModesId IN (";
|
||||
tempVal = "(";
|
||||
string[] gameModeClauseItems = gamemode.Split(",");
|
||||
for (int i = 0; i < gameModeClauseItems.Length; i++)
|
||||
{
|
||||
@@ -133,7 +126,7 @@ namespace gaseous_server.Controllers
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string gameModeLabel = "@GameMode" + i;
|
||||
tempVal += gameModeLabel;
|
||||
tempVal += "JSON_CONTAINS(Game.GameModes, " + gameModeLabel + ", '$')";
|
||||
whereParams.Add(gameModeLabel, gameModeClauseItems[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
@@ -142,7 +135,7 @@ namespace gaseous_server.Controllers
|
||||
|
||||
if (playerperspective.Length > 0)
|
||||
{
|
||||
tempVal = "Relation_Game_PlayerPerspectives.PlayerPerspectivesId IN (";
|
||||
tempVal = "(";
|
||||
string[] playerPerspectiveClauseItems = playerperspective.Split(",");
|
||||
for (int i = 0; i < playerPerspectiveClauseItems.Length; i++)
|
||||
{
|
||||
@@ -151,7 +144,7 @@ namespace gaseous_server.Controllers
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string playerPerspectiveLabel = "@PlayerPerspective" + i;
|
||||
tempVal += playerPerspectiveLabel;
|
||||
tempVal += "JSON_CONTAINS(Game.PlayerPerspectives, " + playerPerspectiveLabel + ", '$')";
|
||||
whereParams.Add(playerPerspectiveLabel, playerPerspectiveClauseItems[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
@@ -160,7 +153,7 @@ namespace gaseous_server.Controllers
|
||||
|
||||
if (theme.Length > 0)
|
||||
{
|
||||
tempVal = "Relation_Game_Themes.ThemesId IN (";
|
||||
tempVal = "(";
|
||||
string[] themeClauseItems = theme.Split(",");
|
||||
for (int i = 0; i < themeClauseItems.Length; i++)
|
||||
{
|
||||
@@ -169,60 +162,13 @@ namespace gaseous_server.Controllers
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string themeLabel = "@Theme" + i;
|
||||
tempVal += themeLabel;
|
||||
tempVal += "JSON_CONTAINS(Game.Themes, " + themeLabel + ", '$')";
|
||||
whereParams.Add(themeLabel, themeClauseItems[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
if (ratinggroup.Length > 0)
|
||||
{
|
||||
List<long> AgeClassificationsList = new List<long>();
|
||||
foreach (string ratingGroup in ratinggroup.Split(','))
|
||||
{
|
||||
AgeGroups.AgeRestrictionGroupings ageRestriction = (AgeGroups.AgeRestrictionGroupings)Enum.Parse(typeof(AgeGroups.AgeRestrictionGroupings), ratingGroup);
|
||||
if (AgeGroups.AgeGroupings.ContainsKey(ageRestriction))
|
||||
{
|
||||
List<AgeGroups.AgeGroupItem> ageGroups = AgeGroups.AgeGroupings[ageRestriction];
|
||||
foreach (AgeGroups.AgeGroupItem ageGroup in ageGroups)
|
||||
{
|
||||
AgeClassificationsList.AddRange(ageGroup.AgeGroupItemValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AgeClassificationsList.Count > 0)
|
||||
{
|
||||
tempVal = "(view_AgeRatings.Rating IN (";
|
||||
for (int i = 0; i < AgeClassificationsList.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += ", ";
|
||||
}
|
||||
string themeLabel = "@Rating" + i;
|
||||
tempVal += themeLabel;
|
||||
whereParams.Add(themeLabel, AgeClassificationsList[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
|
||||
tempVal += " OR ";
|
||||
|
||||
if (includenullrating == true)
|
||||
{
|
||||
tempVal += "view_AgeRatings.Rating IS NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
tempVal += "view_AgeRatings.Rating IS NOT NULL";
|
||||
}
|
||||
tempVal += ")";
|
||||
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
}
|
||||
|
||||
// build where clause
|
||||
if (whereClauses.Count > 0)
|
||||
{
|
||||
@@ -252,21 +198,14 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
|
||||
// order by clause
|
||||
string orderByField = "Name";
|
||||
if (sortbynamethe == true)
|
||||
{
|
||||
orderByField = "NameThe";
|
||||
}
|
||||
string orderByClause = "ORDER BY `" + orderByField + "` ASC";
|
||||
string orderByClause = "ORDER BY `Name` ASC";
|
||||
if (sortdescending == true)
|
||||
{
|
||||
orderByClause = "ORDER BY `" + orderByField + "` DESC";
|
||||
orderByClause = "ORDER BY `Name` DESC";
|
||||
}
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
//string sql = "SELECT DISTINCT Games_Roms.GameId AS ROMGameId, Game.* FROM Games_Roms LEFT JOIN Game ON Game.Id = Games_Roms.GameId LEFT JOIN Relation_Game_Genres ON Game.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON Game.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON Game.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON Game.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
||||
|
||||
string sql = "SELECT DISTINCT Games_Roms.GameId AS ROMGameId, Game.*, case when Game.`Name` like 'The %' then CONCAT(trim(substr(Game.`Name` from 4)), ', The') else Game.`Name` end as NameThe FROM Games_Roms LEFT JOIN Game ON Game.Id = Games_Roms.GameId LEFT JOIN Relation_Game_Genres ON Game.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON Game.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON Game.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON Game.Id = Relation_Game_Themes.GameId LEFT JOIN (SELECT Relation_Game_AgeRatings.GameId, AgeRating.* FROM Relation_Game_AgeRatings JOIN AgeRating ON Relation_Game_AgeRatings.AgeRatingsId = AgeRating.Id) view_AgeRatings ON Game.Id = view_AgeRatings.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT DISTINCT Games_Roms.GameId AS ROMGameId, Game.Id, Game.AgeRatings, Game.AggregatedRating, Game.AggregatedRatingCount, Game.AlternativeNames, Game.Artworks, Game.Bundles, Game.Category, Game.Collection, Game.Cover, Game.Dlcs, Game.Expansions, Game.ExternalGames, Game.FirstReleaseDate, Game.`Follows`, Game.Franchise, Game.Franchises, Game.GameEngines, Game.GameModes, Game.Genres, Game.Hypes, Game.InvolvedCompanies, Game.Keywords, Game.MultiplayerModes, Game.`Name`, Game.ParentGame, Game.Platforms, Game.PlayerPerspectives, Game.Rating, Game.RatingCount, Game.ReleaseDates, Game.Screenshots, Game.SimilarGames, Game.Slug, Game.StandaloneExpansions, Game.`Status`, Game.StoryLine, Game.Summary, Game.Tags, Game.Themes, Game.TotalRating, Game.TotalRatingCount, Game.VersionParent, Game.VersionTitle, Game.Videos, Game.Websites FROM gaseous.Games_Roms LEFT JOIN Game ON Game.Id = Games_Roms.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
||||
|
||||
List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>();
|
||||
|
||||
@@ -280,8 +219,6 @@ namespace gaseous_server.Controllers
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}")]
|
||||
[ProducesResponseType(typeof(Game), StatusCodes.Status200OK)]
|
||||
@@ -308,8 +245,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/alternativename")]
|
||||
[ProducesResponseType(typeof(List<AlternativeName>), StatusCodes.Status200OK)]
|
||||
@@ -341,8 +276,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/agerating")]
|
||||
[ProducesResponseType(typeof(List<AgeRatings.GameAgeRating>), StatusCodes.Status200OK)]
|
||||
@@ -374,8 +307,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/agerating/{RatingId}/image")]
|
||||
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
|
||||
@@ -455,8 +386,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/artwork")]
|
||||
[ProducesResponseType(typeof(List<Artwork>), StatusCodes.Status200OK)]
|
||||
@@ -486,8 +415,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/artwork/{ArtworkId}")]
|
||||
[ProducesResponseType(typeof(Artwork), StatusCodes.Status200OK)]
|
||||
@@ -522,8 +449,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/artwork/{ArtworkId}/image")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
@@ -578,8 +503,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/cover")]
|
||||
[ProducesResponseType(typeof(Cover), StatusCodes.Status200OK)]
|
||||
@@ -613,8 +536,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/cover/image")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
@@ -654,8 +575,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/genre")]
|
||||
[ProducesResponseType(typeof(List<Genre>), StatusCodes.Status200OK)]
|
||||
@@ -692,8 +611,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/companies")]
|
||||
[ProducesResponseType(typeof(List<Dictionary<string, object>>), StatusCodes.Status200OK)]
|
||||
@@ -737,8 +654,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/companies/{CompanyId}")]
|
||||
[ProducesResponseType(typeof(Dictionary<string, object>), StatusCodes.Status200OK)]
|
||||
@@ -780,8 +695,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/companies/{CompanyId}/image")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
@@ -825,58 +738,20 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/releasedates")]
|
||||
[ProducesResponseType(typeof(List<ReleaseDate>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ResponseCache(CacheProfileName = "7Days")]
|
||||
public ActionResult GameReleaseDates(long GameId)
|
||||
{
|
||||
try
|
||||
{
|
||||
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
if (gameObject != null)
|
||||
{
|
||||
List<ReleaseDate> rdObjects = new List<ReleaseDate>();
|
||||
if (gameObject.ReleaseDates != null)
|
||||
{
|
||||
foreach (long icId in gameObject.ReleaseDates.Ids)
|
||||
{
|
||||
ReleaseDate releaseDate = Classes.Metadata.ReleaseDates.GetReleaseDates(icId);
|
||||
|
||||
rdObjects.Add(releaseDate);
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(rdObjects);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/roms")]
|
||||
[ProducesResponseType(typeof(Classes.Roms.GameRomObject), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(List<Classes.Roms.GameRomItem>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||
public ActionResult GameRom(long GameId, int pageNumber = 0, int pageSize = 0, long PlatformId = -1)
|
||||
public ActionResult GameRom(long GameId)
|
||||
{
|
||||
try
|
||||
{
|
||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
return Ok(Classes.Roms.GetRoms(GameId, PlatformId, pageNumber, pageSize));
|
||||
List<Classes.Roms.GameRomItem> roms = Classes.Roms.GetRoms(GameId);
|
||||
|
||||
return Ok(roms);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -884,8 +759,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/roms/{RomId}")]
|
||||
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
||||
@@ -913,10 +786,7 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPatch]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[Route("{GameId}/roms/{RomId}")]
|
||||
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
@@ -943,10 +813,7 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpDelete]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[Route("{GameId}/roms/{RomId}")]
|
||||
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
@@ -973,11 +840,7 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpHead]
|
||||
[Route("{GameId}/roms/{RomId}/file")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
@@ -1012,11 +875,7 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpHead]
|
||||
[Route("{GameId}/roms/{RomId}/{FileName}")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
@@ -1051,175 +910,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/romgroup/{RomGroupId}")]
|
||||
[ProducesResponseType(typeof(Classes.RomMediaGroup.GameRomMediaGroupItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||
public ActionResult GameRomGroup(long GameId, long RomGroupId)
|
||||
{
|
||||
try
|
||||
{
|
||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
Classes.RomMediaGroup.GameRomMediaGroupItem rom = Classes.RomMediaGroup.GetMediaGroup(RomGroupId);
|
||||
if (rom.GameId == GameId)
|
||||
{
|
||||
return Ok(rom);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[Route("{GameId}/romgroup")]
|
||||
[ProducesResponseType(typeof(Classes.RomMediaGroup.GameRomMediaGroupItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult NewGameRomGroup(long GameId, long PlatformId, [FromBody] List<long> RomIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
try
|
||||
{
|
||||
Classes.RomMediaGroup.GameRomMediaGroupItem rom = Classes.RomMediaGroup.CreateMediaGroup(GameId, PlatformId, RomIds);
|
||||
return Ok(rom);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPatch]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[Route("{GameId}/romgroup/{RomId}")]
|
||||
[ProducesResponseType(typeof(Classes.RomMediaGroup.GameRomMediaGroupItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GameRomGroupMembers(long GameId, long RomGroupId, [FromBody] List<long> RomIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
Classes.RomMediaGroup.GameRomMediaGroupItem rom = Classes.RomMediaGroup.GetMediaGroup(RomGroupId);
|
||||
if (rom.GameId == GameId)
|
||||
{
|
||||
rom = Classes.RomMediaGroup.EditMediaGroup(RomGroupId, RomIds);
|
||||
return Ok(rom);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpDelete]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[Route("{GameId}/romgroup/{RomGroupId}")]
|
||||
[ProducesResponseType(typeof(Classes.RomMediaGroup.GameRomMediaGroupItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GameRomGroupDelete(long GameId, long RomGroupId)
|
||||
{
|
||||
try
|
||||
{
|
||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
Classes.RomMediaGroup.GameRomMediaGroupItem rom = Classes.RomMediaGroup.GetMediaGroup(RomGroupId);
|
||||
if (rom.GameId == GameId)
|
||||
{
|
||||
Classes.RomMediaGroup.DeleteMediaGroup(RomGroupId);
|
||||
return Ok(rom);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpHead]
|
||||
[Route("{GameId}/romgroup/{RomGroupId}/file")]
|
||||
[Route("{GameId}/romgroup/{RomGroupId}/{filename}")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GameRomGroupFile(long GameId, long RomGroupId, string filename = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||
|
||||
Classes.RomMediaGroup.GameRomMediaGroupItem rom = Classes.RomMediaGroup.GetMediaGroup(RomGroupId);
|
||||
if (rom.GameId != GameId)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
string romFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMediaGroupDirectory, RomGroupId + ".zip");
|
||||
if (System.IO.File.Exists(romFilePath))
|
||||
{
|
||||
FileStream content = new FileStream(romFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
string returnFileName = "";
|
||||
if (filename == "")
|
||||
{
|
||||
returnFileName = gameObject.Name + ".zip";
|
||||
}
|
||||
else
|
||||
{
|
||||
returnFileName = filename;
|
||||
}
|
||||
FileStreamResult response = File(content, "application/octet-stream", returnFileName);
|
||||
return response;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("search")]
|
||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||
@@ -1257,8 +947,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/screenshots")]
|
||||
[ProducesResponseType(typeof(List<Screenshot>), StatusCodes.Status200OK)]
|
||||
@@ -1288,8 +976,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/screenshots/{ScreenshotId}")]
|
||||
[ProducesResponseType(typeof(Screenshot), StatusCodes.Status200OK)]
|
||||
@@ -1322,8 +1008,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/screenshots/{ScreenshotId}/image")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||
@@ -1366,8 +1050,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/videos")]
|
||||
[ProducesResponseType(typeof(List<GameVideo>), StatusCodes.Status200OK)]
|
21
gaseous-server/Controllers/LogsController.cs
Normal file
21
gaseous-server/Controllers/LogsController.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_tools;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v1/[controller]")]
|
||||
public class LogsController : Controller
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public List<Logging.LogItem> Logs(long? StartIndex, int PageNumber = 1, int PageSize = 100)
|
||||
{
|
||||
return Logging.GetLogs(StartIndex, PageNumber, PageSize);
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,24 +7,18 @@ using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Models;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Route("api/v1/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class PlatformMapsController : Controller
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(List<PlatformMapping.PlatformMapItem>), StatusCodes.Status200OK)]
|
||||
public ActionResult GetPlatformMap(bool ResetToDefault = false)
|
||||
@@ -37,8 +31,6 @@ namespace gaseous_server.Controllers
|
||||
return Ok(PlatformMapping.PlatformMap);
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{PlatformId}")]
|
||||
[ProducesResponseType(typeof(PlatformMapping.PlatformMapItem), StatusCodes.Status200OK)]
|
||||
@@ -64,13 +56,10 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(List<IFormFile>), StatusCodes.Status200OK)]
|
||||
[RequestSizeLimit(long.MaxValue)]
|
||||
[DisableRequestSizeLimit, RequestFormLimits(MultipartBodyLengthLimit = long.MaxValue, ValueLengthLimit = int.MaxValue)]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> UploadPlatformMap(List<IFormFile> files)
|
||||
{
|
||||
Guid sessionid = Guid.NewGuid();
|
||||
@@ -121,9 +110,7 @@ namespace gaseous_server.Controllers
|
||||
return Ok(new { count = files.Count, size });
|
||||
}
|
||||
|
||||
// [MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
// [HttpPost]
|
||||
// [Route("{PlatformId}")]
|
||||
// [ProducesResponseType(typeof(PlatformMapping.PlatformMapItem), StatusCodes.Status200OK)]
|
||||
// [ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
@@ -150,13 +137,10 @@ namespace gaseous_server.Controllers
|
||||
// }
|
||||
// }
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPatch]
|
||||
[Route("{PlatformId}")]
|
||||
[ProducesResponseType(typeof(PlatformMapping.PlatformMapItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public ActionResult EditPlatformMap(long PlatformId, PlatformMapping.PlatformMapItem Map)
|
||||
{
|
||||
try
|
@@ -5,26 +5,20 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Models;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
[Route("api/v1/[controller]")]
|
||||
[ApiController]
|
||||
public class PlatformsController : Controller
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(List<Platform>), StatusCodes.Status200OK)]
|
||||
public ActionResult Platform()
|
||||
@@ -34,9 +28,9 @@ namespace gaseous_server.Controllers
|
||||
|
||||
public static List<Platform> GetPlatforms()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
string sql = "SELECT * FROM Platform WHERE Id IN (SELECT DISTINCT PlatformId FROM Games_Roms) ORDER BY `Name` ASC;";
|
||||
string sql = "SELECT * FROM gaseous.Platform WHERE Id IN (SELECT DISTINCT PlatformId FROM Games_Roms) ORDER BY `Name` ASC;";
|
||||
|
||||
List<Platform> RetVal = new List<Platform>();
|
||||
|
||||
@@ -49,8 +43,6 @@ namespace gaseous_server.Controllers
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{PlatformId}")]
|
||||
[ProducesResponseType(typeof(Platform), StatusCodes.Status200OK)]
|
||||
@@ -76,8 +68,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{PlatformId}/platformlogo")]
|
||||
[ProducesResponseType(typeof(PlatformLogo), StatusCodes.Status200OK)]
|
||||
@@ -110,8 +100,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{PlatformId}/platformlogo/image")]
|
||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
@@ -6,28 +6,22 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using static gaseous_server.Classes.Metadata.AgeRatings;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
[Route("api/v1/[controller]")]
|
||||
[ApiController]
|
||||
public class RomsController : Controller
|
||||
public class RomsController : ControllerBase
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin,Gamer")]
|
||||
[ProducesResponseType(typeof(List<IFormFile>), StatusCodes.Status200OK)]
|
||||
[RequestSizeLimit(long.MaxValue)]
|
||||
[DisableRequestSizeLimit, RequestFormLimits(MultipartBodyLengthLimit = long.MaxValue, ValueLengthLimit = int.MaxValue)]
|
||||
@@ -77,7 +71,7 @@ namespace gaseous_server.Controllers
|
||||
// Process uploaded files
|
||||
foreach (Dictionary<string, object> UploadedFile in UploadedFiles)
|
||||
{
|
||||
Classes.ImportGame.ImportGameFile((string)UploadedFile["fullpath"], OverridePlatform);
|
||||
Classes.ImportGame.ImportGameFile((string)UploadedFile["fullpath"], OverridePlatform, false);
|
||||
}
|
||||
|
||||
if (Directory.Exists(workPath))
|
@@ -2,26 +2,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static gaseous_server.Classes.Metadata.Games;
|
||||
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
[Route("api/v1/[controller]")]
|
||||
public class SearchController : Controller
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
[HttpGet]
|
||||
[Route("Platform")]
|
||||
[ProducesResponseType(typeof(List<Platform>), StatusCodes.Status200OK)]
|
||||
@@ -34,18 +33,15 @@ namespace gaseous_server.Controllers
|
||||
private static async Task<List<Platform>> _SearchForPlatform(string SearchString)
|
||||
{
|
||||
string searchBody = "";
|
||||
string searchFields = "fields abbreviation,alternative_name,category,checksum,created_at,generation,name,platform_family,platform_logo,slug,summary,updated_at,url,versions,websites; ";
|
||||
searchBody += "fields abbreviation,alternative_name,category,checksum,created_at,generation,name,platform_family,platform_logo,slug,summary,updated_at,url,versions,websites; ";
|
||||
searchBody += "where name ~ *\"" + SearchString + "\"*;";
|
||||
|
||||
// get Platform metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Platform>(IGDBClient.Endpoints.Platforms, searchFields, searchBody);
|
||||
var results = await igdb.QueryAsync<Platform>(IGDBClient.Endpoints.Platforms, query: searchBody);
|
||||
|
||||
return results.ToList();
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("Game")]
|
||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||
@@ -58,13 +54,12 @@ namespace gaseous_server.Controllers
|
||||
private static async Task<List<Game>> _SearchForGame(long PlatformId, string SearchString)
|
||||
{
|
||||
string searchBody = "";
|
||||
string searchFields = "fields cover.*,first_release_date,name,platforms,slug; ";
|
||||
searchBody += "fields cover.*,first_release_date,name,platforms,slug; ";
|
||||
searchBody += "search \"" + SearchString + "\";";
|
||||
searchBody += "where platforms = (" + PlatformId + ");";
|
||||
|
||||
// get Platform metadata
|
||||
Communications comms = new Communications();
|
||||
var results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody);
|
||||
var results = await igdb.QueryAsync<Game>(IGDBClient.Endpoints.Games, query: searchBody);
|
||||
|
||||
return results.ToList();
|
||||
}
|
@@ -4,9 +4,7 @@ using System.Data;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_signature_parser.models.RomSignatureObject;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using gaseous_tools;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||
@@ -14,18 +12,13 @@ using Microsoft.AspNetCore.Mvc;
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]/[action]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
public class SignaturesController : Controller
|
||||
[Route("api/v1/[controller]/[action]")]
|
||||
public class SignaturesController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the current signature counts from the database
|
||||
/// </summary>
|
||||
/// <returns>Number of sources, publishers, games, and rom signatures in the database</returns>
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Models.Signatures_Status Status()
|
||||
@@ -33,8 +26,6 @@ namespace gaseous_server.Controllers
|
||||
return new Models.Signatures_Status();
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public List<Models.Signatures_Games> GetSignature(string md5 = "", string sha1 = "")
|
||||
@@ -48,8 +39,6 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public List<Models.Signatures_Games> GetByTosecName(string TosecName = "")
|
||||
@@ -65,7 +54,7 @@ namespace gaseous_server.Controllers
|
||||
|
||||
private List<Models.Signatures_Games> _GetSignature(string sqlWhere, string searchString)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT view_Signatures_Games.*, Signatures_Roms.Id AS romid, Signatures_Roms.Name AS romname, Signatures_Roms.Size, Signatures_Roms.CRC, Signatures_Roms.MD5, Signatures_Roms.SHA1, Signatures_Roms.DevelopmentStatus, Signatures_Roms.Attributes, Signatures_Roms.RomType, Signatures_Roms.RomTypeMedia, Signatures_Roms.MediaLabel, Signatures_Roms.MetadataSource FROM Signatures_Roms INNER JOIN view_Signatures_Games ON Signatures_Roms.GameId = view_Signatures_Games.Id WHERE " + sqlWhere;
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("searchString", searchString);
|
||||
@@ -103,7 +92,7 @@ namespace gaseous_server.Controllers
|
||||
Sha1 = ((string)sigDbRow["SHA1"]).ToLower(),
|
||||
DevelopmentStatus = (string)sigDbRow["DevelopmentStatus"],
|
||||
Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(sigDbRow["Attributes"], "[]")),
|
||||
RomType = (RomSignatureObject.Game.Rom.RomTypes)(int)sigDbRow["RomType"],
|
||||
RomType = (Models.Signatures_Games.RomItem.RomTypes)(int)sigDbRow["RomType"],
|
||||
RomTypeMedia = (string)sigDbRow["RomTypeMedia"],
|
||||
MediaLabel = (string)sigDbRow["MediaLabel"],
|
||||
SignatureSource = (gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType)(Int32)sigDbRow["MetadataSource"]
|
112
gaseous-server/Controllers/SystemController.cs
Normal file
112
gaseous-server/Controllers/SystemController.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_tools;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v1/[controller]")]
|
||||
public class SystemController : Controller
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public SystemInfo GetSystemStatus()
|
||||
{
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
SystemInfo ReturnValue = new SystemInfo();
|
||||
|
||||
// disk size
|
||||
List<SystemInfo.PathItem> Disks = new List<SystemInfo.PathItem>();
|
||||
//Disks.Add(GetDisk(gaseous_tools.Config.ConfigurationPath));
|
||||
Disks.Add(GetDisk(gaseous_tools.Config.LibraryConfiguration.LibraryRootDirectory));
|
||||
ReturnValue.Paths = Disks;
|
||||
|
||||
// database size
|
||||
string sql = "SELECT table_schema, SUM(data_length + index_length) FROM information_schema.tables WHERE table_schema = '" + Config.DatabaseConfiguration.DatabaseName + "'";
|
||||
DataTable dbResponse = db.ExecuteCMD(sql);
|
||||
ReturnValue.DatabaseSize = (long)(System.Decimal)dbResponse.Rows[0][1];
|
||||
|
||||
// platform statistics
|
||||
sql = "SELECT Platform.`name`, grc.Count, grs.Size FROM Platform INNER JOIN (SELECT Platform.`name` AS `Name`, SUM(grs.Size) AS Size FROM Platform JOIN Games_Roms AS grs ON (grs.PlatformId = Platform.Id) GROUP BY Platform.`name`) grs ON (grs.`Name` = Platform.`name`) INNER JOIN (SELECT Platform.`name` AS `Name`, COUNT(grc.Size) AS Count FROM Platform JOIN Games_Roms AS grc ON (grc.PlatformId = Platform.Id) GROUP BY Platform.`name`) grc ON (grc.`Name` = Platform.`name`) ORDER BY Platform.`name`;";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
ReturnValue.PlatformStatistics = new List<SystemInfo.PlatformStatisticsItem>();
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
SystemInfo.PlatformStatisticsItem platformStatisticsItem = new SystemInfo.PlatformStatisticsItem
|
||||
{
|
||||
Platform = (string)dr["name"],
|
||||
RomCount = (long)dr["Count"],
|
||||
TotalSize = (long)(System.Decimal)dr["Size"]
|
||||
};
|
||||
ReturnValue.PlatformStatistics.Add(platformStatisticsItem);
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("Version")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Version GetSystemVersion() {
|
||||
return Assembly.GetExecutingAssembly().GetName().Version;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("VersionFile")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public FileContentResult GetSystemVersionAsFile() {
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string ver = "var AppVersion = \"" + Assembly.GetExecutingAssembly().GetName().Version.ToString() + "\";" + Environment.NewLine +
|
||||
"var DBSchemaVersion = \"" + db.GetDatabaseSchemaVersion() + "\";";
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(ver);
|
||||
return File(bytes, "text/javascript");
|
||||
}
|
||||
|
||||
private SystemInfo.PathItem GetDisk(string Path)
|
||||
{
|
||||
SystemInfo.PathItem pathItem = new SystemInfo.PathItem {
|
||||
LibraryPath = Path,
|
||||
SpaceUsed = gaseous_tools.Common.DirSize(new DirectoryInfo(Path)),
|
||||
SpaceAvailable = new DriveInfo(Path).AvailableFreeSpace,
|
||||
TotalSpace = new DriveInfo(Path).TotalSize
|
||||
};
|
||||
|
||||
return pathItem;
|
||||
}
|
||||
|
||||
public class SystemInfo
|
||||
{
|
||||
public Version ApplicationVersion {
|
||||
get
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().GetName().Version;
|
||||
}
|
||||
}
|
||||
public List<PathItem>? Paths { get; set; }
|
||||
public long DatabaseSize { get; set; }
|
||||
public List<PlatformStatisticsItem>? PlatformStatistics { get; set; }
|
||||
|
||||
public class PathItem
|
||||
{
|
||||
public string LibraryPath { get; set; }
|
||||
public long SpaceUsed { get; set; }
|
||||
public long SpaceAvailable { get; set; }
|
||||
public long TotalSpace { get; set; }
|
||||
}
|
||||
|
||||
public class PlatformStatisticsItem
|
||||
{
|
||||
public string Platform { get; set; }
|
||||
public long RomCount { get; set; }
|
||||
public long TotalSize { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,417 +0,0 @@
|
||||
using System.Data;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Authentication;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
public class AccountController : Controller
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly IEmailSender _emailSender;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public AccountController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
IEmailSender emailSender,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
_emailSender = emailSender;
|
||||
_logger = loggerFactory.CreateLogger<AccountController>();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("Login")]
|
||||
public async Task<IActionResult> Login(LoginViewModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// This doesn't count login failures towards account lockout
|
||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
||||
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Login", model.Email + " has logged in, from IP: " + HttpContext.Connection.RemoteIpAddress?.ToString());
|
||||
return Ok(result.ToString());
|
||||
}
|
||||
// if (result.RequiresTwoFactor)
|
||||
// {
|
||||
// return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
|
||||
// }
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Login", model.Email + " was unable to login due to a locked account. Login attempt from IP: " + HttpContext.Connection.RemoteIpAddress?.ToString());
|
||||
return Unauthorized();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Login", "An unknown error occurred during login by " + model.Email + ". Login attempt from IP: " + HttpContext.Connection.RemoteIpAddress?.ToString());
|
||||
return Unauthorized();
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
Logging.Log(Logging.LogType.Critical, "Login", "An unknown error occurred during login by " + model.Email + ". Login attempt from IP: " + HttpContext.Connection.RemoteIpAddress?.ToString());
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("LogOff")]
|
||||
public async Task<IActionResult> LogOff()
|
||||
{
|
||||
var userName = User.FindFirstValue(ClaimTypes.Name);
|
||||
await _signInManager.SignOutAsync();
|
||||
if (userName != null)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Login", userName + " has logged out");
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("Profile/Basic")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> ProfileBasic()
|
||||
{
|
||||
ProfileBasicViewModel profile = new ProfileBasicViewModel();
|
||||
profile.UserId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
ApplicationUser user = await _userManager.FindByIdAsync(profile.UserId);
|
||||
profile.UserName = _userManager.GetUserName(HttpContext.User);
|
||||
profile.EmailAddress = await _userManager.GetEmailAsync(user);
|
||||
profile.Roles = new List<string>(await _userManager.GetRolesAsync(user));
|
||||
profile.SecurityProfile = user.SecurityProfile;
|
||||
profile.UserPreferences = user.UserPreferences;
|
||||
profile.Roles.Sort();
|
||||
|
||||
return Ok(profile);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("Profile/Basic/profile.js")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> ProfileBasicFile()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user != null)
|
||||
{
|
||||
ProfileBasicViewModel profile = new ProfileBasicViewModel();
|
||||
profile.UserId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
profile.UserName = _userManager.GetUserName(HttpContext.User);
|
||||
profile.EmailAddress = await _userManager.GetEmailAsync(user);
|
||||
profile.Roles = new List<string>(await _userManager.GetRolesAsync(user));
|
||||
profile.SecurityProfile = user.SecurityProfile;
|
||||
profile.UserPreferences = user.UserPreferences;
|
||||
profile.Roles.Sort();
|
||||
|
||||
string profileString = "var userProfile = " + Newtonsoft.Json.JsonConvert.SerializeObject(profile, Newtonsoft.Json.Formatting.Indented) + ";";
|
||||
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(profileString);
|
||||
return File(bytes, "text/javascript");
|
||||
}
|
||||
else
|
||||
{
|
||||
string profileString = "var userProfile = null;";
|
||||
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(profileString);
|
||||
return File(bytes, "text/javascript");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("ChangePassword")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> ChangePassword(ChangePasswordViewModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
{
|
||||
return RedirectToAction("Login");
|
||||
}
|
||||
|
||||
// ChangePasswordAsync changes the user password
|
||||
var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
|
||||
|
||||
// The new password did not meet the complexity rules or
|
||||
// the current password is incorrect. Add these errors to
|
||||
// the ModelState and rerender ChangePassword view
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, error.Description);
|
||||
}
|
||||
return Unauthorized(result);
|
||||
}
|
||||
|
||||
// Upon successfully changing the password refresh sign-in cookie
|
||||
await _signInManager.RefreshSignInAsync(user);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("Users")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> GetAllUsers()
|
||||
{
|
||||
List<UserViewModel> users = new List<UserViewModel>();
|
||||
|
||||
foreach (ApplicationUser rawUser in _userManager.Users)
|
||||
{
|
||||
UserViewModel user = new UserViewModel();
|
||||
user.Id = rawUser.Id;
|
||||
user.EmailAddress = rawUser.NormalizedEmail.ToLower();
|
||||
user.LockoutEnabled = rawUser.LockoutEnabled;
|
||||
user.LockoutEnd = rawUser.LockoutEnd;
|
||||
user.SecurityProfile = rawUser.SecurityProfile;
|
||||
|
||||
// get roles
|
||||
ApplicationUser? aUser = await _userManager.FindByIdAsync(rawUser.Id);
|
||||
if (aUser != null)
|
||||
{
|
||||
IList<string> aUserRoles = await _userManager.GetRolesAsync(aUser);
|
||||
user.Roles = aUserRoles.ToList();
|
||||
|
||||
user.Roles.Sort();
|
||||
}
|
||||
|
||||
users.Add(user);
|
||||
}
|
||||
|
||||
return Ok(users);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("Users")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> NewUser(RegisterViewModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
ApplicationUser user = new ApplicationUser
|
||||
{
|
||||
UserName = model.UserName,
|
||||
NormalizedUserName = model.UserName.ToUpper(),
|
||||
Email = model.Email,
|
||||
NormalizedEmail = model.Email.ToUpper()
|
||||
};
|
||||
var result = await _userManager.CreateAsync(user, model.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
// add new users to the player role
|
||||
await _userManager.AddToRoleAsync(user, "Player");
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "User Management", User.FindFirstValue(ClaimTypes.Name) + " created user " + model.Email + " with password.");
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("Users/{UserId}")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> GetUser(string UserId)
|
||||
{
|
||||
ApplicationUser? rawUser = await _userManager.FindByIdAsync(UserId);
|
||||
|
||||
if (rawUser != null)
|
||||
{
|
||||
UserViewModel user = new UserViewModel();
|
||||
user.Id = rawUser.Id;
|
||||
user.EmailAddress = rawUser.NormalizedEmail.ToLower();
|
||||
user.LockoutEnabled = rawUser.LockoutEnabled;
|
||||
user.LockoutEnd = rawUser.LockoutEnd;
|
||||
user.SecurityProfile = rawUser.SecurityProfile;
|
||||
|
||||
// get roles
|
||||
IList<string> aUserRoles = await _userManager.GetRolesAsync(rawUser);
|
||||
user.Roles = aUserRoles.ToList();
|
||||
|
||||
user.Roles.Sort();
|
||||
|
||||
return Ok(user);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("Users/{UserId}")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> DeleteUser(string UserId)
|
||||
{
|
||||
// get user
|
||||
ApplicationUser? user = await _userManager.FindByIdAsync(UserId);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
else
|
||||
{
|
||||
await _userManager.DeleteAsync(user);
|
||||
Logging.Log(Logging.LogType.Information, "User Management", User.FindFirstValue(ClaimTypes.Name) + " deleted user " + user.Email);
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("Users/{UserId}/Roles")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> SetUserRoles(string UserId, string RoleName)
|
||||
{
|
||||
ApplicationUser? user = await _userManager.FindByIdAsync(UserId);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
// get roles
|
||||
List<string> userRoles = (await _userManager.GetRolesAsync(user)).ToList();
|
||||
|
||||
// delete all roles
|
||||
foreach (string role in userRoles)
|
||||
{
|
||||
if ((new string[] { "Admin", "Gamer", "Player" }).Contains(role) )
|
||||
{
|
||||
await _userManager.RemoveFromRoleAsync(user, role);
|
||||
}
|
||||
}
|
||||
|
||||
// add only requested roles
|
||||
switch (RoleName)
|
||||
{
|
||||
case "Admin":
|
||||
await _userManager.AddToRoleAsync(user, "Admin");
|
||||
await _userManager.AddToRoleAsync(user, "Gamer");
|
||||
await _userManager.AddToRoleAsync(user, "Player");
|
||||
break;
|
||||
case "Gamer":
|
||||
await _userManager.AddToRoleAsync(user, "Gamer");
|
||||
await _userManager.AddToRoleAsync(user, "Player");
|
||||
break;
|
||||
case "Player":
|
||||
await _userManager.AddToRoleAsync(user, "Player");
|
||||
break;
|
||||
default:
|
||||
await _userManager.AddToRoleAsync(user, RoleName);
|
||||
break;
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("Users/{UserId}/SecurityProfile")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> SetUserSecurityProfile(string UserId, SecurityProfileViewModel securityProfile)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
ApplicationUser? user = await _userManager.FindByIdAsync(UserId);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
user.SecurityProfile = securityProfile;
|
||||
await _userManager.UpdateAsync(user);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("Users/{UserId}/Password")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> ResetPassword(string UserId, SetPasswordViewModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// we can reset the users password
|
||||
ApplicationUser? user = await _userManager.FindByIdAsync(UserId);
|
||||
if (user != null)
|
||||
{
|
||||
string resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);
|
||||
IdentityResult passwordChangeResult = await _userManager.ResetPasswordAsync(user, resetToken, model.NewPassword);
|
||||
if (passwordChangeResult.Succeeded == true)
|
||||
{
|
||||
return Ok(passwordChangeResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Ok(passwordChangeResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("Preferences")]
|
||||
public async Task<IActionResult> SetPreferences(List<UserPreferenceViewModel> model)
|
||||
{
|
||||
ApplicationUser? user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
else
|
||||
{
|
||||
user.UserPreferences = model;
|
||||
await _userManager.UpdateAsync(user);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Authentication;
|
||||
using gaseous_server.Classes;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
public class FilterController : Controller
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
|
||||
public FilterController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||
public async Task<IActionResult> FilterAsync()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
|
||||
return Ok(Filters.Filter(user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction, user.SecurityProfile.AgeRestrictionPolicy.IncludeUnrated));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public class LibraryController : Controller
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(List<GameLibrary.LibraryItem>), StatusCodes.Status200OK)]
|
||||
public ActionResult GetLibraries()
|
||||
{
|
||||
return Ok(GameLibrary.GetLibraries);
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet("{LibraryId}")]
|
||||
[ProducesResponseType(typeof(GameLibrary.LibraryItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult GetLibrary(int LibraryId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(GameLibrary.GetLibrary(LibraryId));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(GameLibrary.LibraryItem), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
||||
public ActionResult AddLibrary(string Name, string Path, long DefaultPlatformId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(GameLibrary.AddLibrary(Name, Path, DefaultPlatformId));
|
||||
}
|
||||
catch (GameLibrary.PathExists exPE)
|
||||
{
|
||||
return Conflict("Path already used in another library");
|
||||
}
|
||||
catch (GameLibrary.PathNotFound exPNF)
|
||||
{
|
||||
return NotFound("Path not found");
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpDelete("{LibraryId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult DelLibrary(int LibraryId)
|
||||
{
|
||||
try
|
||||
{
|
||||
GameLibrary.DeleteLibrary(LibraryId);
|
||||
return Ok();
|
||||
}
|
||||
catch (GameLibrary.CannotDeleteDefaultLibrary exCDDL)
|
||||
{
|
||||
return BadRequest(exCDDL.ToString());
|
||||
}
|
||||
catch (GameLibrary.LibraryNotFound exLNF)
|
||||
{
|
||||
return NotFound(exLNF.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public class LogsController : Controller
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public List<Logging.LogItem> Logs(Logging.LogsViewModel model)
|
||||
{
|
||||
return Logging.GetLogs(model);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,321 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Razor.Hosting;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.0")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
public class SystemController : Controller
|
||||
{
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public SystemInfo GetSystemStatus()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
SystemInfo ReturnValue = new SystemInfo();
|
||||
|
||||
// disk size
|
||||
List<SystemInfo.PathItem> Disks = new List<SystemInfo.PathItem>();
|
||||
foreach (GameLibrary.LibraryItem libraryItem in GameLibrary.GetLibraries)
|
||||
{
|
||||
Disks.Add(GetDisk(libraryItem.Path));
|
||||
}
|
||||
ReturnValue.Paths = Disks;
|
||||
|
||||
// database size
|
||||
string sql = "SELECT table_schema, SUM(data_length + index_length) FROM information_schema.tables WHERE table_schema = '" + Config.DatabaseConfiguration.DatabaseName + "'";
|
||||
DataTable dbResponse = db.ExecuteCMD(sql);
|
||||
ReturnValue.DatabaseSize = (long)(System.Decimal)dbResponse.Rows[0][1];
|
||||
|
||||
// platform statistics
|
||||
sql = "SELECT Platform.`name`, grc.Count, grs.Size FROM Platform INNER JOIN (SELECT Platform.`name` AS `Name`, SUM(grs.Size) AS Size FROM Platform JOIN Games_Roms AS grs ON (grs.PlatformId = Platform.Id) GROUP BY Platform.`name`) grs ON (grs.`Name` = Platform.`name`) INNER JOIN (SELECT Platform.`name` AS `Name`, COUNT(grc.Size) AS Count FROM Platform JOIN Games_Roms AS grc ON (grc.PlatformId = Platform.Id) GROUP BY Platform.`name`) grc ON (grc.`Name` = Platform.`name`) ORDER BY Platform.`name`;";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
ReturnValue.PlatformStatistics = new List<SystemInfo.PlatformStatisticsItem>();
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
SystemInfo.PlatformStatisticsItem platformStatisticsItem = new SystemInfo.PlatformStatisticsItem
|
||||
{
|
||||
Platform = (string)dr["name"],
|
||||
RomCount = (long)dr["Count"],
|
||||
TotalSize = (long)(System.Decimal)dr["Size"]
|
||||
};
|
||||
ReturnValue.PlatformStatistics.Add(platformStatisticsItem);
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("Version")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Version GetSystemVersion() {
|
||||
return Assembly.GetExecutingAssembly().GetName().Version;
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("VersionFile")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public FileContentResult GetSystemVersionAsFile() {
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
// get age ratings dictionary
|
||||
Dictionary<int, string> ClassificationBoardsStrings = new Dictionary<int, string>();
|
||||
foreach(IGDB.Models.AgeRatingCategory ageRatingCategory in Enum.GetValues(typeof(IGDB.Models.AgeRatingCategory)) )
|
||||
{
|
||||
ClassificationBoardsStrings.Add((int)ageRatingCategory, ageRatingCategory.ToString());
|
||||
}
|
||||
|
||||
Dictionary<int, string> AgeRatingsStrings = new Dictionary<int, string>();
|
||||
foreach(IGDB.Models.AgeRatingTitle ageRatingTitle in Enum.GetValues(typeof(IGDB.Models.AgeRatingTitle)) )
|
||||
{
|
||||
AgeRatingsStrings.Add((int)ageRatingTitle, ageRatingTitle.ToString());
|
||||
}
|
||||
|
||||
string ver = "var AppVersion = \"" + Assembly.GetExecutingAssembly().GetName().Version.ToString() + "\";" + Environment.NewLine +
|
||||
"var DBSchemaVersion = \"" + db.GetDatabaseSchemaVersion() + "\";" + Environment.NewLine +
|
||||
"var FirstRunStatus = " + Config.ReadSetting("FirstRunStatus", "0") + ";" + Environment.NewLine +
|
||||
"var AgeRatingBoardsStrings = " + JsonSerializer.Serialize(ClassificationBoardsStrings, new JsonSerializerOptions{
|
||||
WriteIndented = true
|
||||
}) + ";" + Environment.NewLine +
|
||||
"var AgeRatingStrings = " + JsonSerializer.Serialize(AgeRatingsStrings, new JsonSerializerOptions{
|
||||
WriteIndented = true
|
||||
}) + ";" + Environment.NewLine +
|
||||
"var AgeRatingGroups = " + JsonSerializer.Serialize(AgeGroups.AgeGroupingsFlat, new JsonSerializerOptions{
|
||||
WriteIndented = true
|
||||
}) + ";";
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(ver);
|
||||
return File(bytes, "text/javascript");
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("Settings/BackgroundTasks/Intervals")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public ActionResult GetBackgroundTasks()
|
||||
{
|
||||
Dictionary<string, BackgroundTaskItem> Intervals = new Dictionary<string, BackgroundTaskItem>();
|
||||
Intervals.Add(ProcessQueue.QueueItemType.SignatureIngestor.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.SignatureIngestor));
|
||||
Intervals.Add(ProcessQueue.QueueItemType.TitleIngestor.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.TitleIngestor));
|
||||
Intervals.Add(ProcessQueue.QueueItemType.MetadataRefresh.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.MetadataRefresh));
|
||||
Intervals.Add(ProcessQueue.QueueItemType.OrganiseLibrary.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.OrganiseLibrary));
|
||||
Intervals.Add(ProcessQueue.QueueItemType.LibraryScan.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.LibraryScan));
|
||||
Intervals.Add(ProcessQueue.QueueItemType.Rematcher.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.Rematcher));
|
||||
Intervals.Add(ProcessQueue.QueueItemType.Maintainer.ToString(), new BackgroundTaskItem(ProcessQueue.QueueItemType.Maintainer));
|
||||
|
||||
return Ok(Intervals);
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[Route("Settings/BackgroundTasks/Intervals")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public ActionResult SetBackgroundTasks(Dictionary<string, int> Intervals)
|
||||
{
|
||||
foreach (KeyValuePair<string, int> Interval in Intervals)
|
||||
{
|
||||
if (Enum.IsDefined(typeof(ProcessQueue.QueueItemType), Interval.Key))
|
||||
{
|
||||
try
|
||||
{
|
||||
BackgroundTaskItem taskItem = new BackgroundTaskItem(
|
||||
(ProcessQueue.QueueItemType)Enum.Parse(typeof(ProcessQueue.QueueItemType), Interval.Key)
|
||||
);
|
||||
|
||||
if (Interval.Value >= taskItem.MinimumAllowedValue)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + Interval.Key + " with new interval " + Interval.Value);
|
||||
|
||||
Config.SetSetting("Interval_" + Interval.Key, Interval.Value.ToString());
|
||||
|
||||
// update existing process
|
||||
foreach (ProcessQueue.QueueItem item in ProcessQueue.QueueItems)
|
||||
{
|
||||
if (item.ItemType.ToString().ToLower() == Interval.Key.ToLower())
|
||||
{
|
||||
item.Interval = Interval.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Warning, "Update Background Task", "Interval " + Interval.Value + " for task " + Interval.Key + " is below the minimum allowed value of " + taskItem.MinimumAllowedValue + ". Skipping.");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// task name not defined
|
||||
Logging.Log(Logging.LogType.Warning, "Update Background Task", "Task " + Interval.Key + " is not user definable. Skipping.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("Settings/System")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public ActionResult GetSystemSettings()
|
||||
{
|
||||
SystemSettingsModel systemSettingsModel = new SystemSettingsModel{
|
||||
AlwaysLogToDisk = Config.LoggingConfiguration.AlwaysLogToDisk,
|
||||
MinimumLogRetentionPeriod = Config.LoggingConfiguration.LogRetention
|
||||
};
|
||||
|
||||
return Ok(systemSettingsModel);
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.0")]
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[Route("Settings/System")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public ActionResult SetSystemSettings(SystemSettingsModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
Config.LoggingConfiguration.AlwaysLogToDisk = model.AlwaysLogToDisk;
|
||||
Config.LoggingConfiguration.LogRetention = model.MinimumLogRetentionPeriod;
|
||||
Config.UpdateConfig();
|
||||
}
|
||||
|
||||
return Ok(model);
|
||||
}
|
||||
|
||||
private SystemInfo.PathItem GetDisk(string Path)
|
||||
{
|
||||
SystemInfo.PathItem pathItem = new SystemInfo.PathItem {
|
||||
LibraryPath = Path,
|
||||
SpaceUsed = Common.DirSize(new DirectoryInfo(Path)),
|
||||
SpaceAvailable = new DriveInfo(Path).AvailableFreeSpace,
|
||||
TotalSpace = new DriveInfo(Path).TotalSize
|
||||
};
|
||||
|
||||
return pathItem;
|
||||
}
|
||||
|
||||
public class SystemInfo
|
||||
{
|
||||
public Version ApplicationVersion {
|
||||
get
|
||||
{
|
||||
return Assembly.GetExecutingAssembly().GetName().Version;
|
||||
}
|
||||
}
|
||||
public List<PathItem>? Paths { get; set; }
|
||||
public long DatabaseSize { get; set; }
|
||||
public List<PlatformStatisticsItem>? PlatformStatistics { get; set; }
|
||||
|
||||
public class PathItem
|
||||
{
|
||||
public string LibraryPath { get; set; }
|
||||
public long SpaceUsed { get; set; }
|
||||
public long SpaceAvailable { get; set; }
|
||||
public long TotalSpace { get; set; }
|
||||
}
|
||||
|
||||
public class PlatformStatisticsItem
|
||||
{
|
||||
public string Platform { get; set; }
|
||||
public long RomCount { get; set; }
|
||||
public long TotalSize { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BackgroundTaskItem
|
||||
{
|
||||
public BackgroundTaskItem(ProcessQueue.QueueItemType TaskName)
|
||||
{
|
||||
this.Task = TaskName.ToString();
|
||||
|
||||
switch (TaskName)
|
||||
{
|
||||
case ProcessQueue.QueueItemType.SignatureIngestor:
|
||||
this.DefaultInterval = 60;
|
||||
this.MinimumAllowedValue = 20;
|
||||
break;
|
||||
|
||||
case ProcessQueue.QueueItemType.TitleIngestor:
|
||||
this.DefaultInterval = 1;
|
||||
this.MinimumAllowedValue = 1;
|
||||
break;
|
||||
|
||||
case ProcessQueue.QueueItemType.MetadataRefresh:
|
||||
this.DefaultInterval = 360;
|
||||
this.MinimumAllowedValue = 360;
|
||||
break;
|
||||
|
||||
case ProcessQueue.QueueItemType.OrganiseLibrary:
|
||||
this.DefaultInterval = 1440;
|
||||
this.MinimumAllowedValue = 120;
|
||||
break;
|
||||
|
||||
case ProcessQueue.QueueItemType.LibraryScan:
|
||||
this.DefaultInterval = 1440;
|
||||
this.MinimumAllowedValue = 120;
|
||||
break;
|
||||
|
||||
case ProcessQueue.QueueItemType.Rematcher:
|
||||
this.DefaultInterval = 1440;
|
||||
this.MinimumAllowedValue = 360;
|
||||
break;
|
||||
|
||||
case ProcessQueue.QueueItemType.Maintainer:
|
||||
this.DefaultInterval = 10080;
|
||||
this.MinimumAllowedValue = 10080;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception("Invalid task");
|
||||
}
|
||||
}
|
||||
|
||||
public string Task { get; set; }
|
||||
public int Interval {
|
||||
get
|
||||
{
|
||||
return int.Parse(Config.ReadSetting("Interval_" + Task, DefaultInterval.ToString()));
|
||||
}
|
||||
}
|
||||
public int DefaultInterval { get; set; }
|
||||
public int MinimumAllowedValue { get; set; }
|
||||
}
|
||||
|
||||
public class SystemSettingsModel
|
||||
{
|
||||
public bool AlwaysLogToDisk { get; set; }
|
||||
public int MinimumLogRetentionPeriod { get; set; }
|
||||
}
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Authentication;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.1")]
|
||||
[Authorize]
|
||||
public class FirstSetupController : Controller
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
|
||||
public FirstSetupController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[Route("0")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult> CreateAdminAccount(Authentication.RegisterViewModel model)
|
||||
{
|
||||
if (Config.ReadSetting("FirstRunStatus", "0") == "0")
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
ApplicationUser user = new ApplicationUser
|
||||
{
|
||||
UserName = model.UserName,
|
||||
NormalizedUserName = model.UserName.ToUpper(),
|
||||
Email = model.Email,
|
||||
NormalizedEmail = model.Email.ToUpper(),
|
||||
SecurityProfile = new SecurityProfileViewModel()
|
||||
};
|
||||
Logging.Log(Logging.LogType.Information, "First Run", "Creating new account " + model.Email);
|
||||
var result = await _userManager.CreateAsync(user, model.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "First Run", "Creation of " + model.Email + " successful.");
|
||||
Logging.Log(Logging.LogType.Information, "First Run", "Adding Player role to " + model.Email);
|
||||
await _userManager.AddToRoleAsync(user, "Player");
|
||||
Logging.Log(Logging.LogType.Information, "First Run", "Adding Gamer role to " + model.Email);
|
||||
await _userManager.AddToRoleAsync(user, "Gamer");
|
||||
Logging.Log(Logging.LogType.Information, "First Run", "Adding Admin role to " + model.Email);
|
||||
await _userManager.AddToRoleAsync(user, "Admin");
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "First Run", "Signing in as " + model.Email);
|
||||
await _signInManager.SignInAsync(user, isPersistent: true);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "First Run", "Setting first run state to 1");
|
||||
Config.SetSetting("FirstRunStatus", "1");
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
return Problem(ModelState.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,500 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Authentication;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using static gaseous_server.Classes.Metadata.AgeRatings;
|
||||
|
||||
namespace gaseous_server.Controllers.v1_1
|
||||
{
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.1")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class GamesController: ControllerBase
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
|
||||
public GamesController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(GameReturnPackage), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> Game_v1_1(GameSearchModel model, int pageNumber = 0, int pageSize = 0)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
// apply security profile filtering
|
||||
if (model.GameAgeRating.AgeGroupings.Count == 0)
|
||||
{
|
||||
model.GameAgeRating.AgeGroupings.Add(AgeGroups.AgeRestrictionGroupings.Adult);
|
||||
model.GameAgeRating.AgeGroupings.Add(AgeGroups.AgeRestrictionGroupings.Mature);
|
||||
model.GameAgeRating.AgeGroupings.Add(AgeGroups.AgeRestrictionGroupings.Teen);
|
||||
model.GameAgeRating.AgeGroupings.Add(AgeGroups.AgeRestrictionGroupings.Child);
|
||||
model.GameAgeRating.IncludeUnrated = true;
|
||||
}
|
||||
List<AgeGroups.AgeRestrictionGroupings> RemoveAgeGroups = new List<AgeGroups.AgeRestrictionGroupings>();
|
||||
switch (user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction)
|
||||
{
|
||||
case AgeGroups.AgeRestrictionGroupings.Adult:
|
||||
break;
|
||||
case AgeGroups.AgeRestrictionGroupings.Mature:
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Adult);
|
||||
break;
|
||||
case AgeGroups.AgeRestrictionGroupings.Teen:
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Adult);
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Mature);
|
||||
break;
|
||||
case AgeGroups.AgeRestrictionGroupings.Child:
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Adult);
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Mature);
|
||||
RemoveAgeGroups.Add(AgeGroups.AgeRestrictionGroupings.Teen);
|
||||
break;
|
||||
}
|
||||
foreach (AgeGroups.AgeRestrictionGroupings RemoveAgeGroup in RemoveAgeGroups)
|
||||
{
|
||||
if (model.GameAgeRating.AgeGroupings.Contains(RemoveAgeGroup))
|
||||
{
|
||||
model.GameAgeRating.AgeGroupings.Remove(RemoveAgeGroup);
|
||||
}
|
||||
}
|
||||
if (user.SecurityProfile.AgeRestrictionPolicy.IncludeUnrated == false)
|
||||
{
|
||||
model.GameAgeRating.IncludeUnrated = false;
|
||||
}
|
||||
|
||||
return Ok(GetGames(model, pageNumber, pageSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
}
|
||||
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Route("{GameId}/Related")]
|
||||
[ProducesResponseType(typeof(GameReturnPackage), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GameRelated(long GameId)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
string IncludeUnrated = "";
|
||||
if (user.SecurityProfile.AgeRestrictionPolicy.IncludeUnrated == true) {
|
||||
IncludeUnrated = " OR view_Games.AgeGroupId IS NULL";
|
||||
}
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT view_Games.Id, view_Games.AgeGroupId, Relation_Game_SimilarGames.SimilarGamesId FROM view_Games JOIN Relation_Game_SimilarGames ON view_Games.Id = Relation_Game_SimilarGames.GameId AND Relation_Game_SimilarGames.SimilarGamesId IN (SELECT Id FROM view_Games) WHERE view_Games.Id = @id AND (view_Games.AgeGroupId <= @agegroupid" + IncludeUnrated + ")";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("id", GameId);
|
||||
dbDict.Add("agegroupid", (int)user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction);
|
||||
|
||||
List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>();
|
||||
|
||||
DataTable dbResponse = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
RetVal.Add(Classes.Metadata.Games.GetGame((long)dr["SimilarGamesId"], false, false, false));
|
||||
}
|
||||
|
||||
GameReturnPackage gameReturn = new GameReturnPackage(RetVal.Count, RetVal);
|
||||
|
||||
return Ok(gameReturn);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
}
|
||||
|
||||
public class GameSearchModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public List<string> Platform { get; set; }
|
||||
public List<string> Genre { get; set; }
|
||||
public List<string> GameMode { get; set; }
|
||||
public List<string> PlayerPerspective { get; set; }
|
||||
public List<string> Theme { get; set; }
|
||||
public GameRatingItem GameRating { get; set; } = new GameRatingItem();
|
||||
public GameAgeRatingItem GameAgeRating { get; set; } = new GameAgeRatingItem();
|
||||
public GameSortingItem Sorting { get; set; } = new GameSortingItem();
|
||||
|
||||
|
||||
public class GameRatingItem
|
||||
{
|
||||
public int MinimumRating { get; set; } = -1;
|
||||
public int MinimumRatingCount { get; set; } = -1;
|
||||
public int MaximumRating { get; set; } = -1;
|
||||
public int MaximumRatingCount { get; set; } = -1;
|
||||
public bool IncludeUnrated { get; set; } = false;
|
||||
}
|
||||
|
||||
public class GameAgeRatingItem
|
||||
{
|
||||
public List<AgeGroups.AgeRestrictionGroupings> AgeGroupings { get; set; } = new List<AgeGroups.AgeRestrictionGroupings>{
|
||||
AgeGroups.AgeRestrictionGroupings.Child,
|
||||
AgeGroups.AgeRestrictionGroupings.Teen,
|
||||
AgeGroups.AgeRestrictionGroupings.Mature,
|
||||
AgeGroups.AgeRestrictionGroupings.Adult
|
||||
};
|
||||
public bool IncludeUnrated { get; set; } = true;
|
||||
}
|
||||
|
||||
public class GameSortingItem
|
||||
{
|
||||
public SortField SortBy { get; set; } = SortField.NameThe;
|
||||
public bool SortAscending { get; set; } = true;
|
||||
|
||||
public enum SortField
|
||||
{
|
||||
Name,
|
||||
NameThe,
|
||||
Rating,
|
||||
RatingCount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static GameReturnPackage GetGames(GameSearchModel model, int pageNumber = 0, int pageSize = 0)
|
||||
{
|
||||
string whereClause = "";
|
||||
string havingClause = "";
|
||||
Dictionary<string, object> whereParams = new Dictionary<string, object>();
|
||||
|
||||
List<string> whereClauses = new List<string>();
|
||||
List<string> havingClauses = new List<string>();
|
||||
|
||||
string tempVal = "";
|
||||
|
||||
string nameWhereClause = "";
|
||||
if (model.Name.Length > 0)
|
||||
{
|
||||
// tempVal = "`Name` LIKE @Name";
|
||||
// whereParams.Add("@Name", "%" + model.Name + "%");
|
||||
// havingClauses.Add(tempVal);
|
||||
nameWhereClause = "WHERE (MATCH(Game.`Name`) AGAINST (@Name IN BOOLEAN MODE) OR MATCH(AlternativeName.`Name`) AGAINST (@Name IN BOOLEAN MODE))";
|
||||
whereParams.Add("@Name", "(*" + model.Name + "*) (" + model.Name + ") ");
|
||||
}
|
||||
|
||||
if (model.GameRating != null)
|
||||
{
|
||||
List<string> ratingClauses = new List<string>();
|
||||
if (model.GameRating.MinimumRating != -1)
|
||||
{
|
||||
string ratingTempMinVal = "totalRating >= @totalMinRating";
|
||||
whereParams.Add("@totalMinRating", model.GameRating.MinimumRating);
|
||||
ratingClauses.Add(ratingTempMinVal);
|
||||
}
|
||||
|
||||
if (model.GameRating.MaximumRating != -1)
|
||||
{
|
||||
string ratingTempMaxVal = "totalRating <= @totalMaxRating";
|
||||
whereParams.Add("@totalMaxRating", model.GameRating.MaximumRating);
|
||||
ratingClauses.Add(ratingTempMaxVal);
|
||||
}
|
||||
|
||||
if (model.GameRating.MinimumRatingCount != -1)
|
||||
{
|
||||
string ratingTempMinCountVal = "totalRatingCount >= @totalMinRatingCount";
|
||||
whereParams.Add("@totalMinRatingCount", model.GameRating.MinimumRatingCount);
|
||||
ratingClauses.Add(ratingTempMinCountVal);
|
||||
}
|
||||
|
||||
if (model.GameRating.MaximumRatingCount != -1)
|
||||
{
|
||||
string ratingTempMaxCountVal = "totalRatingCount <= @totalMaxRatingCount";
|
||||
whereParams.Add("@totalMaxRatingCount", model.GameRating.MaximumRatingCount);
|
||||
ratingClauses.Add(ratingTempMaxCountVal);
|
||||
}
|
||||
|
||||
// generate rating sub clause
|
||||
string ratingClauseValue = "";
|
||||
if (ratingClauses.Count > 0)
|
||||
{
|
||||
foreach (string ratingClause in ratingClauses)
|
||||
{
|
||||
if (ratingClauseValue.Length > 0)
|
||||
{
|
||||
ratingClauseValue += " AND ";
|
||||
}
|
||||
ratingClauseValue += ratingClause;
|
||||
}
|
||||
}
|
||||
|
||||
string unratedClause = "";
|
||||
if (model.GameRating.IncludeUnrated == true)
|
||||
{
|
||||
unratedClause = "totalRating IS NULL";
|
||||
}
|
||||
|
||||
if (ratingClauseValue.Length > 0)
|
||||
{
|
||||
if (unratedClause.Length > 0)
|
||||
{
|
||||
havingClauses.Add("((" + ratingClauseValue + ") OR " + unratedClause + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
havingClauses.Add("(" + ratingClauseValue + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string platformWhereClause = "";
|
||||
if (model.Platform.Count > 0)
|
||||
{
|
||||
tempVal = " AND Games_Roms.PlatformId IN (";
|
||||
for (int i = 0; i < model.Platform.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += ", ";
|
||||
}
|
||||
string platformLabel = "@Platform" + i;
|
||||
tempVal += platformLabel;
|
||||
whereParams.Add(platformLabel, model.Platform[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
//whereClauses.Add(tempVal);
|
||||
platformWhereClause = tempVal;
|
||||
}
|
||||
|
||||
if (model.Genre.Count > 0)
|
||||
{
|
||||
tempVal = "Relation_Game_Genres.GenresId IN (";
|
||||
for (int i = 0; i < model.Genre.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string genreLabel = "@Genre" + i;
|
||||
tempVal += genreLabel;
|
||||
whereParams.Add(genreLabel, model.Genre[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
if (model.GameMode.Count > 0)
|
||||
{
|
||||
tempVal = "Relation_Game_GameModes.GameModesId IN (";
|
||||
for (int i = 0; i < model.GameMode.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string gameModeLabel = "@GameMode" + i;
|
||||
tempVal += gameModeLabel;
|
||||
whereParams.Add(gameModeLabel, model.GameMode[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
if (model.PlayerPerspective.Count > 0)
|
||||
{
|
||||
tempVal = "Relation_Game_PlayerPerspectives.PlayerPerspectivesId IN (";
|
||||
for (int i = 0; i < model.PlayerPerspective.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string playerPerspectiveLabel = "@PlayerPerspective" + i;
|
||||
tempVal += playerPerspectiveLabel;
|
||||
whereParams.Add(playerPerspectiveLabel, model.PlayerPerspective[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
if (model.Theme.Count > 0)
|
||||
{
|
||||
tempVal = "Relation_Game_Themes.ThemesId IN (";
|
||||
for (int i = 0; i < model.Theme.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string themeLabel = "@Theme" + i;
|
||||
tempVal += themeLabel;
|
||||
whereParams.Add(themeLabel, model.Theme[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
if (model.GameAgeRating != null)
|
||||
{
|
||||
if (model.GameAgeRating.AgeGroupings.Count > 0)
|
||||
{
|
||||
tempVal = "(Game.AgeGroupId IN (";
|
||||
for (int i = 0; i < model.GameAgeRating.AgeGroupings.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += ", ";
|
||||
}
|
||||
string themeLabel = "@Rating" + i;
|
||||
tempVal += themeLabel;
|
||||
whereParams.Add(themeLabel, model.GameAgeRating.AgeGroupings[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
|
||||
if (model.GameAgeRating.IncludeUnrated == true)
|
||||
{
|
||||
tempVal += " OR Game.AgeGroupId IS NULL";
|
||||
}
|
||||
tempVal += ")";
|
||||
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
}
|
||||
|
||||
// build where clause
|
||||
if (whereClauses.Count > 0)
|
||||
{
|
||||
whereClause = "WHERE ";
|
||||
for (int i = 0; i < whereClauses.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
whereClause += " AND ";
|
||||
}
|
||||
whereClause += whereClauses[i];
|
||||
}
|
||||
}
|
||||
|
||||
// build having clause
|
||||
if (havingClauses.Count > 0)
|
||||
{
|
||||
havingClause = "HAVING ";
|
||||
for (int i = 0; i < havingClauses.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
havingClause += " AND ";
|
||||
}
|
||||
havingClause += havingClauses[i];
|
||||
}
|
||||
}
|
||||
|
||||
// order by clause
|
||||
string orderByField = "NameThe";
|
||||
string orderByOrder = "ASC";
|
||||
if (model.Sorting != null)
|
||||
{
|
||||
switch(model.Sorting.SortBy)
|
||||
{
|
||||
case GameSearchModel.GameSortingItem.SortField.NameThe:
|
||||
orderByField = "NameThe";
|
||||
break;
|
||||
case GameSearchModel.GameSortingItem.SortField.Name:
|
||||
orderByField = "Name";
|
||||
break;
|
||||
case GameSearchModel.GameSortingItem.SortField.Rating:
|
||||
orderByField = "TotalRating";
|
||||
break;
|
||||
case GameSearchModel.GameSortingItem.SortField.RatingCount:
|
||||
orderByField = "TotalRatingCount";
|
||||
break;
|
||||
default:
|
||||
orderByField = "NameThe";
|
||||
break;
|
||||
}
|
||||
|
||||
if (model.Sorting.SortAscending == true)
|
||||
{
|
||||
orderByOrder = "ASC";
|
||||
}
|
||||
else
|
||||
{
|
||||
orderByOrder = "DESC";
|
||||
}
|
||||
}
|
||||
string orderByClause = "ORDER BY `" + orderByField + "` " + orderByOrder;
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
//string sql = "SELECT DISTINCT view_Games.* FROM view_Games LEFT JOIN Relation_Game_Platforms ON view_Games.Id = Relation_Game_Platforms.GameId AND (Relation_Game_Platforms.PlatformsId IN (SELECT DISTINCT PlatformId FROM Games_Roms WHERE Games_Roms.GameId = view_Games.Id)) LEFT JOIN Relation_Game_Genres ON view_Games.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON view_Games.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON view_Games.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON view_Games.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
||||
|
||||
string sql = "SELECT DISTINCT Game.Id, Game.`Name`, Game.NameThe, Game.PlatformId, Game.TotalRating, Game.TotalRatingCount, Game.Cover, Game.Artworks, Game.FirstReleaseDate, Game.Category, Game.ParentGame, Game.AgeRatings, Game.AgeGroupId, Game.RomCount FROM (SELECT DISTINCT Game.*, CASE WHEN Game.`Name` LIKE 'The %' THEN CONCAT(TRIM(SUBSTR(Game.`Name` FROM 4)), ', The') ELSE Game.`Name` END AS NameThe, Games_Roms.PlatformId, AgeGroup.AgeGroupId, COUNT(Games_Roms.Id) AS RomCount FROM Game LEFT JOIN AgeGroup ON Game.Id = AgeGroup.GameId LEFT JOIN Games_Roms ON Game.Id = Games_Roms.GameId" + platformWhereClause + " LEFT JOIN AlternativeName ON Game.Id = AlternativeName.Game " + nameWhereClause + " GROUP BY Game.Id HAVING RomCount > 0) Game LEFT JOIN Relation_Game_Genres ON Game.Id = Relation_Game_Genres.GameId LEFT JOIN Relation_Game_GameModes ON Game.Id = Relation_Game_GameModes.GameId LEFT JOIN Relation_Game_PlayerPerspectives ON Game.Id = Relation_Game_PlayerPerspectives.GameId LEFT JOIN Relation_Game_Themes ON Game.Id = Relation_Game_Themes.GameId " + whereClause + " " + havingClause + " " + orderByClause;
|
||||
|
||||
List<IGDB.Models.Game> RetVal = new List<IGDB.Models.Game>();
|
||||
|
||||
DataTable dbResponse = db.ExecuteCMD(sql, whereParams);
|
||||
|
||||
// get count
|
||||
int RecordCount = dbResponse.Rows.Count;
|
||||
|
||||
// compile data for return
|
||||
int pageOffset = pageSize * (pageNumber - 1);
|
||||
for (int i = pageOffset; i < dbResponse.Rows.Count; i++)
|
||||
{
|
||||
if (i >= (pageOffset + pageSize))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Game retGame = Storage.BuildCacheObject<Game>(new Game() , dbResponse.Rows[i]);
|
||||
RetVal.Add(retGame);
|
||||
}
|
||||
|
||||
GameReturnPackage gameReturn = new GameReturnPackage(RecordCount, RetVal);
|
||||
|
||||
return gameReturn;
|
||||
}
|
||||
|
||||
public class GameReturnPackage
|
||||
{
|
||||
public GameReturnPackage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GameReturnPackage(int Count, List<Game> Games)
|
||||
{
|
||||
this.Count = Count;
|
||||
|
||||
List<Games.MinimalGameItem> minimalGames = new List<Games.MinimalGameItem>();
|
||||
foreach (Game game in Games)
|
||||
{
|
||||
minimalGames.Add(new Classes.Metadata.Games.MinimalGameItem(game));
|
||||
}
|
||||
|
||||
this.Games = minimalGames;
|
||||
}
|
||||
|
||||
public int Count { get; set; }
|
||||
public List<Games.MinimalGameItem> Games { get; set; } = new List<Games.MinimalGameItem>();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using IGDB.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using static gaseous_server.Classes.Metadata.AgeRatings;
|
||||
|
||||
namespace gaseous_server.Controllers.v1_1
|
||||
{
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[ApiVersion("1.1")]
|
||||
[ApiController]
|
||||
public class RatingsController: ControllerBase
|
||||
{
|
||||
[MapToApiVersion("1.1")]
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
[Route("Images/{RatingBoard}/{RatingId}/image.svg")]
|
||||
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult RatingsImageById(string RatingBoard, int RatingId)
|
||||
{
|
||||
IGDB.Models.AgeRatingTitle RatingTitle = (AgeRatingTitle)RatingId;
|
||||
|
||||
string resourceName = "gaseous_server.Assets.Ratings." + RatingBoard + "." + RatingTitle.ToString() + ".svg";
|
||||
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
string[] resources = assembly.GetManifestResourceNames();
|
||||
if (resources.Contains(resourceName))
|
||||
{
|
||||
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||
using (StreamReader reader = new StreamReader(stream))
|
||||
{
|
||||
byte[] filedata = new byte[stream.Length];
|
||||
stream.Read(filedata, 0, filedata.Length);
|
||||
|
||||
string filename = RatingBoard + "-" + RatingTitle.ToString() + ".svg";
|
||||
string contentType = "image/svg+xml";
|
||||
|
||||
var cd = new System.Net.Mime.ContentDisposition
|
||||
{
|
||||
FileName = filename,
|
||||
Inline = true,
|
||||
};
|
||||
|
||||
Response.Headers.Add("Content-Disposition", cd.ToString());
|
||||
Response.Headers.Add("Cache-Control", "public, max-age=604800");
|
||||
|
||||
return File(filedata, contentType);
|
||||
}
|
||||
}
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,10 +4,10 @@ using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Web;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
using gaseous_server.Controllers;
|
||||
using gaseous_tools;
|
||||
using IGDB.Models;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@@ -72,9 +72,6 @@ namespace gaseous_server.Models
|
||||
|
||||
foreach (PlatformMapItem mapItem in platforms)
|
||||
{
|
||||
// get the IGDB platform data
|
||||
Platform platform = Platforms.GetPlatform(mapItem.IGDBId);
|
||||
|
||||
try
|
||||
{
|
||||
PlatformMapItem item = GetPlatformMap(mapItem.IGDBId);
|
||||
@@ -96,7 +93,7 @@ namespace gaseous_server.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT * FROM PlatformMap";
|
||||
DataTable data = db.ExecuteCMD(sql);
|
||||
|
||||
@@ -128,7 +125,7 @@ namespace gaseous_server.Models
|
||||
}
|
||||
else
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
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);
|
||||
@@ -151,24 +148,24 @@ namespace gaseous_server.Models
|
||||
|
||||
public static void WritePlatformMap(PlatformMapItem item, bool Update, bool AllowAvailableEmulatorOverwrite)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
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, AvailableWebEmulators) VALUES (@Id, @RetroPieDirectoryName, @WebEmulator_Type, @WebEmulator_Core, @AvailableWebEmulators);";
|
||||
sql = "INSERT INTO PlatformMap (Id, RetroPieDirectoryName, WebEmulator_Type, WebEmulator_Core, AvailableWebEmulators) VALUES (@Id, @RetroPieDirectoryName, @WebEmulator_Type, @WebEmulator_Core, @AvailableWebEmulators)";
|
||||
}
|
||||
else
|
||||
{
|
||||
// update
|
||||
if (AllowAvailableEmulatorOverwrite == true)
|
||||
{
|
||||
sql = "UPDATE PlatformMap SET RetroPieDirectoryName=@RetroPieDirectoryName, WebEmulator_Type=@WebEmulator_Type, WebEmulator_Core=@WebEmulator_Core, AvailableWebEmulators=@AvailableWebEmulators WHERE Id = @Id; ";
|
||||
sql = "UPDATE PlatformMap SET RetroPieDirectoryName=@RetroPieDirectoryName, WebEmulator_Type=@WebEmulator_Type, WebEmulator_Core=@WebEmulator_Core, AvailableWebEmulators=@AvailableWebEmulators WHERE Id = @Id";
|
||||
}
|
||||
else
|
||||
{
|
||||
sql = "UPDATE PlatformMap SET RetroPieDirectoryName=@RetroPieDirectoryName, WebEmulator_Type=@WebEmulator_Type, WebEmulator_Core=@WebEmulator_Core WHERE Id = @Id;";
|
||||
sql = "UPDATE PlatformMap SET RetroPieDirectoryName=@RetroPieDirectoryName, WebEmulator_Type=@WebEmulator_Type, WebEmulator_Core=@WebEmulator_Core WHERE Id = @Id";
|
||||
}
|
||||
}
|
||||
dbDict.Add("Id", item.IGDBId);
|
||||
@@ -201,7 +198,7 @@ namespace gaseous_server.Models
|
||||
sql = "INSERT INTO PlatformMap_AlternateNames (Id, Name) VALUES (@Id, @Name);";
|
||||
dbDict.Clear();
|
||||
dbDict.Add("Id", item.IGDBId);
|
||||
dbDict.Add("Name", HttpUtility.HtmlDecode(alternateName));
|
||||
dbDict.Add("Name", alternateName);
|
||||
db.ExecuteCMD(sql, dbDict);
|
||||
}
|
||||
}
|
||||
@@ -248,7 +245,7 @@ namespace gaseous_server.Models
|
||||
static PlatformMapItem BuildPlatformMapItem(DataRow row)
|
||||
{
|
||||
long IGDBId = (long)row["Id"];
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
string sql = "";
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using gaseous_signature_parser.models.RomSignatureObject;
|
||||
|
||||
namespace gaseous_server.Models
|
||||
{
|
||||
@@ -129,11 +128,49 @@ namespace gaseous_server.Models
|
||||
|
||||
public List<KeyValuePair<string, object>> Attributes { get; set; } = new List<KeyValuePair<string, object>>();
|
||||
|
||||
public RomSignatureObject.Game.Rom.RomTypes RomType { get; set; }
|
||||
public RomTypes RomType { get; set; }
|
||||
public string? RomTypeMedia { get; set; }
|
||||
public string? MediaLabel { get; set; }
|
||||
|
||||
public RomSignatureObject.Game.Rom.SignatureSourceType SignatureSource { get; set; }
|
||||
public gaseous_signature_parser.models.RomSignatureObject.RomSignatureObject.Game.Rom.SignatureSourceType SignatureSource { get; set; }
|
||||
|
||||
public enum RomTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Media type is unknown
|
||||
/// </summary>
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Optical media
|
||||
/// </summary>
|
||||
Disc = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Magnetic media
|
||||
/// </summary>
|
||||
Disk = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Individual files
|
||||
/// </summary>
|
||||
File = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Individual pars
|
||||
/// </summary>
|
||||
Part = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Tape base media
|
||||
/// </summary>
|
||||
Tape = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Side of the media
|
||||
/// </summary>
|
||||
Side = 6
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public int Score
|
||||
|
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_tools;
|
||||
|
||||
namespace gaseous_server.Models
|
||||
{
|
||||
@@ -14,7 +14,7 @@ namespace gaseous_server.Models
|
||||
|
||||
public Signatures_Status()
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
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);
|
||||
|
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel.Design.Serialization;
|
||||
using System.Data;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_tools;
|
||||
|
||||
namespace gaseous_server
|
||||
{
|
||||
@@ -15,7 +13,7 @@ namespace gaseous_server
|
||||
{
|
||||
_ItemType = ItemType;
|
||||
_ItemState = QueueItemState.NeverStarted;
|
||||
_LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ"))).AddMinutes(-5);
|
||||
_LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ")));
|
||||
_Interval = ExecutionInterval;
|
||||
_AllowManualStart = AllowManualStart;
|
||||
_RemoveWhenStopped = RemoveWhenStopped;
|
||||
@@ -25,7 +23,7 @@ namespace gaseous_server
|
||||
{
|
||||
_ItemType = ItemType;
|
||||
_ItemState = QueueItemState.NeverStarted;
|
||||
_LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ"))).AddMinutes(-5);
|
||||
_LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ")));
|
||||
_Interval = ExecutionInterval;
|
||||
_AllowManualStart = AllowManualStart;
|
||||
_RemoveWhenStopped = RemoveWhenStopped;
|
||||
@@ -35,7 +33,6 @@ namespace gaseous_server
|
||||
private QueueItemType _ItemType = QueueItemType.NotConfigured;
|
||||
private QueueItemState _ItemState = QueueItemState.NeverStarted;
|
||||
private DateTime _LastRunTime = DateTime.UtcNow;
|
||||
private double _LastRunDuration = 0;
|
||||
private DateTime _LastFinishTime
|
||||
{
|
||||
get
|
||||
@@ -58,32 +55,19 @@ namespace gaseous_server
|
||||
private bool _AllowManualStart = true;
|
||||
private bool _RemoveWhenStopped = false;
|
||||
private bool _IsBlocked = false;
|
||||
private string _CorrelationId = "";
|
||||
private List<QueueItemType> _Blocks = new List<QueueItemType>();
|
||||
|
||||
public QueueItemType ItemType => _ItemType;
|
||||
public QueueItemState ItemState => _ItemState;
|
||||
public DateTime LastRunTime => _LastRunTime;
|
||||
public DateTime LastFinishTime => _LastFinishTime;
|
||||
public double LastRunDuration => _LastRunDuration;
|
||||
public DateTime NextRunTime
|
||||
{
|
||||
public DateTime NextRunTime {
|
||||
get
|
||||
{
|
||||
return LastRunTime.AddMinutes(Interval);
|
||||
}
|
||||
}
|
||||
public int Interval
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Interval;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Interval = value;
|
||||
}
|
||||
}
|
||||
public int Interval => _Interval;
|
||||
public string LastResult => _LastResult;
|
||||
public string? LastError => _LastError;
|
||||
public bool Force => _ForceExecute;
|
||||
@@ -91,9 +75,6 @@ namespace gaseous_server
|
||||
public bool RemoveWhenStopped => _RemoveWhenStopped;
|
||||
public bool IsBlocked => _IsBlocked;
|
||||
public object? Options { get; set; } = null;
|
||||
public string CurrentState { get; set; } = "";
|
||||
public string CurrentStateProgress { get; set; } = "";
|
||||
public string CorrelationId => _CorrelationId;
|
||||
public List<QueueItemType> Blocks => _Blocks;
|
||||
|
||||
public void Execute()
|
||||
@@ -108,15 +89,7 @@ namespace gaseous_server
|
||||
_LastResult = "";
|
||||
_LastError = null;
|
||||
|
||||
// set the correlation id
|
||||
Guid correlationId = Guid.NewGuid();
|
||||
_CorrelationId = correlationId.ToString();
|
||||
CallContext.SetData("CorrelationId", correlationId);
|
||||
CallContext.SetData("CallingProcess", _ItemType.ToString());
|
||||
CallContext.SetData("CallingUser", "System");
|
||||
|
||||
// log the start
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Executing " + _ItemType + " with correlation id " + _CorrelationId);
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Executing " + _ItemType);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -124,10 +97,7 @@ namespace gaseous_server
|
||||
{
|
||||
case QueueItemType.SignatureIngestor:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Signature Ingestor");
|
||||
SignatureIngestors.XML.XMLIngestor tIngest = new SignatureIngestors.XML.XMLIngestor
|
||||
{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
SignatureIngestors.XML.XMLIngestor tIngest = new SignatureIngestors.XML.XMLIngestor();
|
||||
|
||||
Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing TOSEC files");
|
||||
tIngest.Import(Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, "TOSEC"), gaseous_signature_parser.parser.SignatureParser.TOSEC);
|
||||
@@ -144,13 +114,7 @@ namespace gaseous_server
|
||||
|
||||
case QueueItemType.TitleIngestor:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Title Ingestor");
|
||||
Classes.ImportGames importGames = new Classes.ImportGames(Config.LibraryConfiguration.LibraryImportDirectory)
|
||||
{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
|
||||
// clean up
|
||||
Classes.ImportGame.DeleteOrphanedDirectories(Config.LibraryConfiguration.LibraryImportDirectory);
|
||||
Classes.ImportGames importGames = new Classes.ImportGames(Config.LibraryConfiguration.LibraryImportDirectory);
|
||||
|
||||
_SaveLastRunTime = true;
|
||||
|
||||
@@ -158,11 +122,7 @@ namespace gaseous_server
|
||||
|
||||
case QueueItemType.MetadataRefresh:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Metadata Refresher");
|
||||
Classes.MetadataManagement metadataManagement = new MetadataManagement
|
||||
{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
metadataManagement.RefreshMetadata(_ForceExecute);
|
||||
Classes.MetadataManagement.RefreshMetadata(true);
|
||||
|
||||
_SaveLastRunTime = true;
|
||||
|
||||
@@ -178,23 +138,7 @@ namespace gaseous_server
|
||||
|
||||
case QueueItemType.LibraryScan:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Library Scanner");
|
||||
Classes.ImportGame import = new ImportGame
|
||||
{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
import.LibraryScan();
|
||||
|
||||
_SaveLastRunTime = true;
|
||||
|
||||
break;
|
||||
|
||||
case QueueItemType.Rematcher:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Rematch");
|
||||
Classes.ImportGame importRematch = new ImportGame
|
||||
{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
importRematch.Rematcher(_ForceExecute);
|
||||
Classes.ImportGame.LibraryScan();
|
||||
|
||||
_SaveLastRunTime = true;
|
||||
|
||||
@@ -205,22 +149,9 @@ namespace gaseous_server
|
||||
Classes.Collections.CompileCollections((long)Options);
|
||||
break;
|
||||
|
||||
case QueueItemType.MediaGroupCompiler:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Media Group Compiler");
|
||||
Classes.RomMediaGroup.CompileMediaGroup((long)Options);
|
||||
break;
|
||||
|
||||
case QueueItemType.BackgroundDatabaseUpgrade:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Background Upgrade");
|
||||
DatabaseMigration.UpgradeScriptBackgroundTasks();
|
||||
break;
|
||||
|
||||
case QueueItemType.Maintainer:
|
||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Maintenance");
|
||||
Classes.Maintenance maintenance = new Maintenance{
|
||||
CallingQueueItem = this
|
||||
};
|
||||
maintenance.RunMaintenance();
|
||||
gaseous_tools.DatabaseMigration.UpgradeScriptBackgroundTasks();
|
||||
break;
|
||||
|
||||
}
|
||||
@@ -235,9 +166,6 @@ namespace gaseous_server
|
||||
_ForceExecute = false;
|
||||
_ItemState = QueueItemState.Stopped;
|
||||
_LastFinishTime = DateTime.UtcNow;
|
||||
_LastRunDuration = Math.Round((DateTime.UtcNow - _LastRunTime).TotalSeconds, 2);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Timered Event", "Total " + _ItemType + " run time = " + _LastRunDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,66 +179,6 @@ namespace gaseous_server
|
||||
{
|
||||
_IsBlocked = BlockState;
|
||||
}
|
||||
|
||||
public HasErrorsItem HasErrors
|
||||
{
|
||||
get
|
||||
{
|
||||
return new HasErrorsItem(_CorrelationId);
|
||||
}
|
||||
}
|
||||
|
||||
public class HasErrorsItem
|
||||
{
|
||||
public HasErrorsItem(string? CorrelationId)
|
||||
{
|
||||
if (CorrelationId != null)
|
||||
{
|
||||
if (CorrelationId.Length > 0)
|
||||
{
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
string sql = "SELECT EventType, COUNT(EventType) AS EventTypes FROM gaseous.ServerLogs WHERE CorrelationId = @correlationid GROUP BY EventType ORDER BY EventType DESC LIMIT 1;";
|
||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||
dbDict.Add("correlationid", CorrelationId);
|
||||
|
||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||
|
||||
if (data.Rows.Count == 0)
|
||||
{
|
||||
ErrorType = null;
|
||||
ErrorCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.LogType errorType = (Logging.LogType)data.Rows[0]["EventType"];
|
||||
if (errorType != Logging.LogType.Information)
|
||||
{
|
||||
ErrorType = errorType;
|
||||
ErrorCount = (int)(long)data.Rows[0]["EventTypes"];
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorType = null;
|
||||
ErrorCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorType = null;
|
||||
ErrorCount = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorType = null;
|
||||
ErrorCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public Logging.LogType? ErrorType { get; set; }
|
||||
public int ErrorCount { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
public enum QueueItemType
|
||||
@@ -350,30 +218,15 @@ namespace gaseous_server
|
||||
/// </summary>
|
||||
LibraryScan,
|
||||
|
||||
/// <summary>
|
||||
/// Looks for roms in the library that have an unknown platform or game match
|
||||
/// </summary>
|
||||
Rematcher,
|
||||
|
||||
/// <summary>
|
||||
/// Builds collections - set the options attribute to the id of the collection to build
|
||||
/// </summary>
|
||||
CollectionCompiler,
|
||||
|
||||
/// <summary>
|
||||
/// Builds media groups - set the options attribute to the id of the media group to build
|
||||
/// </summary>
|
||||
MediaGroupCompiler,
|
||||
|
||||
/// <summary>
|
||||
/// Performs and post database upgrade scripts that can be processed as a background task
|
||||
/// </summary>
|
||||
BackgroundDatabaseUpgrade,
|
||||
|
||||
/// <summary>
|
||||
/// Performs a clean up of old files, and optimises the database
|
||||
/// </summary>
|
||||
Maintainer
|
||||
BackgroundDatabaseUpgrade
|
||||
}
|
||||
|
||||
public enum QueueItemState
|
||||
|
@@ -1,57 +1,26 @@
|
||||
using System.Reflection;
|
||||
using System.Text.Json.Serialization;
|
||||
using gaseous_server;
|
||||
using gaseous_server.Classes;
|
||||
using gaseous_server.Models;
|
||||
using gaseous_server.SignatureIngestors.XML;
|
||||
using gaseous_tools;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Versioning;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Authentication;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using IGDB.Models;
|
||||
using gaseous_server.Classes.Metadata;
|
||||
|
||||
Logging.WriteToDiskOnly = true;
|
||||
Logging.Log(Logging.LogType.Information, "Startup", "Starting Gaseous Server " + Assembly.GetExecutingAssembly().GetName().Version);
|
||||
|
||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionStringNoDatabase);
|
||||
|
||||
// check db availability
|
||||
bool dbOnline = false;
|
||||
do
|
||||
{
|
||||
Logging.Log(Logging.LogType.Information, "Startup", "Waiting for database...");
|
||||
if (db.TestConnection() == true)
|
||||
{
|
||||
dbOnline = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(30000);
|
||||
}
|
||||
} while (dbOnline == false);
|
||||
|
||||
db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
|
||||
// set up db
|
||||
Database db = new gaseous_tools.Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||
db.InitDB();
|
||||
|
||||
// populate db with static data for lookups
|
||||
AgeRatings.PopulateAgeMap();
|
||||
|
||||
// load app settings
|
||||
Config.InitSettings();
|
||||
// write updated settings back to the config file
|
||||
Config.UpdateConfig();
|
||||
|
||||
// set api metadata source from config
|
||||
Communications.MetadataSource = Config.MetadataConfiguration.Source;
|
||||
|
||||
// set initial values
|
||||
Guid APIKey = Guid.NewGuid();
|
||||
if (Config.ReadSetting("API Key", "Test API Key") == "Test API Key")
|
||||
@@ -61,16 +30,6 @@ if (Config.ReadSetting("API Key", "Test API Key") == "Test API Key")
|
||||
Config.SetSetting("API Key", APIKey.ToString());
|
||||
}
|
||||
|
||||
// clean up storage
|
||||
if (Directory.Exists(Config.LibraryConfiguration.LibraryTempDirectory))
|
||||
{
|
||||
Directory.Delete(Config.LibraryConfiguration.LibraryTempDirectory, true);
|
||||
}
|
||||
if (Directory.Exists(Config.LibraryConfiguration.LibraryUploadDirectory))
|
||||
{
|
||||
Directory.Delete(Config.LibraryConfiguration.LibraryUploadDirectory, true);
|
||||
}
|
||||
|
||||
// kick off any delayed upgrade tasks
|
||||
// run 1002 background updates in the background on every start
|
||||
DatabaseMigration.BackgroundUpgradeTargetSchemaVersions.Add(1002);
|
||||
@@ -124,24 +83,6 @@ builder.Services.AddControllers(options =>
|
||||
Location = ResponseCacheLocation.Any
|
||||
});
|
||||
});
|
||||
builder.Services.AddApiVersioning(config =>
|
||||
{
|
||||
config.DefaultApiVersion = new ApiVersion(1, 0);
|
||||
config.AssumeDefaultVersionWhenUnspecified = true;
|
||||
config.ReportApiVersions = true;
|
||||
config.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
|
||||
new HeaderApiVersionReader("x-api-version"),
|
||||
new MediaTypeApiVersionReader("x-api-version"));
|
||||
});
|
||||
// builder.Services.AddApiVersioning(setup =>
|
||||
// {
|
||||
// setup.ApiVersionReader = new UrlSegmentApiVersionReader();
|
||||
// });
|
||||
builder.Services.AddVersionedApiExplorer(setup =>
|
||||
{
|
||||
setup.GroupNameFormat = "'v'VVV";
|
||||
setup.SubstituteApiVersionInUrl = true;
|
||||
});
|
||||
|
||||
// set max upload size
|
||||
builder.Services.Configure<IISServerOptions>(options =>
|
||||
@@ -165,25 +106,7 @@ builder.Services.AddSwaggerGen(options =>
|
||||
{
|
||||
options.SwaggerDoc("v1", new OpenApiInfo
|
||||
{
|
||||
Version = "v1.0",
|
||||
Title = "Gaseous Server API",
|
||||
Description = "An API for managing the Gaseous Server",
|
||||
TermsOfService = new Uri("https://github.com/gaseous-project/gaseous-server"),
|
||||
Contact = new OpenApiContact
|
||||
{
|
||||
Name = "GitHub Repository",
|
||||
Url = new Uri("https://github.com/gaseous-project/gaseous-server")
|
||||
},
|
||||
License = new OpenApiLicense
|
||||
{
|
||||
Name = "Gaseous Server License",
|
||||
Url = new Uri("https://github.com/gaseous-project/gaseous-server/blob/main/LICENSE")
|
||||
}
|
||||
});
|
||||
|
||||
options.SwaggerDoc("v1.1", new OpenApiInfo
|
||||
{
|
||||
Version = "v1.1",
|
||||
Version = "v1",
|
||||
Title = "Gaseous Server API",
|
||||
Description = "An API for managing the Gaseous Server",
|
||||
TermsOfService = new Uri("https://github.com/gaseous-project/gaseous-server"),
|
||||
@@ -206,97 +129,19 @@ builder.Services.AddSwaggerGen(options =>
|
||||
);
|
||||
builder.Services.AddHostedService<TimedHostedService>();
|
||||
|
||||
// identity
|
||||
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
|
||||
{
|
||||
options.Password.RequireDigit = true;
|
||||
options.Password.RequireLowercase = true;
|
||||
options.Password.RequireNonAlphanumeric = false;
|
||||
options.Password.RequireUppercase = true;
|
||||
options.Password.RequiredLength = 10;
|
||||
options.User.AllowedUserNameCharacters = null;
|
||||
options.User.RequireUniqueEmail = true;
|
||||
options.SignIn.RequireConfirmedPhoneNumber = false;
|
||||
options.SignIn.RequireConfirmedEmail = false;
|
||||
options.SignIn.RequireConfirmedAccount = false;
|
||||
})
|
||||
.AddUserStore<UserStore>()
|
||||
.AddRoleStore<RoleStore>()
|
||||
.AddDefaultTokenProviders()
|
||||
.AddDefaultUI()
|
||||
;
|
||||
builder.Services.ConfigureApplicationCookie(options =>
|
||||
{
|
||||
options.Cookie.Name = "Gaseous.Identity";
|
||||
options.ExpireTimeSpan = TimeSpan.FromDays(90);
|
||||
options.SlidingExpiration = true;
|
||||
options.Cookie.HttpOnly = true;
|
||||
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
|
||||
options.Cookie.SameSite = SameSiteMode.Strict;
|
||||
});
|
||||
// builder.Services.AddIdentityCore<ApplicationUser>(options => {
|
||||
// options.SignIn.RequireConfirmedAccount = false;
|
||||
// options.User.RequireUniqueEmail = true;
|
||||
// options.Password.RequireDigit = false;
|
||||
// options.Password.RequiredLength = 10;
|
||||
// options.Password.RequireNonAlphanumeric = false;
|
||||
// options.Password.RequireUppercase = false;
|
||||
// options.Password.RequireLowercase = false;
|
||||
// });
|
||||
builder.Services.AddScoped<UserStore>();
|
||||
builder.Services.AddScoped<RoleStore>();
|
||||
|
||||
builder.Services.AddTransient<IUserStore<ApplicationUser>, UserStore>();
|
||||
builder.Services.AddTransient<IRoleStore<ApplicationRole>, RoleStore>();
|
||||
|
||||
builder.Services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy("Admin", policy => policy.RequireRole("Admin"));
|
||||
options.AddPolicy("Gamer", policy => policy.RequireRole("Gamer"));
|
||||
options.AddPolicy("Player", policy => policy.RequireRole("Player"));
|
||||
});
|
||||
|
||||
// builder.Services.AddControllersWithViews(options =>
|
||||
// {
|
||||
// options.Filters.Add(new Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute());
|
||||
// });
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
//if (app.Environment.IsDevelopment())
|
||||
//{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(options =>
|
||||
{
|
||||
options.SwaggerEndpoint($"/swagger/v1/swagger.json", "v1.0");
|
||||
options.SwaggerEndpoint($"/swagger/v1.1/swagger.json", "v1.1");
|
||||
}
|
||||
);
|
||||
app.UseSwaggerUI();
|
||||
//}
|
||||
|
||||
//app.UseHttpsRedirection();
|
||||
|
||||
app.UseResponseCaching();
|
||||
|
||||
// set up system roles
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var roleManager = scope.ServiceProvider.GetRequiredService<RoleStore>();
|
||||
var roles = new[] { "Admin", "Gamer", "Player" };
|
||||
|
||||
foreach (var role in roles)
|
||||
{
|
||||
if (await roleManager.FindByNameAsync(role, CancellationToken.None) == null)
|
||||
{
|
||||
ApplicationRole applicationRole = new ApplicationRole();
|
||||
applicationRole.Name = role;
|
||||
applicationRole.NormalizedName = role.ToUpper();
|
||||
await roleManager.CreateAsync(applicationRole, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseDefaultFiles();
|
||||
@@ -308,163 +153,38 @@ app.UseStaticFiles(new StaticFileOptions
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
// set the correlation id
|
||||
string correlationId = Guid.NewGuid().ToString();
|
||||
CallContext.SetData("CorrelationId", correlationId);
|
||||
CallContext.SetData("CallingProcess", context.Request.Method + ": " + context.Request.Path);
|
||||
|
||||
string userIdentity;
|
||||
try
|
||||
{
|
||||
userIdentity = context.User.Claims.Where(x=>x.Type==System.Security.Claims.ClaimTypes.NameIdentifier).FirstOrDefault().Value;
|
||||
}
|
||||
catch
|
||||
{
|
||||
userIdentity = "";
|
||||
}
|
||||
CallContext.SetData("CallingUser", userIdentity);
|
||||
|
||||
context.Response.Headers.Add("x-correlation-id", correlationId.ToString());
|
||||
await next();
|
||||
});
|
||||
|
||||
// emergency password recovery if environment variable is set
|
||||
// process:
|
||||
// - set the environment variable "recoveraccount" to the email address of the account to be recovered
|
||||
// - when the server starts the password will be reset to a random string and saved in the library
|
||||
// directory with the name RecoverAccount.txt
|
||||
// - user should copy this password and remove the "recoveraccount" environment variable and the
|
||||
// RecoverAccount.txt file
|
||||
// - the server will not start while the RecoverAccount.txt file exists
|
||||
string PasswordRecoveryFile = Path.Combine(Config.LibraryConfiguration.LibraryRootDirectory, "RecoverAccount.txt");
|
||||
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("recoveraccount")))
|
||||
{
|
||||
if (File.Exists(PasswordRecoveryFile))
|
||||
{
|
||||
// password has already been set - do nothing and just exit
|
||||
Logging.Log(Logging.LogType.Critical, "Server Startup", "Unable to start while recoveraccount environment varibale is set and RecoverAccount.txt file exists.", null, true);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// generate and save the password to disk
|
||||
int length = 10;
|
||||
string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+";
|
||||
var random = new Random();
|
||||
string password = new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
|
||||
|
||||
File.WriteAllText(PasswordRecoveryFile, password);
|
||||
|
||||
// reset the password
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var userManager = scope.ServiceProvider.GetRequiredService<UserStore>();
|
||||
if (await userManager.FindByNameAsync(Environment.GetEnvironmentVariable("recoveraccount"), CancellationToken.None) != null)
|
||||
{
|
||||
ApplicationUser User = await userManager.FindByEmailAsync(Environment.GetEnvironmentVariable("recoveraccount"), CancellationToken.None);
|
||||
|
||||
//set user password
|
||||
PasswordHasher<ApplicationUser> ph = new PasswordHasher<ApplicationUser>();
|
||||
User.PasswordHash = ph.HashPassword(User, password);
|
||||
|
||||
await userManager.SetPasswordHashAsync(User, User.PasswordHash, CancellationToken.None);
|
||||
|
||||
Logging.Log(Logging.LogType.Information, "Server Startup", "Password reset complete, remove the recoveraccount environment variable and RecoverAccount.text file to allow server start.", null, true);
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(Logging.LogType.Critical, "Server Startup", "Account to recover not found.", null, true);
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if RecoverAccount.text file is present
|
||||
if (File.Exists(PasswordRecoveryFile))
|
||||
{
|
||||
// cannot start while password recovery file exists
|
||||
Logging.Log(Logging.LogType.Critical, "Server Startup", "Unable to start while RecoverAccount.txt file exists. Remove the file and try again.", null, true);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
// setup library directories
|
||||
Config.LibraryConfiguration.InitLibrary();
|
||||
|
||||
// insert unknown platform and game if not present
|
||||
gaseous_server.Classes.Metadata.Games.GetGame(0, false, false, false);
|
||||
gaseous_server.Classes.Metadata.Games.AssignAllGamesToPlatformIdZero();
|
||||
gaseous_server.Classes.Metadata.Platforms.GetPlatform(0);
|
||||
gaseous_server.Classes.Metadata.Platforms.AssignAllPlatformsToGameIdZero();
|
||||
|
||||
// extract platform map if not present
|
||||
PlatformMapping.ExtractPlatformMap();
|
||||
|
||||
// force load platform map into cache
|
||||
var platformMap = PlatformMapping.PlatformMap;
|
||||
|
||||
// add background tasks
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(ProcessQueue.QueueItemType.SignatureIngestor, 60));
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.SignatureIngestor,
|
||||
int.Parse(Config.ReadSetting("Interval_SignatureIngestor", "60"))
|
||||
)
|
||||
);
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.TitleIngestor,
|
||||
int.Parse(Config.ReadSetting("Interval_TitleIngestor", "1")),
|
||||
ProcessQueue.QueueItemType.TitleIngestor, 1,
|
||||
new List<ProcessQueue.QueueItemType>
|
||||
{
|
||||
ProcessQueue.QueueItemType.OrganiseLibrary,
|
||||
ProcessQueue.QueueItemType.LibraryScan
|
||||
})
|
||||
);
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(ProcessQueue.QueueItemType.MetadataRefresh, 360));
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.MetadataRefresh,
|
||||
int.Parse(Config.ReadSetting("Interval_MetadataRefresh", "360"))
|
||||
)
|
||||
);
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.OrganiseLibrary,
|
||||
int.Parse(Config.ReadSetting("Interval_OrganiseLibrary", "1440")),
|
||||
new List<ProcessQueue.QueueItemType>
|
||||
ProcessQueue.QueueItemType.OrganiseLibrary, 1440, new List<ProcessQueue.QueueItemType>
|
||||
{
|
||||
ProcessQueue.QueueItemType.LibraryScan,
|
||||
ProcessQueue.QueueItemType.TitleIngestor,
|
||||
ProcessQueue.QueueItemType.Rematcher
|
||||
ProcessQueue.QueueItemType.TitleIngestor
|
||||
})
|
||||
);
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.LibraryScan,
|
||||
int.Parse(Config.ReadSetting("Interval_LibraryScan", "1440")),
|
||||
new List<ProcessQueue.QueueItemType>
|
||||
ProcessQueue.QueueItemType.LibraryScan, 1440, new List<ProcessQueue.QueueItemType>
|
||||
{
|
||||
ProcessQueue.QueueItemType.OrganiseLibrary,
|
||||
ProcessQueue.QueueItemType.Rematcher
|
||||
})
|
||||
);
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.Rematcher,
|
||||
int.Parse(Config.ReadSetting("Interval_Rematcher", "1440")),
|
||||
new List<ProcessQueue.QueueItemType>
|
||||
{
|
||||
ProcessQueue.QueueItemType.OrganiseLibrary,
|
||||
ProcessQueue.QueueItemType.LibraryScan
|
||||
})
|
||||
);
|
||||
ProcessQueue.QueueItems.Add(new ProcessQueue.QueueItem(
|
||||
ProcessQueue.QueueItemType.Maintainer,
|
||||
int.Parse(Config.ReadSetting("Interval_Maintainer", "10080")),
|
||||
new List<ProcessQueue.QueueItemType>
|
||||
{
|
||||
ProcessQueue.QueueItemType.All
|
||||
ProcessQueue.QueueItemType.OrganiseLibrary
|
||||
})
|
||||
);
|
||||
|
||||
|
@@ -1,585 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Security.Claims;
|
||||
using Authentication;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
namespace gaseous_server.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("Account")]
|
||||
[Authorize]
|
||||
public class OldAccountController : Controller
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly IEmailSender _emailSender;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public OldAccountController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
IEmailSender emailSender,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
_emailSender = emailSender;
|
||||
_logger = loggerFactory.CreateLogger<OldAccountController>();
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/Login
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("Login")]
|
||||
public IActionResult Login(string returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/Login
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("Login")]
|
||||
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// This doesn't count login failures towards account lockout
|
||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
||||
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_logger.LogInformation(1, "User logged in.");
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
if (result.RequiresTwoFactor)
|
||||
{
|
||||
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
_logger.LogWarning(2, "User account locked out.");
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/Register
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("Register")]
|
||||
public IActionResult Register(string returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/Register
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("Register")]
|
||||
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
|
||||
{
|
||||
// ViewData["ReturnUrl"] = returnUrl;
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
ApplicationUser user = new ApplicationUser
|
||||
{
|
||||
UserName = model.UserName,
|
||||
NormalizedUserName = model.UserName.ToUpper(),
|
||||
Email = model.Email,
|
||||
NormalizedEmail = model.Email.ToUpper()
|
||||
};
|
||||
var result = await _userManager.CreateAsync(user, model.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
|
||||
// Send an email with this link
|
||||
//var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
//var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
|
||||
//await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
|
||||
// "Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>");
|
||||
|
||||
// add all users to the member role
|
||||
await _userManager.AddToRoleAsync(user, "Player");
|
||||
|
||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
||||
_logger.LogInformation(3, "User created a new account with password.");
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
AddErrors(result);
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/LogOff
|
||||
[HttpPost]
|
||||
[Route("LogOff")]
|
||||
public async Task<IActionResult> LogOff()
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
_logger.LogInformation(4, "User logged out.");
|
||||
//return RedirectToAction(nameof(HomeController.Index), "Home");
|
||||
return Ok();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ExternalLogin
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("ExternalLogin")]
|
||||
public IActionResult ExternalLogin(string provider, string returnUrl = null)
|
||||
{
|
||||
// Request a redirect to the external login provider.
|
||||
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
|
||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
|
||||
return Challenge(properties, provider);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ExternalLoginCallback
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("ExternalLoginCallback")]
|
||||
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
|
||||
{
|
||||
if (remoteError != null)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
|
||||
return View(nameof(Login));
|
||||
}
|
||||
var info = await _signInManager.GetExternalLoginInfoAsync();
|
||||
if (info == null)
|
||||
{
|
||||
return RedirectToAction(nameof(Login));
|
||||
}
|
||||
|
||||
// Sign in the user with this external login provider if the user already has a login.
|
||||
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
// Update any authentication tokens if login succeeded
|
||||
await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
|
||||
|
||||
_logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
if (result.RequiresTwoFactor)
|
||||
{
|
||||
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl });
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the user does not have an account, then ask the user to create an account.
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
ViewData["ProviderDisplayName"] = info.ProviderDisplayName;
|
||||
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
|
||||
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ExternalLoginConfirmation
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("ExternalLoginConfirmation")]
|
||||
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// Get the information about the user from the external login provider
|
||||
var info = await _signInManager.GetExternalLoginInfoAsync();
|
||||
if (info == null)
|
||||
{
|
||||
return View("ExternalLoginFailure");
|
||||
}
|
||||
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
|
||||
var result = await _userManager.CreateAsync(user);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
result = await _userManager.AddLoginAsync(user, info);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
||||
_logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider);
|
||||
|
||||
// Update any authentication tokens as well
|
||||
await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
|
||||
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
}
|
||||
AddErrors(result);
|
||||
}
|
||||
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /Account/ConfirmEmail
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("ConfirmEmail")]
|
||||
public async Task<IActionResult> ConfirmEmail(string userId, string code)
|
||||
{
|
||||
if (userId == null || code == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
var user = await _userManager.FindByIdAsync(userId);
|
||||
if (user == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
var result = await _userManager.ConfirmEmailAsync(user, code);
|
||||
return View(result.Succeeded ? "ConfirmEmail" : "Error");
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ForgotPassword
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("ForgotPassword")]
|
||||
public IActionResult ForgotPassword()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ForgotPassword
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("ForgotPassword")]
|
||||
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(model.Email);
|
||||
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
|
||||
{
|
||||
// Don't reveal that the user does not exist or is not confirmed
|
||||
return View("ForgotPasswordConfirmation");
|
||||
}
|
||||
|
||||
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
|
||||
// Send an email with this link
|
||||
//var code = await _userManager.GeneratePasswordResetTokenAsync(user);
|
||||
//var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
|
||||
//await _emailSender.SendEmailAsync(model.Email, "Reset Password",
|
||||
// "Please reset your password by clicking here: <a href=\"" + callbackUrl + "\">link</a>");
|
||||
//return View("ForgotPasswordConfirmation");
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ForgotPasswordConfirmation
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("ForgotPasswordConfirmation")]
|
||||
public IActionResult ForgotPasswordConfirmation()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ResetPassword
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("ResetPassword")]
|
||||
public IActionResult ResetPassword(string code = null)
|
||||
{
|
||||
return code == null ? View("Error") : View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ResetPassword
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("ResetPassword")]
|
||||
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
var user = await _userManager.FindByEmailAsync(model.Email);
|
||||
if (user == null)
|
||||
{
|
||||
// Don't reveal that the user does not exist
|
||||
return RedirectToAction(nameof(OldAccountController.ResetPasswordConfirmation), "Account");
|
||||
}
|
||||
var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return RedirectToAction(nameof(OldAccountController.ResetPasswordConfirmation), "Account");
|
||||
}
|
||||
AddErrors(result);
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ResetPasswordConfirmation
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("ResetPasswordConfirmation")]
|
||||
public IActionResult ResetPasswordConfirmation()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/SendCode
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("SendCode")]
|
||||
public async Task<ActionResult> SendCode(string returnUrl = null, bool rememberMe = false)
|
||||
{
|
||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||
if (user == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);
|
||||
var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList();
|
||||
return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe });
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/SendCode
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("SendCode")]
|
||||
public async Task<IActionResult> SendCode(SendCodeViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||
if (user == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
|
||||
if (model.SelectedProvider == "Authenticator")
|
||||
{
|
||||
return RedirectToAction(nameof(VerifyAuthenticatorCode), new { ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe });
|
||||
}
|
||||
|
||||
// Generate the token and send it
|
||||
var code = await _userManager.GenerateTwoFactorTokenAsync(user, model.SelectedProvider);
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
|
||||
var message = "Your security code is: " + code;
|
||||
if (model.SelectedProvider == "Email")
|
||||
{
|
||||
await _emailSender.SendEmailAsync(await _userManager.GetEmailAsync(user), "Security Code", message);
|
||||
}
|
||||
// else if (model.SelectedProvider == "Phone")
|
||||
// {
|
||||
// await _smsSender.SendSmsAsync(await _userManager.GetPhoneNumberAsync(user), message);
|
||||
// }
|
||||
|
||||
return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe });
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/VerifyCode
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("VerifyCode")]
|
||||
public async Task<IActionResult> VerifyCode(string provider, bool rememberMe, string returnUrl = null)
|
||||
{
|
||||
// Require that the user has already logged in via username/password or external login
|
||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||
if (user == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe });
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/VerifyCode
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("VerifyCode")]
|
||||
public async Task<IActionResult> VerifyCode(VerifyCodeViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// The following code protects for brute force attacks against the two factor codes.
|
||||
// If a user enters incorrect codes for a specified amount of time then the user account
|
||||
// will be locked out for a specified amount of time.
|
||||
var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return RedirectToLocal(model.ReturnUrl);
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
_logger.LogWarning(7, "User account locked out.");
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Invalid code.");
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/VerifyAuthenticatorCode
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("VerifyAuthenticatorCode")]
|
||||
public async Task<IActionResult> VerifyAuthenticatorCode(bool rememberMe, string returnUrl = null)
|
||||
{
|
||||
// Require that the user has already logged in via username/password or external login
|
||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||
if (user == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
return View(new VerifyAuthenticatorCodeViewModel { ReturnUrl = returnUrl, RememberMe = rememberMe });
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/VerifyAuthenticatorCode
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("VerifyAuthenticatorCode")]
|
||||
public async Task<IActionResult> VerifyAuthenticatorCode(VerifyAuthenticatorCodeViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// The following code protects for brute force attacks against the two factor codes.
|
||||
// If a user enters incorrect codes for a specified amount of time then the user account
|
||||
// will be locked out for a specified amount of time.
|
||||
var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(model.Code, model.RememberMe, model.RememberBrowser);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return RedirectToLocal(model.ReturnUrl);
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
_logger.LogWarning(7, "User account locked out.");
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Invalid code.");
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/UseRecoveryCode
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
[Route("UseRecoveryCode")]
|
||||
public async Task<IActionResult> UseRecoveryCode(string returnUrl = null)
|
||||
{
|
||||
// Require that the user has already logged in via username/password or external login
|
||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||
if (user == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
return View(new UseRecoveryCodeViewModel { ReturnUrl = returnUrl });
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/UseRecoveryCode
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[Route("UseRecoveryCode")]
|
||||
public async Task<IActionResult> UseRecoveryCode(UseRecoveryCodeViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(model.Code);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return RedirectToLocal(model.ReturnUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Invalid code.");
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
private void AddErrors(IdentityResult result)
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, error.Description);
|
||||
}
|
||||
}
|
||||
|
||||
private Task<ApplicationUser> GetCurrentUserAsync()
|
||||
{
|
||||
return _userManager.GetUserAsync(HttpContext.User);
|
||||
}
|
||||
|
||||
private IActionResult RedirectToLocal(string returnUrl)
|
||||
{
|
||||
if (Url.IsLocalUrl(returnUrl))
|
||||
{
|
||||
return Redirect(returnUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Redirect("/");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user