Skip to content

Commit

Permalink
V2.0.0.1 (#253)
Browse files Browse the repository at this point in the history
* Update packages, update queries in API.

Tons of bug fixes and hopefully resolves client headers not being sent.

* Update api.ts

Include a debug log to check the body of requests being sent in.

* Update case statement due to missing breaks.

De-duplicate match check codes and move them up to the api.

Adjust onplayerdeath to take care of any issues with sql pains.

* Include default case to throw 400.

* Find a better way for concurrent match restores.

Update to implement round_end.

Update demos to properly upload to folder.

Formatting.

Update map stats on round end as well.

* Remove unused import in backupapi

Fixed demoapi to rename the demo to zip as we are zipping the file, just not renaming the extension.

Update veto picks in maplflow service to choose the correct maps from the in-game veto pool.

Move `updatePlayerStats` to the Utils class as it's used in seriesflow and mapflow services.

Update seriesflowservice to update the stats a final time to ensure data correctness at the end of a map.

* Update map flow to catch an edge case where player stats do not exist yet.
  • Loading branch information
PhlexPlexico authored Jun 26, 2023
1 parent 7686954 commit fff92cd
Show file tree
Hide file tree
Showing 12 changed files with 442 additions and 433 deletions.
29 changes: 29 additions & 0 deletions migrations/development/20230625215254-get5db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";

var dbm;
var type;
var seed;
var async = require("async");

/**
* We receive the dbmigrate dependency from dbmigrate initially.
* This enables us to not have to rely on NODE_PATH.
*/
exports.setup = function (options, seedLink) {
dbm = options.dbmigrate;
type = dbm.dataType;
seed = seedLink;
};

exports.up = function (db, callback) {
return db.runSql(
"ALTER TABLE `map_stats` ADD COLUMN round_restored tinyint(1) DEFAULT 0 AFTER end_time;"
);
};

exports.down = function (db, callback) {
return db.removeColumn("map_stats", "round_restored");
};
exports._meta = {
version: 24
};
29 changes: 29 additions & 0 deletions migrations/production/20230625215254-get5db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";

var dbm;
var type;
var seed;
var async = require("async");

/**
* We receive the dbmigrate dependency from dbmigrate initially.
* This enables us to not have to rely on NODE_PATH.
*/
exports.setup = function (options, seedLink) {
dbm = options.dbmigrate;
type = dbm.dataType;
seed = seedLink;
};

exports.up = function (db, callback) {
return db.runSql(
"ALTER TABLE `map_stats` ADD COLUMN round_restored tinyint(1) DEFAULT 0 AFTER end_time;"
);
};

exports.down = function (db, callback) {
return db.removeColumn("map_stats", "round_restored");
};
exports._meta = {
version: 24
};
29 changes: 29 additions & 0 deletions migrations/test/20230625215254-get5db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";

var dbm;
var type;
var seed;
var async = require("async");

/**
* We receive the dbmigrate dependency from dbmigrate initially.
* This enables us to not have to rely on NODE_PATH.
*/
exports.setup = function (options, seedLink) {
dbm = options.dbmigrate;
type = dbm.dataType;
seed = seedLink;
};

exports.up = function (db, callback) {
return db.runSql(
"ALTER TABLE `map_stats` ADD COLUMN round_restored tinyint(1) DEFAULT 0 AFTER end_time;"
);
};

exports.down = function (db, callback) {
return db.removeColumn("map_stats", "round_restored");
};
exports._meta = {
version: 24
};
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "g5api",
"version": "2.0.0.0",
"version": "2.0.0.1",
"private": true,
"type": "module",
"licenses": [
Expand Down Expand Up @@ -89,7 +89,7 @@
"passport": "^0.6.0",
"passport-local": "^1.0.0",
"passport-steam": "^1.0.17",
"pm2": "^5.2.0",
"pm2": "^5.3.0",
"randomstring": "^1.2.2",
"rcon": "^1.1.0",
"redis": "^4.3.0",
Expand All @@ -103,10 +103,10 @@
"@types/express": "^4.17.17",
"@types/node": "^20.2.5",
"@types/steamapi": "^2.2.2",
"jest": "^29.1.0",
"jest": "^29.5.0",
"jest-ts-webcompat-resolver": "^1.0.0",
"jsdoc": "^4.0.2",
"nodemon": "^2.0.15",
"nodemon": "^2.0.22",
"passport-mock-strategy": "^2.0.0",
"redis-mock": "^0.56.3",
"supertest": "^6.3.3",
Expand Down
116 changes: 66 additions & 50 deletions src/routes/v2/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import { Get5_OnMatchPausedUnpaused } from "../../types/map_flow/Get5_OnMatchPau
import { Get5_OnPlayerDeath } from "../../types/map_flow/Get5_OnPlayerDeath.js";
import { Get5_OnBombEvent } from "../../types/map_flow/Get5_OnBombEvent.js";
import { Get5_OnRoundStart } from "../../types/map_flow/Get5_OnRoundStart.js";
import Utils from "../../utility/utils.js";
import { Get5_OnRoundEnd } from "../../types/map_flow/Get5_OnRoundEnd.js";

/** Basic Rate limiter.
* @const
Expand Down Expand Up @@ -83,14 +85,13 @@ const basicRateLimit = rateLimit({
* $ref: '#/components/responses/Error'
*/
router.post("/", basicRateLimit, async (req, res) => {
let matchId: string = req.body?.matchId;
let matchId: string = req.body?.matchid;
const apiKey: string | undefined = req.get("Authorization");
const eventType: Get5_OnEvent = req.body;

try {
if (!apiKey) {
res.status(401).send({ message: "API key not provided." });
return;
return res.status(401).send({ message: "API key not provided." });
}

if (!matchId) {
Expand All @@ -106,81 +107,96 @@ router.post("/", basicRateLimit, async (req, res) => {
matchId = dbMatchKey[0].id;
}

const matchApiCheck: number = await Utils.checkApiKey(apiKey, matchId);
if (eventType.event == "demo_upload_ended") {
// Ignore demo_upload_ended event.
return res.status(200).send({message: "Success"});
} else if (eventType.event == "series_end") {
// let forfeit: number = event.
// Match is finalized, this is usually called after a cancel so we just ignore the value with a 200 response.
if (matchApiCheck == 2) {
return res.status(200).send({
message:
"Match already finalized or and invalid API key has been given."
});
} else if (matchApiCheck == 1) {
console.error(
"Match already finalized or and invalid API key has been given."
);
return res.status(401).send({
message:
"Match already finalized or and invalid API key has been given."
});
}
} else {
if (matchApiCheck == 2 || matchApiCheck == 1) {
console.error(
"Match already finalized or and invalid API key has been given."
);
return res.status(401).send({
message:
"Match already finalized or and invalid API key has been given."
});
}
}

switch (eventType.event) {
// Series Flows
case "map_picked":
SeriesFlowService.OnMapPicked(
apiKey,
req.body as Get5_OnMapPicked,
res
);
SeriesFlowService.OnMapPicked(req.body as Get5_OnMapPicked, res);
break;
case "map_vetoed":
SeriesFlowService.OnMapVetoed(
apiKey,
req.body as Get5_OnMapVetoed,
res
);
SeriesFlowService.OnMapVetoed(req.body as Get5_OnMapVetoed, res);
break;
case "side_picked":
SeriesFlowService.OnSidePicked(
apiKey,
req.body as Get5_OnSidePicked,
res
);
SeriesFlowService.OnSidePicked(req.body as Get5_OnSidePicked, res);
break;
case "backup_loaded":
SeriesFlowService.OnBackupRestore(
apiKey,
req.body as Get5_OnBackupRestore,
res
);
break;
case "map_result":
SeriesFlowService.OnMapResult(
apiKey,
req.body as Get5_OnMapResult,
res
);
SeriesFlowService.OnMapResult(req.body as Get5_OnMapResult, res);
break;
case "series_end":
SeriesFlowService.OnSeriesResult(
apiKey,
req.body as Get5_OnSeriesResult,
res
);
SeriesFlowService.OnSeriesResult(req.body as Get5_OnSeriesResult, res);
break;
// Map Flows
case "going_live":
MapFlowService.OnGoingLive(apiKey, req.body as Get5_OnGoingLive, res);
MapFlowService.OnGoingLive(req.body as Get5_OnGoingLive, res);
break;
case "round_start":
MapFlowService.OnRoundStart(apiKey, req.body as Get5_OnRoundStart, res);
MapFlowService.OnRoundStart(req.body as Get5_OnRoundStart, res);
break;
case "round_end":
MapFlowService.OnRoundEnd(req.body as Get5_OnRoundEnd, res);
break;
case "player_death":
MapFlowService.OnPlayerDeath(
apiKey,
req.body as Get5_OnPlayerDeath,
res
);
MapFlowService.OnPlayerDeath(req.body as Get5_OnPlayerDeath, res);
break;
case "bomb_planted":
MapFlowService.OnBombEvent(
apiKey,
req.body as Get5_OnBombEvent,
res,
false
);
MapFlowService.OnBombEvent(req.body as Get5_OnBombEvent, res, false);
break;
case "bomb_defused":
MapFlowService.OnBombEvent(
apiKey,
req.body as Get5_OnBombEvent,
res,
true
);
MapFlowService.OnBombEvent(req.body as Get5_OnBombEvent, res, true);
break;
case "game_paused":
MapFlowService.OnMatchPausedUnPaused(
apiKey,
req.body as Get5_OnMatchPausedUnpaused,
res
);
break;
case "game_unpaused":
MapFlowService.OnMatchPausedUnPaused(
apiKey,
req.body as Get5_OnMatchPausedUnpaused,
res
);
break;
default:
res.status(400).send({message: `Event ${eventType.event} is not implemented.`});
break;
}
// Responses are taken care of in the case statements.
return;
Expand Down
1 change: 0 additions & 1 deletion src/routes/v2/backupapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { RowDataPacket } from "mysql2";
* @const
* Global Server Sent Emitter class for real time data.
*/
import GlobalEmitter from "../../utility/emitter.js";
import { existsSync, mkdirSync, writeFile } from "fs";

/** Express module
Expand Down
16 changes: 6 additions & 10 deletions src/routes/v2/demoapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,16 @@ router.post("/", async (req: Request, res: Response) => {
const demoFilename: string | undefined = req.get("Get5-FileName");
// Check that the values have made it across.
if (!apiKey || !matchId || !mapNumber || !demoFilename) {
res
return res
.status(401)
.send({ message: "API key, Match ID, or Map Number not provided." });
return;
}
// Check if our API key is correct.
const matchApiCheck: number = await Utils.checkApiKey(apiKey, matchId);
if (matchApiCheck == 1) {
res.status(401).send({
return res.status(401).send({
message: "Invalid API key has been given."
});
return;
}
// Begin file compression into public/demos and check time variance of 8 minutes.
let zip: JSZip = new JSZip();
Expand All @@ -126,8 +124,7 @@ router.post("/", async (req: Request, res: Response) => {
mapNumber
]);
if (mapInfo.length == 0) {
res.status(404).send({ message: "Failed to find map stats object." });
return;
return res.status(404).send({ message: "Failed to find map stats object." });
}
let currentDate: Date = new Date();
let endTimeMs: Date = new Date(mapInfo[0].end_time);
Expand All @@ -137,15 +134,14 @@ router.post("/", async (req: Request, res: Response) => {
let minuteDifference = Math.floor(timeDifference / 1000 / 60);
let updateStmt: object;
if (minuteDifference > 8) {
res.status(401).json({ message: "Demo can no longer be uploaded." });
return;
return res.status(401).json({ message: "Demo can no longer be uploaded." });
}

zip.file(demoFilename, req.body, { binary: true });
zip
.generateAsync({ type: "nodebuffer", compression: "DEFLATE" })
.then((buf) => {
writeFile("public/demos" + demoFilename, buf, "binary", function (err) {
writeFile("public/demos/" + demoFilename.replace(".dem", ".zip"), buf, "binary", function (err) {
if (err) {
console.error(err);
throw err;
Expand All @@ -159,7 +155,7 @@ router.post("/", async (req: Request, res: Response) => {
updateStmt = await db.buildUpdateStatement(updateStmt);

sqlString = "UPDATE map_stats SET ? WHERE id = ?";
await db.query(sqlString, [mapInfo[0].id]);
await db.query(sqlString, [updateStmt, mapInfo[0].id]);
GlobalEmitter.emit("demoUpdate");
res.status(200).send({message: "Success"});
return;
Expand Down
1 change: 0 additions & 1 deletion src/routes/vetoes.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ router.get("/:match_id/stream", async (req, res, next) => {
res.write(vetoEventString);

req.on("close", () => {
console.log("\n\nCLOSED\n\n");
GlobalEmitter.removeListener("vetoUpdate", vetoStreamData);
res.end();
});
Expand Down
Loading

0 comments on commit fff92cd

Please sign in to comment.