diff --git a/config/locales/en.json b/config/locales/en.json index b51bb02..d878da2 100644 --- a/config/locales/en.json +++ b/config/locales/en.json @@ -21,7 +21,12 @@ "in_seconds": "in {{seconds}} seconds", "indexing": "Indexing in progress, if the list is missing something please try reloading in a few minutes", "non_game_filter": "Non-game content filter is active", - "displaying_results": "Displaying results {{start}} through {{end}}." + "no_description": "No descrption found.", + "no_metadata": "No metadata found.", + "displaying_results": "Displaying results {{start}} through {{end}}.", + "released": "Released", + "region": "Region", + "platform": "Platform" }, "about": { "title": "About", @@ -40,6 +45,10 @@ "credits": { "created_by": "Search engine created by", "view_github": "View project on GitHub" + }, + "metadata": { + "title": "Metadata Information", + "description": "This website pulls metadata information about games from {{metadata_source}}. This information is pulled on search. Search queries may be slow until metadata has been cached in the database." } }, "settings": { @@ -69,6 +78,10 @@ "hide_non_game": { "label": "Hide Non-Game Content", "tooltip": "Filters out ROM hacks, patches, artwork, and other non-game content from search results." + }, + "use_old_results": { + "label": "Old Search", + "tooltip": "Redirects your search to the old table formatted results. These will load faster as they will ignore pulling metadata." } }, "save": "Save Settings" diff --git a/lib/metadatasearch.js b/lib/metadatasearch.js index 610ff13..8f9b434 100644 --- a/lib/metadatasearch.js +++ b/lib/metadatasearch.js @@ -48,6 +48,8 @@ export default class MetadataSearch { "game_localizations.region.name", "platforms.name", "game_type.type", + "screenshots.image_id", + "videos.video_id" ]; async setupClient() { @@ -143,6 +145,8 @@ export default class MetadataSearch { string = string.replace("Nintendo Satellaview", "Satellaview"); string = string.replace("Sony PlayStation", "PlayStation"); string = string.replace("Microsoft Xbox", "Xbox"); + string = string.replace("Commodore 64", "Commodore C64"); + string = string.replace("Commodore Amiga", "Amiga"); return [where("platforms.name", op, string, WhereFlags.CONTAINS)]; } @@ -208,16 +212,13 @@ export default class MetadataSearch { return combined; } catch (error) { console.error("Error getting metadata:", error); + return [] } } async addMetadataToDb(metadata, game) { try { - let md = await Metadata.findOne({ - where: { - id: metadata.id, - }, - }); + let md = await Metadata.findByPk(metadata.id); if (!md) { md = await Metadata.build( { @@ -237,6 +238,8 @@ export default class MetadataSearch { platforms: JSON.stringify( metadata.platforms?.map((platform) => platform.name) ), + screenshots: JSON.stringify(metadata.screenshots?.map((ss) => ss.image_id)), + videos: JSON.stringify(metadata.videos?.map((v) => v.video_id)) }, { returning: true, diff --git a/lib/models/metadata.js b/lib/models/metadata.js index 7cc42f4..cfeaded 100644 --- a/lib/models/metadata.js +++ b/lib/models/metadata.js @@ -39,6 +39,12 @@ export default function (sequelize) { }, platforms: { type: DataTypes.STRING + }, + screenshots: { + type: DataTypes.STRING + }, + videos:{ + type: DataTypes.STRING } }, { indexes: [ diff --git a/lib/services/elasticsearch.js b/lib/services/elasticsearch.js index a46f50e..f63858f 100644 --- a/lib/services/elasticsearch.js +++ b/lib/services/elasticsearch.js @@ -102,7 +102,7 @@ export async function bulkIndexFiles(files) { filenamekws: file.filenamekws, categorykws: file.categorykws, regionkws: file.regionkws, - nongame: file.nongame + nongame: file.nongame, }, ]); @@ -168,7 +168,7 @@ export async function search(query, options) { // Fetch full records from PostgreSQL for the search results const ids = response.hits.hits.map((hit) => hit._id); const fullRecords = await File.findAll({ - where: { id: ids }, + where: { id: ids } }); // Create a map of full records by id @@ -179,7 +179,7 @@ export async function search(query, options) { // Build results with full PostgreSQL records let results = response.hits.hits.map((hit) => ({ - file:{ + file: { ...recordMap[hit._id]?.dataValues, }, score: hit._score, @@ -187,7 +187,7 @@ export async function search(query, options) { })); //Filter out anything that couldn't be found in postgres - results = results.filter(result => result.file.filename) + results = results.filter((result) => result.file.filename); const elapsed = timer.elapsedSeconds(); return { diff --git a/lib/taskqueue.js b/lib/taskqueue.js index 49d70a0..98664af 100644 --- a/lib/taskqueue.js +++ b/lib/taskqueue.js @@ -1,6 +1,11 @@ export default class TaskQueue { - constructor(maxTasksPerSecond = 4, maxSimultaneousTasks = 8) { + constructor( + maxTasksPerSecond = 4, + maxSimultaneousTasks = 8, + maxQueueLength = 20 + ) { this.maxTasksPerSecond = maxTasksPerSecond; + this.maxQueueLength = maxQueueLength; this.maxSimultaneousTasks = maxSimultaneousTasks; this.queue = []; this.processing = false; @@ -9,8 +14,12 @@ export default class TaskQueue { this.tasksWaiting = 0; } - async enqueue(taskFunction, that=this, ...args) { + async enqueue(taskFunction, that = this, ...args) { return new Promise((resolve, reject) => { + if (this.queue.length >= this.maxQueueLength) { + reject(new Error("Queue is full. Maximum queue size exceeded.")); + return; + } this.queue.push({ taskFunction, that, diff --git a/server.js b/server.js index cdf3de0..a8acf59 100644 --- a/server.js +++ b/server.js @@ -171,7 +171,11 @@ app.get("/", function (req, res) { app.get("/search", async function (req, res) { let query = req.query.q ? req.query.q : ""; let pageNum = parseInt(req.query.p); - let urlPrefix = encodeURI(`/search?s=${req.query.s}&q=${req.query.q}&p=`); + let urlPrefix = encodeURI( + `/search?s=${req.query.s}&q=${req.query.q}${ + req.query.o ? "&o=" + req.query.o : "" + }&p=` + ); pageNum = pageNum ? pageNum : 1; let settings = {}; try { @@ -198,9 +202,13 @@ app.get("/search", async function (req, res) { } settings.pageSize = settings.useOldResults ? 100 : 10; settings.page = pageNum - 1; + settings.sort = req.query.o || ""; let results = await search.findAllMatches(query, settings); debugPrint(results); - let metas = await metadataSearch.queueGetGamesMetadata(results.db); + let metas = []; + if (!settings.useOldResults) { + metas = await metadataSearch.queueGetGamesMetadata(results.db); + } if (results.count && pageNum == 1) { queryCount += 1; await QueryCount.update({ count: queryCount }, { where: { id: 1 } }); @@ -301,6 +309,29 @@ app.get("/play/:id", async function (req, res) { res.render(indexPage, options); }); +app.get("/info/:id", async function (req, res) { + //set header to allow video embed + res.setHeader("Cross-Origin-Embedder-Policy", "unsafe-non"); + if (!metadataSearch.authorized) { + res.redirect("/"); + return; + } + let romId = parseInt(req.params.id); + let romFile = await search.findIndex(romId); + let romInfo = await metadataSearch.queueGetGamesMetadata([romFile]); + + if (!romInfo.length) { + res.redirect("/"); + return; + } + let options = { + romFile: romInfo[0], + }; + let page = "info"; + options = buildOptions(page, options); + res.render(indexPage, options); +}); + app.get("/proxy-rom/:id", async function (req, res, next) { // Block access if emulator is disabled if (process.env.EMULATOR_ENABLED !== "true") { diff --git a/views/pages/about.ejs b/views/pages/about.ejs index 2084c88..7961ed5 100644 --- a/views/pages/about.ejs +++ b/views/pages/about.ejs @@ -16,6 +16,11 @@ <%= __('about.donate') %> +
<%= __('about.metadata.description', {metadata_source: 'IGDB'}) %>
+<%= file.category %>
+<%- stars%> (<%= Math.floor(metadata.rating) %>%)
+Developed by: <%= JSON.parse(metadata.developers).join(", ") %>
+Published by: <%= JSON.parse(metadata.publishers).join(", ") %>
+Release date: <%= metadata.releasedate %>
+Region: <%= file.region %>
+Genre: <%= JSON.parse(metadata.genre).join(", ") %>
+Gameplay modes: <%= JSON.parse(metadata.gamemodes).join(", ") %>
+<%= metadata.description %>
++ Download + <% if (process.env.EMULATOR_ENABLED === 'true') { %> + <% if (isEmulatorCompatible(file.category)) { %> + <%= __('emulator.play')%> <% } else { %> + + <% } + }%> +