feat: added company info support

This commit is contained in:
Michael Green
2023-06-30 19:18:19 +10:00
parent fba9b7a6c9
commit 0cc8e76f77
11 changed files with 811 additions and 3 deletions

View File

@@ -0,0 +1,123 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
namespace gaseous_server.Classes.Metadata
{
public class Companies
{
const string fieldList = "fields change_date,change_date_category,changed_company_id,checksum,country,created_at,description,developed,logo,name,parent,published,slug,start_date,start_date_category,updated_at,url,websites;";
public Companies()
{
}
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))
{
return null;
}
else
{
Task<Company> RetVal = _GetCompanies(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static Company GetCompanies(string Slug)
{
Task<Company> RetVal = _GetCompanies(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<Company> _GetCompanies(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("Company", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("Company", (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");
}
Company returnValue = new Company();
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
if (returnValue != null) { Storage.NewCacheValue(returnValue); }
UpdateSubClasses(returnValue);
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
if (returnValue != null) { Storage.NewCacheValue(returnValue, true); }
UpdateSubClasses(returnValue);
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<Company>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private static void UpdateSubClasses(Company company)
{
if (company.Logo != null)
{
CompanyLogo companyLogo = CompanyLogos.GetCompanyLogo(company.Logo.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Company(company));
}
}
private enum SearchUsing
{
id,
slug
}
private static async Task<Company> GetObjectFromServer(string WhereClause)
{
// get Companies metadata
var results = await igdb.QueryAsync<Company>(IGDBClient.Endpoints.Companies, query: fieldList + " " + WhereClause + ";");
if (results.Length > 0)
{
var result = results.First();
return result;
}
else
{
return null;
}
}
}
}

View File

@@ -0,0 +1,175 @@
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
{
public class CompanyLogos
{
const string fieldList = "fields alpha_channel,animated,checksum,height,image_id,url,width;";
public CompanyLogos()
{
}
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))
{
return null;
}
else
{
Task<CompanyLogo> RetVal = _GetCompanyLogo(SearchUsing.id, Id, LogoPath);
return RetVal.Result;
}
}
public static CompanyLogo GetCompanyLogo(string Slug, string LogoPath)
{
Task<CompanyLogo> RetVal = _GetCompanyLogo(SearchUsing.slug, Slug, LogoPath);
return RetVal.Result;
}
private static async Task<CompanyLogo> _GetCompanyLogo(SearchUsing searchUsing, object searchValue, string LogoPath)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("CompanyLogo", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("CompanyLogo", (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");
}
CompanyLogo returnValue = new CompanyLogo();
bool forceImageDownload = false;
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
if (returnValue != null)
{
Storage.NewCacheValue(returnValue);
forceImageDownload = true;
}
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause, LogoPath);
if (returnValue != null)
{
Storage.NewCacheValue(returnValue, true);
forceImageDownload = true;
}
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<CompanyLogo>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
if (returnValue != null)
{
if ((!File.Exists(Path.Combine(LogoPath, "Logo.jpg"))) || forceImageDownload == true)
{
GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_thumb);
GetImageFromServer(returnValue.Url, LogoPath, LogoSize.t_logo_med);
}
}
return returnValue;
}
private enum SearchUsing
{
id,
slug
}
private static async Task<CompanyLogo?> GetObjectFromServer(string WhereClause, string LogoPath)
{
// get CompanyLogo metadata
var results = await igdb.QueryAsync<CompanyLogo>(IGDBClient.Endpoints.CompanyLogos, query: fieldList + " " + WhereClause + ";");
if (results.Length > 0)
{
var result = results.First();
GetImageFromServer(result.Url, LogoPath, LogoSize.t_thumb);
GetImageFromServer(result.Url, LogoPath, LogoSize.t_logo_med);
return result;
}
else
{
return null;
}
}
private static void GetImageFromServer(string Url, string LogoPath, LogoSize logoSize)
{
using (var client = new HttpClient())
{
string fileName = "Logo.jpg";
string extension = "jpg";
switch (logoSize)
{
case LogoSize.t_thumb:
fileName = "Logo_Thumb";
extension = "jpg";
break;
case LogoSize.t_logo_med:
fileName = "Logo_Medium";
extension = "png";
break;
default:
fileName = "Logo";
extension = "jpg";
break;
}
string imageUrl = Url.Replace(LogoSize.t_thumb.ToString(), logoSize.ToString()).Replace("jpg", extension);
using (var s = client.GetStreamAsync("https:" + imageUrl))
{
if (!Directory.Exists(LogoPath)) { Directory.CreateDirectory(LogoPath); }
using (var fs = new FileStream(Path.Combine(LogoPath, fileName + "." + extension), FileMode.OpenOrCreate))
{
s.Result.CopyTo(fs);
}
}
}
}
private enum LogoSize
{
t_thumb,
t_logo_med
}
}
}

View File

@@ -122,6 +122,7 @@ namespace gaseous_server.Classes.Metadata
AgeRating GameAgeRating = AgeRatings.GetAgeRatings(AgeRatingId);
}
}
if (Game.AlternativeNames != null)
{
foreach (long AlternativeNameId in Game.AlternativeNames.Ids)
@@ -129,6 +130,7 @@ namespace gaseous_server.Classes.Metadata
AlternativeName GameAlternativeName = AlternativeNames.GetAlternativeNames(AlternativeNameId);
}
}
if (Game.Artworks != null)
{
foreach (long ArtworkId in Game.Artworks.Ids)
@@ -136,6 +138,7 @@ namespace gaseous_server.Classes.Metadata
Artwork GameArtwork = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
}
}
if (followSubGames)
{
List<long> gamesToFetch = new List<long>();
@@ -152,14 +155,17 @@ namespace gaseous_server.Classes.Metadata
Game relatedGame = GetGame(gameId, false, false);
}
}
if (Game.Collection != null)
{
Collection GameCollection = Collections.GetCollections(Game.Collection.Id);
}
if (Game.Cover != null)
{
Cover GameCover = Covers.GetCover(Game.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
}
if (Game.ExternalGames != null)
{
foreach (long ExternalGameId in Game.ExternalGames.Ids)
@@ -167,10 +173,12 @@ namespace gaseous_server.Classes.Metadata
ExternalGame GameExternalGame = ExternalGames.GetExternalGames(ExternalGameId);
}
}
if (Game.Franchise != null)
{
Franchise GameFranchise = Franchises.GetFranchises(Game.Franchise.Id);
}
if (Game.Franchises != null)
{
foreach (long FranchiseId in Game.Franchises.Ids)
@@ -178,6 +186,7 @@ namespace gaseous_server.Classes.Metadata
Franchise GameFranchise = Franchises.GetFranchises(FranchiseId);
}
}
if (Game.Genres != null)
{
foreach (long GenreId in Game.Genres.Ids)
@@ -185,6 +194,15 @@ namespace gaseous_server.Classes.Metadata
Genre GameGenre = Genres.GetGenres(GenreId);
}
}
if (Game.InvolvedCompanies != null)
{
foreach (long involvedCompanyId in Game.InvolvedCompanies.Ids)
{
InvolvedCompany involvedCompany = InvolvedCompanies.GetInvolvedCompanies(involvedCompanyId);
}
}
if (Game.Platforms != null)
{
foreach (long PlatformId in Game.Platforms.Ids)
@@ -192,6 +210,7 @@ namespace gaseous_server.Classes.Metadata
Platform GamePlatform = Platforms.GetPlatform(PlatformId);
}
}
if (Game.Screenshots != null)
{
foreach (long ScreenshotId in Game.Screenshots.Ids)
@@ -199,6 +218,7 @@ namespace gaseous_server.Classes.Metadata
Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game));
}
}
if (Game.Videos != null)
{
foreach (long GameVideoId in Game.Videos.Ids)

View File

@@ -0,0 +1,126 @@
using System;
using gaseous_tools;
using IGDB;
using IGDB.Models;
namespace gaseous_server.Classes.Metadata
{
public class InvolvedCompanies
{
const string fieldList = "fields *;";
public InvolvedCompanies()
{
}
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))
{
return null;
}
else
{
Task<InvolvedCompany> RetVal = _GetInvolvedCompanies(SearchUsing.id, Id);
return RetVal.Result;
}
}
public static InvolvedCompany GetInvolvedCompanies(string Slug)
{
Task<InvolvedCompany> RetVal = _GetInvolvedCompanies(SearchUsing.slug, Slug);
return RetVal.Result;
}
private static async Task<InvolvedCompany> _GetInvolvedCompanies(SearchUsing searchUsing, object searchValue)
{
// check database first
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
if (searchUsing == SearchUsing.id)
{
cacheStatus = Storage.GetCacheStatus("InvolvedCompany", (long)searchValue);
}
else
{
cacheStatus = Storage.GetCacheStatus("InvolvedCompany", (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");
}
InvolvedCompany returnValue = new InvolvedCompany();
switch (cacheStatus)
{
case Storage.CacheStatus.NotPresent:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue);
UpdateSubClasses(returnValue);
break;
case Storage.CacheStatus.Expired:
returnValue = await GetObjectFromServer(WhereClause);
Storage.NewCacheValue(returnValue, true);
UpdateSubClasses(returnValue);
break;
case Storage.CacheStatus.Current:
returnValue = Storage.GetCacheValue<InvolvedCompany>(returnValue, "id", (long)searchValue);
break;
default:
throw new Exception("How did you get here?");
}
return returnValue;
}
private static void UpdateSubClasses(InvolvedCompany involvedCompany)
{
if (involvedCompany.Company != null)
{
Company company = Companies.GetCompanies(involvedCompany.Company.Id);
}
}
private enum SearchUsing
{
id,
slug
}
private static async Task<InvolvedCompany> GetObjectFromServer(string WhereClause)
{
// get InvolvedCompanies metadata
try
{
var results = await igdb.QueryAsync<InvolvedCompany>(IGDBClient.Endpoints.InvolvedCompanies, query: fieldList + " " + WhereClause + ";");
var result = results.First();
return result;
}
catch (Exception ex)
{
Logging.Log(Logging.LogType.Critical, "Involved Companies", "Failure when requesting involved companies.");
Logging.Log(Logging.LogType.Critical, "Involved Companies", "Field list: " + fieldList);
Logging.Log(Logging.LogType.Critical, "Involved Companies", "Where clause: " + WhereClause);
Logging.Log(Logging.LogType.Critical, "Involved Companies", "Error", ex);
throw;
}
}
}
}

