Merge pull request #258 from zkldi/zkldi/issue-249-Session-View-Count

Session View Count
This commit is contained in:
zkldi
2021-07-29 01:39:06 +01:00
committed by GitHub
6 changed files with 57 additions and 6 deletions
+4 -4
View File
@@ -84,7 +84,7 @@ dependencies:
redis: 3.1.2
rimraf: 3.0.2
safe-json-stringify: 1.2.0
tachi-common: github.com/zkldi/tachi-common/606ef49825d0e7b649a0b50899d162d603c2c9e2_ts-node@10.0.0+typescript@4.3.4
tachi-common: github.com/zkldi/tachi-common/42a4da4ced2934d73b862f31a38814a0cc0a16f0_ts-node@10.0.0+typescript@4.3.4
typescript: 4.3.4
winston: 3.3.3
@@ -4226,9 +4226,9 @@ packages:
engines: {node: '>=6'}
dev: true
github.com/zkldi/tachi-common/606ef49825d0e7b649a0b50899d162d603c2c9e2_ts-node@10.0.0+typescript@4.3.4:
resolution: {tarball: https://codeload.github.com/zkldi/tachi-common/tar.gz/606ef49825d0e7b649a0b50899d162d603c2c9e2}
id: github.com/zkldi/tachi-common/606ef49825d0e7b649a0b50899d162d603c2c9e2
github.com/zkldi/tachi-common/42a4da4ced2934d73b862f31a38814a0cc0a16f0_ts-node@10.0.0+typescript@4.3.4:
resolution: {tarball: https://codeload.github.com/zkldi/tachi-common/tar.gz/42a4da4ced2934d73b862f31a38814a0cc0a16f0}
id: github.com/zkldi/tachi-common/42a4da4ced2934d73b862f31a38814a0cc0a16f0
name: tachi-common
version: 0.1.0
dependencies:
+2
View File
@@ -26,6 +26,7 @@ import {
BMSCourseDocument,
ImportLockDocument,
UGPTSettings,
SessionViewDocument,
} from "tachi-common";
import monk, { TMiddleware } from "monk";
import { MONGO_CONNECTION_URL, MONGO_DATABASE_NAME } from "lib/setup/config";
@@ -144,6 +145,7 @@ const db = {
tables: monkDB.get<TableDocument>("tables"),
"game-settings": monkDB.get<UGPTSettings>("game-settings"),
"game-stats-snapshots": monkDB.get<UserGameStatsSnapshot>("game-stats-snapshots"),
"session-view-cache": monkDB.get<SessionViewDocument>("session-view-cache"),
};
export default db;
+5
View File
@@ -4,6 +4,7 @@ import { IndexOptions } from "mongodb";
import { ValidDatabases } from "tachi-common";
import CreateLogCtx from "lib/logger/logger";
import { CONF_INFO } from "lib/setup/config";
import { ONE_DAY } from "lib/constants/time";
const logger = CreateLogCtx(__filename);
@@ -80,6 +81,10 @@ const staticIndexes: Partial<Record<ValidDatabases, Index[]>> = {
"api-tokens": [index({ token: 1 }, UNIQUE), index({ userID: 1 })],
tables: [index({ tableID: 1 }, UNIQUE), index({ game: 1, playtype: 1 })],
"game-stats-snapshots": [index({ timestamp: 1, userID: 1, game: 1, playtype: 1 }, UNIQUE)],
"session-view-cache": [
index({ sessionID: 1, ip: 1 }, UNIQUE),
index({ timestamp: 1 }, { expireAfterSeconds: ONE_DAY / 1000 }),
],
};
const indexes: Partial<Record<ValidDatabases, Index[]>> = staticIndexes;
@@ -133,6 +133,7 @@ function CreateSession(
timeStarted: groupScores[0].timeAchieved!,
timeEnded: groupScores[groupScores.length - 1].timeAchieved!,
calculatedData,
views: 0,
};
}
@@ -1,6 +1,7 @@
import { RequestHandler } from "express";
import db from "external/mongo/db";
import { SYMBOL_TachiAPIAuth, SYMBOL_TachiData } from "lib/constants/tachi";
import { ONE_DAY } from "lib/constants/time";
import { AssignToReqTachiData } from "utils/req-tachi-data";
export const GetSessionFromParam: RequestHandler = async (req, res, next) => {
@@ -33,3 +34,41 @@ export const RequireOwnershipOfSession: RequestHandler = (req, res, next) => {
return next();
};
export const UpdateSessionViewcount: RequestHandler = async (req, res, next) => {
const session = req[SYMBOL_TachiData]!.sessionDoc!;
// we don't need to actually check timestamp - this collection expires documents every 24hours.
const hasViewedRecently = await db["session-view-cache"].findOne({
sessionID: session.sessionID,
ip: req.ip,
});
if (hasViewedRecently) {
return next();
}
await db["session-view-cache"].insert([
{
sessionID: session.sessionID,
ip: req.ip,
timestamp: Date.now(),
},
]);
await db.sessions.update(
{
sessionID: session.sessionID,
},
{
$inc: {
views: 1,
},
}
);
// increment locally so that the right state is shown to the end user.
session.views++;
return next();
};
@@ -4,7 +4,11 @@ import { SYMBOL_TachiData } from "lib/constants/tachi";
import { RequirePermissions } from "server/middleware/auth";
import prValidate from "server/middleware/prudence-validate";
import p from "prudence";
import { GetSessionFromParam, RequireOwnershipOfSession } from "./middleware";
import {
GetSessionFromParam,
RequireOwnershipOfSession,
UpdateSessionViewcount,
} from "./middleware";
import { GetUserWithID } from "utils/user";
const router: Router = Router({ mergeParams: true });
@@ -16,7 +20,7 @@ router.use(GetSessionFromParam);
*
* @name GET /api/v1/sessions/:sessionID
*/
router.get("/", async (req, res) => {
router.get("/", UpdateSessionViewcount, async (req, res) => {
const session = req[SYMBOL_TachiData]!.sessionDoc!;
const scores = await db.scores.find({