diff --git a/gaseous-server/Classes/Metadata/Company.cs b/gaseous-server/Classes/Metadata/Company.cs new file mode 100644 index 0000000..a00e183 --- /dev/null +++ b/gaseous-server/Classes/Metadata/Company.cs @@ -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 RetVal = _GetCompanies(SearchUsing.id, Id); + return RetVal.Result; + } + } + + public static Company GetCompanies(string Slug) + { + Task RetVal = _GetCompanies(SearchUsing.slug, Slug); + return RetVal.Result; + } + + private static async Task _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(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 GetObjectFromServer(string WhereClause) + { + // get Companies metadata + var results = await igdb.QueryAsync(IGDBClient.Endpoints.Companies, query: fieldList + " " + WhereClause + ";"); + if (results.Length > 0) + { + var result = results.First(); + + return result; + } + else + { + return null; + } + + } + } +} + diff --git a/gaseous-server/Classes/Metadata/CompanyLogos.cs b/gaseous-server/Classes/Metadata/CompanyLogos.cs new file mode 100644 index 0000000..88ec456 --- /dev/null +++ b/gaseous-server/Classes/Metadata/CompanyLogos.cs @@ -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 RetVal = _GetCompanyLogo(SearchUsing.id, Id, LogoPath); + return RetVal.Result; + } + } + + public static CompanyLogo GetCompanyLogo(string Slug, string LogoPath) + { + Task RetVal = _GetCompanyLogo(SearchUsing.slug, Slug, LogoPath); + return RetVal.Result; + } + + private static async Task _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(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 GetObjectFromServer(string WhereClause, string LogoPath) + { + // get CompanyLogo metadata + var results = await igdb.QueryAsync(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 + } + } +} + diff --git a/gaseous-server/Classes/Metadata/Games.cs b/gaseous-server/Classes/Metadata/Games.cs index f83a351..09a6be6 100644 --- a/gaseous-server/Classes/Metadata/Games.cs +++ b/gaseous-server/Classes/Metadata/Games.cs @@ -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 gamesToFetch = new List(); @@ -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) diff --git a/gaseous-server/Classes/Metadata/InvolvedCompany.cs b/gaseous-server/Classes/Metadata/InvolvedCompany.cs new file mode 100644 index 0000000..0d6c3f9 --- /dev/null +++ b/gaseous-server/Classes/Metadata/InvolvedCompany.cs @@ -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 RetVal = _GetInvolvedCompanies(SearchUsing.id, Id); + return RetVal.Result; + } + } + + public static InvolvedCompany GetInvolvedCompanies(string Slug) + { + Task RetVal = _GetInvolvedCompanies(SearchUsing.slug, Slug); + return RetVal.Result; + } + + private static async Task _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(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 GetObjectFromServer(string WhereClause) + { + // get InvolvedCompanies metadata + try + { + var results = await igdb.QueryAsync(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; + } + } + } +} + diff --git a/gaseous-server/Classes/Metadata/Storage.cs b/gaseous-server/Classes/Metadata/Storage.cs index d2fb9be..1f10712 100644 --- a/gaseous-server/Classes/Metadata/Storage.cs +++ b/gaseous-server/Classes/Metadata/Storage.cs @@ -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(id: (long)dataRow[property.Name]); break; + case "company": + objectToStore = new IdentityOrValue(id: (long)dataRow[property.Name]); + break; case "cover": objectToStore = new IdentityOrValue(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; diff --git a/gaseous-server/Controllers/GamesController.cs b/gaseous-server/Controllers/GamesController.cs index 93e4d51..5ec5efc 100644 --- a/gaseous-server/Controllers/GamesController.cs +++ b/gaseous-server/Controllers/GamesController.cs @@ -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), 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 genreObjects = new List(); + if (gameObject.Genres != null) + { + foreach (long genreId in gameObject.Genres.Ids) + { + genreObjects.Add(Classes.Metadata.Genres.GetGenres(genreId)); + } + } + + List sortedGenreObjects = genreObjects.OrderBy(o => o.Name).ToList(); + + return Ok(sortedGenreObjects); + } + else + { + return NotFound(); + } + } + catch + { + return NotFound(); + } + } + + [HttpGet] + [Route("{GameId}/companies")] + [ProducesResponseType(typeof(List>), 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> icObjects = new List>(); + 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 companyData = new Dictionary(); + 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), 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> icObjects = new List>(); + 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 companyData = new Dictionary(); + 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), StatusCodes.Status200OK)] diff --git a/gaseous-server/wwwroot/pages/game.html b/gaseous-server/wwwroot/pages/game.html index 56ffe81..6682078 100644 --- a/gaseous-server/wwwroot/pages/game.html +++ b/gaseous-server/wwwroot/pages/game.html @@ -1,8 +1,11 @@ -
+
+
+

+

Also known as:

@@ -11,6 +14,15 @@
+
+

Genres

+
+
+

Developers

+
+
+

Publishers

+

Age Ratings

@@ -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) { diff --git a/gaseous-server/wwwroot/scripts/main.js b/gaseous-server/wwwroot/scripts/main.js index 07b9ac7..94789ac 100644 --- a/gaseous-server/wwwroot/scripts/main.js +++ b/gaseous-server/wwwroot/scripts/main.js @@ -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; } \ No newline at end of file diff --git a/gaseous-server/wwwroot/styles/style.css b/gaseous-server/wwwroot/styles/style.css index 80e91c5..ebf6388 100644 --- a/gaseous-server/wwwroot/styles/style.css +++ b/gaseous-server/wwwroot/styles/style.css @@ -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; } \ No newline at end of file diff --git a/gaseous-tools/Config.cs b/gaseous-tools/Config.cs index 05ac47f..a2292dd 100644 --- a/gaseous-tools/Config.cs +++ b/gaseous-tools/Config.cs @@ -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 diff --git a/gaseous-tools/Database/MySQL/gaseous-1000.sql b/gaseous-tools/Database/MySQL/gaseous-1000.sql index b44033b..ee50687 100644 --- a/gaseous-tools/Database/MySQL/gaseous-1000.sql +++ b/gaseous-tools/Database/MySQL/gaseous-1000.sql @@ -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` --