View File

@@ -204,6 +204,10 @@ namespace gaseous_server.Classes.Metadata
{
switch (objectTypeName)
{
//case "boolean":
// Boolean storedBool = Convert.ToBoolean((int)dataRow[property.Name]);
// property.SetValue(EndpointType, storedBool);
// break;
case "datetimeoffset":
DateTimeOffset? storedDate = (DateTime?)dataRow[property.Name];
property.SetValue(EndpointType, storedDate);
@@ -219,6 +223,9 @@ namespace gaseous_server.Classes.Metadata
case "collection":
objectToStore = new IdentityOrValue<Collection>(id: (long)dataRow[property.Name]);
break;
case "company":
objectToStore = new IdentityOrValue<Company>(id: (long)dataRow[property.Name]);
break;
case "cover":
objectToStore = new IdentityOrValue<Cover>(id: (long)dataRow[property.Name]);
break;
@@ -354,6 +361,9 @@ namespace gaseous_server.Classes.Metadata
case "[igdb.models.externalcategory":
property.SetValue(EndpointType, (ExternalCategory)dataRow[property.Name]);
break;
case "[igdb.models.startdatecategory":
property.SetValue(EndpointType, (StartDateCategory)dataRow[property.Name]);
break;
default:
property.SetValue(EndpointType, dataRow[property.Name]);
break;

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
@@ -11,6 +12,7 @@ using IGDB.Models;
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
@@ -481,6 +483,169 @@ namespace gaseous_server.Controllers
}
}
[HttpGet]
[Route("{GameId}/genre")]
[ProducesResponseType(typeof(List<Genre>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ResponseCache(CacheProfileName = "7Days")]
public ActionResult GameGenre(long GameId)
{
try
{
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false);
if (gameObject != null)
{
List<IGDB.Models.Genre> genreObjects = new List<Genre>();
if (gameObject.Genres != null)
{
foreach (long genreId in gameObject.Genres.Ids)
{
genreObjects.Add(Classes.Metadata.Genres.GetGenres(genreId));
}
}
List<IGDB.Models.Genre> sortedGenreObjects = genreObjects.OrderBy(o => o.Name).ToList();
return Ok(sortedGenreObjects);
}
else
{
return NotFound();
}
}
catch
{
return NotFound();
}
}
[HttpGet]
[Route("{GameId}/companies")]
[ProducesResponseType(typeof(List<Dictionary<string, object>>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ResponseCache(CacheProfileName = "7Days")]
public ActionResult GameInvolvedCompanies(long GameId)
{
try
{
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false);
if (gameObject != null)
{
List<Dictionary<string, object>> icObjects = new List<Dictionary<string, object>>();
if (gameObject.InvolvedCompanies != null)
{
foreach (long icId in gameObject.InvolvedCompanies.Ids)
{
InvolvedCompany involvedCompany = Classes.Metadata.InvolvedCompanies.GetInvolvedCompanies(icId);
Company company = Classes.Metadata.Companies.GetCompanies(involvedCompany.Company.Id);
company.Developed = null;
company.Published = null;
Dictionary<string, object> companyData = new Dictionary<string, object>();
companyData.Add("involvement", involvedCompany);
companyData.Add("company", company);
icObjects.Add(companyData);
}
}
return Ok(icObjects);
}
else
{
return NotFound();
}
}
catch
{
return NotFound();
}
}
[HttpGet]
[Route("{GameId}/companies/{CompanyId}")]
[ProducesResponseType(typeof(Dictionary<string, object>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ResponseCache(CacheProfileName = "7Days")]
public ActionResult GameInvolvedCompanies(long GameId, long CompanyId)
{
try
{
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false);
if (gameObject != null)
{
List<Dictionary<string, object>> icObjects = new List<Dictionary<string, object>>();
if (gameObject.InvolvedCompanies != null)
{
InvolvedCompany involvedCompany = Classes.Metadata.InvolvedCompanies.GetInvolvedCompanies(CompanyId);
Company company = Classes.Metadata.Companies.GetCompanies(involvedCompany.Company.Id);
company.Developed = null;
company.Published = null;
Dictionary<string, object> companyData = new Dictionary<string, object>();
companyData.Add("involvement", involvedCompany);
companyData.Add("company", company);
return Ok(companyData);
} else
{
return NotFound();
}
}
else
{
return NotFound();
}
}
catch
{
return NotFound();
}
}
[HttpGet]
[Route("{GameId}/companies/{CompanyId}/image")]
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult GameCompanyImage(long GameId, long CompanyId)
{
try
{
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false);
InvolvedCompany involvedCompany = Classes.Metadata.InvolvedCompanies.GetInvolvedCompanies(CompanyId);
Company company = Classes.Metadata.Companies.GetCompanies(involvedCompany.Company.Id);
string coverFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Company(company), "Logo_Medium.png");
if (System.IO.File.Exists(coverFilePath))
{
string filename = "Logo.png";
string filepath = coverFilePath;
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
string contentType = "image/png";
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);
}
else
{
return NotFound();
}
}
catch
{
return NotFound();
}
}
[HttpGet]
[Route("{GameId}/roms")]
[ProducesResponseType(typeof(List<Classes.Roms.GameRomItem>), StatusCodes.Status200OK)]

