Allow callers to pass either a raw Steam app ID or a full store URL (e.g. https://store.steampowered.com/app/730/...) in req.body.steamId. In create() in controllers/games.js: - normalize input into a local steamId variable: if the value includes store.steampowered.com, extract the numeric ID via match(/\d+/)[0], otherwise use the value as-is - use the normalized steamId for both duplicate checks: user-scoped lookup (steamId + accessedBy.user) and global lookup This lets users paste a copied store link directly without manually stripping the app ID, while keeping existing raw-ID behavior unchanged.
299 lines
8.2 KiB
JavaScript
299 lines
8.2 KiB
JavaScript
// noinspection DuplicatedCode
|
|
|
|
import Game from "../models/Game.js";
|
|
import steamScraper from "../scripts/scraper.js";
|
|
import asyncHandler from "../middleware/async.js";
|
|
import ErrorResponse from "../utils/errorResponse.js";
|
|
import { decode, isValid } from "js-base64";
|
|
|
|
const checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
|
|
const checkForTwelveRegExp = new RegExp("^[0-9a-fA-F]{12}$");
|
|
/**
|
|
* games.js
|
|
*
|
|
* @description :: Server-side logic for managing games.
|
|
*/
|
|
|
|
/**
|
|
* gameController.list()
|
|
*/
|
|
export const list = asyncHandler(async (req, res, next) => {
|
|
const data = res.advancedResults.data;
|
|
if (data[0]?.accessedBy) {
|
|
for (let i = 0; i < data.length; i++) {
|
|
for (let x = 0; x < data[i].accessedBy.length; x++) {
|
|
if (data[i].accessedBy[x].user.toString() !== req.user.id)
|
|
data[i].accessedBy.splice(x, 1);
|
|
}
|
|
}
|
|
}
|
|
return res.status(200).json(res.advancedResults);
|
|
});
|
|
|
|
/**
|
|
* gameController.show()
|
|
*/
|
|
export const show = asyncHandler(async (req, res, next) => {
|
|
const { id } = req.params;
|
|
|
|
const gameId =
|
|
id === id.match(checkForTwelveRegExp) || id.match(checkForHexRegExp)
|
|
? "_id"
|
|
: "steamId";
|
|
|
|
const game = await Game.findOne({ [gameId]: id });
|
|
|
|
if (!game)
|
|
return next(
|
|
new ErrorResponse(`Game not found with id of ${req.params.id}`, 404),
|
|
);
|
|
|
|
if (
|
|
!game.accessedBy
|
|
.map((x) => x.user.toString() === req.user.id)
|
|
.includes(true)
|
|
)
|
|
return next(
|
|
new ErrorResponse(
|
|
`You do not have permission to access Game ID ${req.params.id}`,
|
|
401,
|
|
),
|
|
);
|
|
|
|
const userGame = await Game.findOne({ [gameId]: id }).select(
|
|
"-createdBy -__v",
|
|
);
|
|
|
|
for (let i = 0; i < userGame.accessedBy.length; i++) {
|
|
if (userGame.accessedBy[i].user.toString() !== req.user.id)
|
|
userGame.accessedBy.splice(i, 1);
|
|
}
|
|
|
|
res.status(200).json({ success: true, data: userGame });
|
|
});
|
|
|
|
/**
|
|
* gameController.create()
|
|
*/
|
|
export const create = asyncHandler(async (req, res, next) => {
|
|
let oldGame;
|
|
let steamId;
|
|
|
|
if (req.body.steamId.includes("store.steampowered.com"))
|
|
steamId = req.body.steamId.match(/\d+/)[0];
|
|
else steamId = req.body.steamId;
|
|
|
|
if (req.body.shortDesc && isValid(req.body.shortDesc))
|
|
req.body.shortDesc = decode(req.body.shortDesc);
|
|
if (req.body.reviews && isValid(req.body.reviews))
|
|
req.body.reviews = decode(req.body.reviews);
|
|
if (req.body.summary && isValid(req.body.summary))
|
|
req.body.summary = decode(req.body.summary);
|
|
isValid(req.body.systemRequirements?.windows?.minimum)
|
|
? (req.body.systemRequirements.windows.minimum = decode(
|
|
req.body.systemRequirements.windows.minimum,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.windows?.recommended)
|
|
? (req.body.systemRequirements.windows.recommended = decode(
|
|
req.body.systemRequirements.windows.recommended,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.mac?.minimum)
|
|
? (req.body.systemRequirements.mac.minimum = decode(
|
|
req.body.systemRequirements.mac.minimum,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.mac?.recommended)
|
|
? (req.body.systemRequirements.mac.recommended = decode(
|
|
req.body.systemRequirements.mac.recommended,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.linux?.minimum)
|
|
? (req.body.systemRequirements.linux.minimum = decode(
|
|
req.body.systemRequirements.linux.minimum,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.linux?.recommended)
|
|
? (req.body.systemRequirements.linux.recommended = decode(
|
|
req.body.systemRequirements.linux.recommended,
|
|
))
|
|
: "";
|
|
|
|
steamId.length > 0
|
|
? (oldGame = await Game.findOne({
|
|
steamId: steamId,
|
|
"accessedBy.user": req.user.id,
|
|
}))
|
|
: (oldGame = await Game.findOne({
|
|
title: req.body.title,
|
|
"accessedBy.user": req.user.id,
|
|
}));
|
|
|
|
if (oldGame)
|
|
return next(
|
|
new ErrorResponse(
|
|
`The game ${oldGame.title} already exists in users account.`,
|
|
400,
|
|
),
|
|
);
|
|
|
|
steamId.length > 0
|
|
? (oldGame = await Game.findOne({ steamId: steamId }))
|
|
: (oldGame = await Game.findOne({ title: req.body.title }));
|
|
|
|
if (oldGame) {
|
|
oldGame.accessedBy.push({
|
|
user: req.user.id,
|
|
store: req.body.accessedBy[0].store,
|
|
playStatus: req.body.accessedBy[0].playStatus,
|
|
soundtrack: req.body.accessedBy[0].soundtrack,
|
|
rating: req.body.accessedBy[0].rating,
|
|
});
|
|
|
|
oldGame.lastModifiedBy = req.user.id;
|
|
|
|
await oldGame.save();
|
|
return res.status(200).json({
|
|
success: true,
|
|
data: oldGame,
|
|
});
|
|
}
|
|
|
|
req.body.createdBy = req.user.id;
|
|
req.body.lastModifiedBy = req.user.id;
|
|
req.body.accessedBy[0].user = req.user.id;
|
|
const data =
|
|
req.body.scrape === true ? await steamScraper(req.body) : req.body;
|
|
|
|
const game = await Game.create(data);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: game,
|
|
});
|
|
});
|
|
|
|
/**
|
|
* gameController.update()
|
|
*/
|
|
export const update = asyncHandler(async (req, res, next) => {
|
|
const { id } = req.params;
|
|
|
|
const gameId =
|
|
id === id.match(checkForTwelveRegExp) || id.match(checkForHexRegExp)
|
|
? "_id"
|
|
: "steamId";
|
|
|
|
if (req.body.shortDesc && isValid(req.body.shortDesc))
|
|
req.body.shortDesc = decode(req.body.shortDesc);
|
|
if (req.body.reviews && isValid(req.body.reviews))
|
|
req.body.reviews = decode(req.body.reviews);
|
|
if (req.body.summary && isValid(req.body.summary))
|
|
req.body.summary = decode(req.body.summary);
|
|
isValid(req.body.systemRequirements?.windows?.minimum)
|
|
? (req.body.systemRequirements.windows.minimum = decode(
|
|
req.body.systemRequirements.windows.minimum,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.windows?.recommended)
|
|
? (req.body.systemRequirements.windows.recommended = decode(
|
|
req.body.systemRequirements.windows.recommended,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.mac?.minimum)
|
|
? (req.body.systemRequirements.mac.minimum = decode(
|
|
req.body.systemRequirements.mac.minimum,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.mac?.recommended)
|
|
? (req.body.systemRequirements.mac.recommended = decode(
|
|
req.body.systemRequirements.mac.recommended,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.linux?.minimum)
|
|
? (req.body.systemRequirements.linux.minimum = decode(
|
|
req.body.systemRequirements.linux.minimum,
|
|
))
|
|
: "";
|
|
isValid(req.body.systemRequirements?.linux?.recommended)
|
|
? (req.body.systemRequirements.linux.recommended = decode(
|
|
req.body.systemRequirements.linux.recommended,
|
|
))
|
|
: "";
|
|
|
|
let game = await Game.findOne({
|
|
[gameId]: id,
|
|
"accessedBy.user": req.user.id,
|
|
});
|
|
|
|
if (!game)
|
|
return next(
|
|
new ErrorResponse(`A game with the id of ${id} does not exist`, 401),
|
|
);
|
|
|
|
game = await Game.findOneAndUpdate(
|
|
{ [gameId]: id, "accessedBy.user": req.user.id },
|
|
{
|
|
$set: {
|
|
series: req.body.series,
|
|
intel: req.body.intel,
|
|
genre: req.body.genre,
|
|
wine: req.body.wine,
|
|
lastModifiedBy: req.user.id,
|
|
"accessedBy.$.store": req.body.accessedBy[0].store,
|
|
"accessedBy.$.playStatus": req.body.accessedBy[0].playStatus,
|
|
"accessedBy.$.soundtrack": req.body.accessedBy[0].soundtrack,
|
|
"accessedBy.$.rating": req.body.accessedBy[0].rating,
|
|
},
|
|
},
|
|
{ new: true, runValidators: true },
|
|
);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: game,
|
|
});
|
|
});
|
|
|
|
/**
|
|
* gameController.remove()
|
|
*/
|
|
export const remove = asyncHandler(async (req, res, next) => {
|
|
const { id } = req.params;
|
|
|
|
const gameId =
|
|
id === id.match(checkForTwelveRegExp) || id.match(checkForHexRegExp)
|
|
? "_id"
|
|
: "steamId";
|
|
|
|
let game = await Game.findOne({
|
|
[gameId]: id,
|
|
"accessedBy.user": req.user.id,
|
|
});
|
|
|
|
if (!game)
|
|
return next(
|
|
new ErrorResponse(`A game with the id of ${id} does not exist`, 401),
|
|
);
|
|
|
|
if (game.accessedBy.length > 1) {
|
|
await Game.findOneAndUpdate(
|
|
{ [gameId]: id, "accessedBy.user": req.user.id },
|
|
{
|
|
$pull: {
|
|
accessedBy: { user: req.user.id },
|
|
},
|
|
},
|
|
{ new: true, runValidators: true },
|
|
);
|
|
} else {
|
|
await Game.findOneAndDelete({ [gameId]: id });
|
|
}
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: {},
|
|
});
|
|
});
|