View File

@@ -1,8 +1,11 @@
<div id="bgImage"></div>
<div id="bgImage">
<div id="bgImage_Opacity"></div>
</div>
<div id="gamepage">
<div id="gametitle">
<h1 id="gametitle_label"></h1>
<p id="gamedeveloper_label"></p>
<p id="gametitle_alts">
<span>Also known as: </span><span id="gametitle_alts_label"></span>
</p>
@@ -11,6 +14,15 @@
<div id="gamesummary">
<div id="gamesummary_cover"></div>
<div id="gamesumarry_genres">
<h3>Genres</h3>
</div>
<div id="gamesummary_developer">
<h3>Developers</h3>
</div>
<div id="gamesummary_publishers">
<h3>Publishers</h3>
</div>
<div id="gamesummary_ratings">
<h3>Age Ratings</h3>
</div>
@@ -97,7 +109,8 @@
// load artwork
if (result.artworks) {
artworks = result.artworks.ids;
artworksPostition = 0;
var startPos = randomIntFromInterval(0, result.artworks.ids.length);
artworksPosition = startPos;
rotateBackground();
} else {
if (result.cover) {
@@ -106,6 +119,52 @@
}
}
// load companies
var gameHeaderDeveloperLabel = document.getElementById('gamedeveloper_label');
var gameHeaderDeveloperLogo = document.getElementById('gamedev_logo');
var gameDeveloperLabel = document.getElementById('gamesummary_developer');
var gamePublisherLabel = document.getElementById('gamesummary_publishers');
var gameDeveloperLoaded = false;
var gamePublisherLoaded = false;
if (result.involvedCompanies) {
ajaxCall('/api/v1/games/' + gameId + '/companies', 'GET', function (result) {
for (var i = 0; i < result.length; i++) {
var companyLabel = document.createElement('span');
companyLabel.className = 'gamegenrelabel';
companyLabel.innerHTML = result[i].company.name;
if (result[i].involvement.developer == true) {
if (gameHeaderDeveloperLabel.innerHTML.length > 0) {
gameHeaderDeveloperLabel += ", ";
}
gameHeaderDeveloperLabel.innerHTML += result[i].company.name;
gameDeveloperLabel.appendChild(companyLabel);
gameDeveloperLoaded = true;
} else {
if (result[i].involvement.publisher == true) {
gamePublisherLabel.appendChild(companyLabel);
gamePublisherLoaded = true;
}
}
}
if (gameDeveloperLoaded == false) {
gameHeaderDeveloperLabel.setAttribute('style', 'display: none;');
gameDeveloperLabel.setAttribute('style', 'display: none;');
}
if (gamePublisherLoaded == false) {
gamePublisherLabel.setAttribute('style', 'display: none;');
}
});
} else {
gameHeaderDeveloperLabel.setAttribute('style', 'display: none;');
gameHeaderDeveloperLogo.setAttribute('style', 'display: none;');
gameDeveloperLabel.setAttribute('style', 'display: none;');
gamePublisherLabel.setAttribute('style', 'display: none;');
}
// load cover
var gameSummaryCover = document.getElementById('gamesummary_cover');
var gameImage = document.createElement('img');
@@ -133,6 +192,22 @@
gameSummaryRatings.setAttribute('style', 'display: none;');
}
// load genres
var gameSummaryGenres = document.getElementById('gamesumarry_genres');
if (result.genres) {
ajaxCall('/api/v1/Games/' + gameId + '/genre', 'GET', function (result) {
for (var i = 0; i < result.length; i++) {
var genreLabel = document.createElement('span');
genreLabel.className = 'gamegenrelabel';
genreLabel.innerHTML = result[i].name;
gameSummaryGenres.appendChild(genreLabel);
}
});
} else {
gameSummaryGenres.setAttribute('style', 'display: none;');
}
// load screenshots
var gameScreenshots = document.getElementById('gamescreenshots');
if (result.screenshots || result.videos) {

View File

@@ -70,4 +70,9 @@ function showDialog(dialogPage, variables) {
modalVariables = variables;
$('#modal-content').load('/pages/dialogs/' + dialogPage + '.html');
}
function randomIntFromInterval(min, max) { // min and max included
var rand = Math.floor(Math.random() * (max - min + 1) + min);
return rand;
}

View File

@@ -240,6 +240,16 @@ input[id='filter_panel_search'] {
z-index: -100;
}
#bgImage_Opacity {
background: rgba(56, 56, 56, 0.7);
position: fixed;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
z-index: -90;
}
#gamepage {
top: 0px;
bottom: 0;
@@ -255,7 +265,6 @@ input[id='filter_panel_search'] {
padding-left: 20px;
padding-right: 20px;
padding-bottom: 20px;
background: rgba(56, 56, 56, 0.7);
}
#mainbody {
@@ -275,6 +284,11 @@ input[id='filter_panel_search'] {
width: 100%;
}
.gamegenrelabel {
display: block;
white-space: pre;
}
.rating_image {
display: inline-block;
max-width: 64px;
@@ -420,4 +434,13 @@ th {
color: white;
text-decoration: underline;
cursor: pointer;
}
#gamedev_logo {
float: right;
max-height: 48px;
}
#gamedeveloper_label {
font-size: 16px;
}

View File

@@ -308,6 +308,13 @@ namespace gaseous_tools
return MetadataPath;
}
public string LibraryMetadataDirectory_Company(Company company)
{
string MetadataPath = Path.Combine(LibraryMetadataDirectory, "Companies", company.Slug);
if (!Directory.Exists(MetadataPath)) { Directory.CreateDirectory(MetadataPath); }
return MetadataPath;
}
public string LibrarySignatureImportDirectory
{
get

View File

@@ -118,6 +118,61 @@ CREATE TABLE `collection` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `company`
--
DROP TABLE IF EXISTS `company`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `company` (
`id` bigint NOT NULL,
`changedate` datetime DEFAULT NULL,
`changedatecategory` int DEFAULT NULL,
`changedcompanyid` bigint DEFAULT NULL,
`checksum` varchar(45) DEFAULT NULL,
`country` int DEFAULT NULL,
`createdat` datetime DEFAULT NULL,
`description` longtext,
`developed` json DEFAULT NULL,
`logo` bigint DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`parent` bigint DEFAULT NULL,
`published` json DEFAULT NULL,
`slug` varchar(100) DEFAULT NULL,
`startdate` datetime DEFAULT NULL,
`startdatecategory` int DEFAULT NULL,
`updatedat` datetime DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
`websites` json DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `companylogo`
--
DROP TABLE IF EXISTS `companylogo`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `companylogo` (
`id` bigint NOT NULL,
`alphachannel` tinyint(1) DEFAULT NULL,
`animated` tinyint(1) DEFAULT NULL,
`checksum` varchar(45) DEFAULT NULL,
`height` int DEFAULT NULL,
`imageid` varchar(45) DEFAULT NULL,
`url` varchar(255) DEFAULT NULL,
`width` int DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `cover`
--
@@ -348,6 +403,30 @@ CREATE TABLE `genre` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `involvedcompany`
--
DROP TABLE IF EXISTS `involvedcompany`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `involvedcompany` (
`id` bigint NOT NULL,
`checksum` varchar(45) DEFAULT NULL,
`company` bigint DEFAULT NULL,
`createdat` datetime DEFAULT NULL,
`developer` tinyint(1) DEFAULT NULL,
`game` bigint DEFAULT NULL,
`porting` tinyint(1) DEFAULT NULL,
`publisher` tinyint(1) DEFAULT NULL,
`supporting` tinyint(1) DEFAULT NULL,
`updatedat` datetime DEFAULT NULL,
`dateAdded` datetime DEFAULT NULL,
`lastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `platform`
--