From 3371c6a099e9d910b61b827edcc14bba0958ab5d Mon Sep 17 00:00:00 2001 From: Michael C Date: Wed, 7 Jul 2021 00:22:05 -0400 Subject: [PATCH 01/24] add reason to getLockCategories --- src/routes/getLockCategories.ts | 12 ++++++++--- src/routes/getLockCategoriesByHash.ts | 9 ++++++-- test/cases/getLockCategories.ts | 18 +++++++++------- test/cases/getLockCategoriesByHash.ts | 30 ++++++++++++++++++--------- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/routes/getLockCategories.ts b/src/routes/getLockCategories.ts index e27acea..7267b86 100644 --- a/src/routes/getLockCategories.ts +++ b/src/routes/getLockCategories.ts @@ -13,11 +13,17 @@ export async function getLockCategories(req: Request, res: Response): Promise entry.category); + const categories = row.map(item => item.category); + if (categories.length === 0 || !categories[0]) return res.sendStatus(404); + // Get existing lock categories markers + const reasons = row.map(item => item.reason); + let longReason = ""; + // set longReason if current length is longer + reasons.forEach((e) => { if (e.length > longReason.length) longReason = e; }); return res.send({ + reason: longReason, categories }); } catch (err) { diff --git a/src/routes/getLockCategoriesByHash.ts b/src/routes/getLockCategoriesByHash.ts index 90772b2..3f76c59 100644 --- a/src/routes/getLockCategoriesByHash.ts +++ b/src/routes/getLockCategoriesByHash.ts @@ -7,13 +7,15 @@ import { Category, VideoID, VideoIDHash } from "../types/segments.model"; interface LockResultByHash { videoID: VideoID, hash: VideoIDHash, + reason: string, categories: Category[] } interface DBLock { videoID: VideoID, hash: VideoIDHash, - category: Category + category: Category, + reason: string, } const mergeLocks = (source: DBLock[]) => { @@ -22,12 +24,15 @@ const mergeLocks = (source: DBLock[]) => { // videoID already exists const destMatch = dest.find(s => s.videoID === obj.videoID); if (destMatch) { + // override longer reason + if (destMatch.reason.length > obj.reason.length) destMatch.reason = obj.reason; // push to categories destMatch.categories.push(obj.category); } else { dest.push({ videoID: obj.videoID, hash: obj.hash, + reason: obj.reason, categories: [obj.category] }); } @@ -45,7 +50,7 @@ export async function getLockCategoriesByHash(req: Request, res: Response): Prom try { // Get existing lock categories markers - const lockedRows = await db.prepare('all', 'SELECT "videoID", "hashedVideoID" as "hash", "category" from "lockCategories" where "hashedVideoID" LIKE ?', [hashPrefix + '%']) as DBLock[]; + const lockedRows = await db.prepare('all', 'SELECT "videoID", "hashedVideoID" as "hash", "category", "reason" from "lockCategories" where "hashedVideoID" LIKE ?', [hashPrefix + '%']) as DBLock[]; if (lockedRows.length === 0 || !lockedRows[0]) return res.sendStatus(404); // merge all locks return res.send(mergeLocks(lockedRows)); diff --git a/test/cases/getLockCategories.ts b/test/cases/getLockCategories.ts index 177710e..e9c7796 100644 --- a/test/cases/getLockCategories.ts +++ b/test/cases/getLockCategories.ts @@ -9,19 +9,19 @@ describe('getLockCategories', () => { const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)'; await db.prepare("run", insertVipUserQuery, [getHash("VIPUser-getLockCategories")]); - const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category") VALUES (?, ?, ?)'; - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'sponsor']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'interaction']); + const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") VALUES (?, ?, ?, ?)'; + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'sponsor', '1-short']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'interaction', '2-longer-reason']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-2', 'preview']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-2', 'preview', '2-reason']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-3', 'nonmusic']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-3', 'nonmusic', '3-reason']); }); it('Should update the database version when starting the application', async () => { const version = (await db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version'])).value; - if (version > 1) return; - else return 'Version isn\'t greater than 1. Version is ' + version; + if (version > 20) return; + else return 'Version isn\'t greater than 20. Version is ' + version; }); it('Should be able to get multiple locks', (done: Done) => { @@ -37,6 +37,8 @@ describe('getLockCategories', () => { done(`Returned incorrect category "${data.categories[0]}"`); } else if (data.categories[1] !== "interaction") { done(`Returned incorrect category "${data.categories[1]}"`); + } else if (data.reason !== "1-longer-reason") { + done(`Returned incorrect reason "${data.reason}"`); } else { done(); // pass } @@ -56,6 +58,8 @@ describe('getLockCategories', () => { done('Returned incorrect number of locks "' + data.categories.length + '"'); } else if (data.categories[0] !== "preview") { done(`Returned incorrect category "${data.categories[0].category}"`); + } else if (data.reason !== "2-reason") { + done(`Returned incorrect reason "${data.reason}"`); } else { done(); // pass } diff --git a/test/cases/getLockCategoriesByHash.ts b/test/cases/getLockCategoriesByHash.ts index 585c08e..5a89ef0 100644 --- a/test/cases/getLockCategoriesByHash.ts +++ b/test/cases/getLockCategoriesByHash.ts @@ -9,23 +9,23 @@ describe('getLockCategoriesByHash', () => { const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)'; await db.prepare("run", insertVipUserQuery, [getHash("VIPUser-getLockCategories")]); - const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "hashedVideoID") VALUES (?, ?, ?, ?)'; - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'sponsor', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'interaction', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']); + const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "reaspm", "hashedVideoID") VALUES (?, ?, ?, ?)'; + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'sponsor', '1-reason-short', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'interaction', '1-longer-reason', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-2', 'preview', 'dff09120437b4bd594dffae5f3cde3cfc5f6099fb01d0ef4051919b2908d9a50']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-2', 'preview', '2-reason', 'dff09120437b4bd594dffae5f3cde3cfc5f6099fb01d0ef4051919b2908d9a50']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-3', 'nonmusic', 'bf1b122fd5630e0df8626d00c4a95c58954ad715e5595b0f75a19ac131e28928']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-3', 'nonmusic', '3-reason', 'bf1b122fd5630e0df8626d00c4a95c58954ad715e5595b0f75a19ac131e28928']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-1', 'outro', 'b05a20424f24a53dac1b059fb78d861ba9723645026be2174c93a94f9106bb35']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-2', 'intro', 'b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-2', 'preview', 'b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-1', 'outro', 'fake1-reason', 'b05a20424f24a53dac1b059fb78d861ba9723645026be2174c93a94f9106bb35']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-2', 'intro', 'fake2-longer-reason', 'b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-2', 'preview', 'fake2-short', 'b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450']); }); it('Database should be greater or equal to version 18', async () => { const version = (await db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version'])).value; - if (version >= 18) return; - else return 'Version isn\'t greater than 18. Version is ' + version; + if (version >= 20) return; + else return 'Version isn\'t greater than 20. Version is ' + version; }); it('Should be able to get multiple locks in one object', (done: Done) => { @@ -45,6 +45,8 @@ describe('getLockCategoriesByHash', () => { done(`Returned incorrect category "${data[0].categories[0]}"`); } else if (data[0].categories[1] !== "interaction") { done(`Returned incorrect category "${data[0].categories[1]}"`); + } else if (data[0].reason !== "1-longer-reason") { + done(`Returned incorrect reason "${data[0].reason}"`); } else { done(); // pass } @@ -70,6 +72,8 @@ describe('getLockCategoriesByHash', () => { done(`Returned incorrect number of categories "${data[0].categories.length}"`); } else if (data[0].categories[0] !== "preview") { done(`Returned incorrect category "${data[0].categories[0]}"`); + } else if (data[0].reason !== "2-reason") { + done(`Returned incorrect reason "${data[0].reason}"`); } else { done(); // pass } @@ -95,6 +99,8 @@ describe('getLockCategoriesByHash', () => { done(`Returned incorrect number of categories "${data[0].categories.length}"`); } else if (data[0].categories[0] !== "nonmusic") { done(`Returned incorrect category "${data[0].categories[0]}"`); + } else if (data[0].reason !== "3-reason") { + done(`Returned incorrect reason "${data[0].reason}"`); } else { done(); // pass } @@ -130,6 +136,10 @@ describe('getLockCategoriesByHash', () => { done(`Returned incorrect category "${data[1].category}"`); } else if (data[1].categories[1] !== "preview") { done(`Returned incorrect category "${data[1].category}"`); + } else if (data[0].reason !== "fake1-reason") { + done(`Returned incorrect reason "${data[0].reason}"`); + } else if (data[1].reason !== "fake2-longer-reason") { + done(`Returned incorrect reason "${data[1].reason}"`); } else { done(); // pass } From 50e7f4af8ef83d8e800a9716b012f00f4b0ff249 Mon Sep 17 00:00:00 2001 From: Michael C Date: Wed, 7 Jul 2021 00:51:08 -0400 Subject: [PATCH 02/24] use .reduce from @HaiDang666 --- src/routes/getLockCategories.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/routes/getLockCategories.ts b/src/routes/getLockCategories.ts index 7267b86..d7707f9 100644 --- a/src/routes/getLockCategories.ts +++ b/src/routes/getLockCategories.ts @@ -14,16 +14,14 @@ export async function getLockCategories(req: Request, res: Response): Promise item.category); if (categories.length === 0 || !categories[0]) return res.sendStatus(404); - // Get existing lock categories markers - const reasons = row.map(item => item.reason); - let longReason = ""; - // set longReason if current length is longer - reasons.forEach((e) => { if (e.length > longReason.length) longReason = e; }); + // Get longest lock reason + const reason = row.map(item => item.reason) + .reduce((a,b) => (a.length > b.length) ? a : b); return res.send({ - reason: longReason, + reason, categories }); } catch (err) { From 4a835d53062c19170ac5ab548885d24f32046d72 Mon Sep 17 00:00:00 2001 From: Michael C Date: Wed, 7 Jul 2021 16:44:05 -0400 Subject: [PATCH 03/24] fix typos --- src/routes/getLockCategoriesByHash.ts | 2 +- test/cases/getLockCategories.ts | 2 +- test/cases/getLockCategoriesByHash.ts | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/routes/getLockCategoriesByHash.ts b/src/routes/getLockCategoriesByHash.ts index 3f76c59..0027888 100644 --- a/src/routes/getLockCategoriesByHash.ts +++ b/src/routes/getLockCategoriesByHash.ts @@ -25,7 +25,7 @@ const mergeLocks = (source: DBLock[]) => { const destMatch = dest.find(s => s.videoID === obj.videoID); if (destMatch) { // override longer reason - if (destMatch.reason.length > obj.reason.length) destMatch.reason = obj.reason; + if (obj.reason.length > destMatch.reason.length) destMatch.reason = obj.reason; // push to categories destMatch.categories.push(obj.category); } else { diff --git a/test/cases/getLockCategories.ts b/test/cases/getLockCategories.ts index e9c7796..8566ab7 100644 --- a/test/cases/getLockCategories.ts +++ b/test/cases/getLockCategories.ts @@ -11,7 +11,7 @@ describe('getLockCategories', () => { const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") VALUES (?, ?, ?, ?)'; await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'sponsor', '1-short']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'interaction', '2-longer-reason']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-1', 'interaction', '1-longer-reason']); await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLock-2', 'preview', '2-reason']); diff --git a/test/cases/getLockCategoriesByHash.ts b/test/cases/getLockCategoriesByHash.ts index 5a89ef0..756f2ae 100644 --- a/test/cases/getLockCategoriesByHash.ts +++ b/test/cases/getLockCategoriesByHash.ts @@ -9,9 +9,9 @@ describe('getLockCategoriesByHash', () => { const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)'; await db.prepare("run", insertVipUserQuery, [getHash("VIPUser-getLockCategories")]); - const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "reaspm", "hashedVideoID") VALUES (?, ?, ?, ?)'; + const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason", "hashedVideoID") VALUES (?, ?, ?, ?, ?)'; await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'sponsor', '1-reason-short', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']); - await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'interaction', '1-longer-reason', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']); + await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-1', 'interaction', '1-reason-longer', '67a654898fda3a5541774aea345796c7709982bb6018cb08d22a18eeddccc1d0']); await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'getLockHash-2', 'preview', '2-reason', 'dff09120437b4bd594dffae5f3cde3cfc5f6099fb01d0ef4051919b2908d9a50']); @@ -22,7 +22,7 @@ describe('getLockCategoriesByHash', () => { await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), 'fakehash-2', 'preview', 'fake2-short', 'b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450']); }); - it('Database should be greater or equal to version 18', async () => { + it('Database should be greater or equal to version 20', async () => { const version = (await db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version'])).value; if (version >= 20) return; else return 'Version isn\'t greater than 20. Version is ' + version; @@ -45,7 +45,7 @@ describe('getLockCategoriesByHash', () => { done(`Returned incorrect category "${data[0].categories[0]}"`); } else if (data[0].categories[1] !== "interaction") { done(`Returned incorrect category "${data[0].categories[1]}"`); - } else if (data[0].reason !== "1-longer-reason") { + } else if (data[0].reason !== "1-reason-longer") { done(`Returned incorrect reason "${data[0].reason}"`); } else { done(); // pass From 5e58efb07f9e5b0330926a9c3e9315305755181c Mon Sep 17 00:00:00 2001 From: Michael C Date: Wed, 7 Jul 2021 17:36:52 -0400 Subject: [PATCH 04/24] early 400 on skipSegments --- src/routes/getSkipSegments.ts | 4 ++++ src/routes/getSkipSegmentsByHash.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/routes/getSkipSegments.ts b/src/routes/getSkipSegments.ts index af322ad..08618e5 100644 --- a/src/routes/getSkipSegments.ts +++ b/src/routes/getSkipSegments.ts @@ -275,6 +275,10 @@ async function chooseSegments(segments: DBSegment[], max: number): Promise { const videoID = req.query.videoID as VideoID; + if (!videoID) { + res.status(400).send("videoID not specified"); + return false; + } // Default to sponsor // If using params instead of JSON, only one category can be pulled const categories: Category[] = req.query.categories diff --git a/src/routes/getSkipSegmentsByHash.ts b/src/routes/getSkipSegmentsByHash.ts index eb2c99c..1518f09 100644 --- a/src/routes/getSkipSegmentsByHash.ts +++ b/src/routes/getSkipSegmentsByHash.ts @@ -5,7 +5,7 @@ import { ActionType, Category, SegmentUUID, Service, VideoIDHash } from '../type export async function getSkipSegmentsByHash(req: Request, res: Response): Promise { let hashPrefix = req.params.prefix as VideoIDHash; - if (!hashPrefixTester(req.params.prefix)) { + if (!req.params.prefix || !hashPrefixTester(req.params.prefix)) { return res.status(400).send("Hash prefix does not match format requirements."); // Exit early on faulty prefix } hashPrefix = hashPrefix.toLowerCase() as VideoIDHash; From 9088d9fb9e0c6413ec026aeb66441f2b8aba083c Mon Sep 17 00:00:00 2001 From: Michael C Date: Wed, 7 Jul 2021 17:37:40 -0400 Subject: [PATCH 05/24] additional tests --- test/cases/getLockCategoriesByHash.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/cases/getLockCategoriesByHash.ts b/test/cases/getLockCategoriesByHash.ts index 585c08e..d31f7cf 100644 --- a/test/cases/getLockCategoriesByHash.ts +++ b/test/cases/getLockCategoriesByHash.ts @@ -173,4 +173,22 @@ describe('getLockCategoriesByHash', () => { }) .catch(() => ("couldn't call endpoint")); }); + + it('should return 400 if hash too short', (done: Done) => { + fetch(getbaseURL() + '/api/lockCategories/00') + .then(res => { + assert.strictEqual(res.status, 400); + done(); + }) + .catch(err => done(err)); + }); + + it('should return 400 if no hash specified', (done: Done) => { + fetch(getbaseURL() + '/api/lockCategories/') + .then(res => { + assert.strictEqual(res.status, 400); + done(); + }) + .catch(err => done(err)); + }); }); From 596dbf4ac8c9622b52db0c66167c6df9f029c816 Mon Sep 17 00:00:00 2001 From: Michael C Date: Wed, 7 Jul 2021 17:39:16 -0400 Subject: [PATCH 06/24] 404 tests --- test/cases/getSkipSegments.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/cases/getSkipSegments.ts b/test/cases/getSkipSegments.ts index 06e64f2..979d33b 100644 --- a/test/cases/getSkipSegments.ts +++ b/test/cases/getSkipSegments.ts @@ -397,4 +397,13 @@ describe('getSkipSegments', () => { }) .catch(() => done("Couldn't call endpoint")); }); + + it('Should get 400 if no videoID passed in', (done: Done) => { + fetch(getbaseURL() + '/api/skipSegments') + .then(async res => { + assert.strictEqual(res.status, 400); + done(); + }) + .catch(err => done(err)); + }); }); From 178ed1e5af850be00e10527e79bedfd4333c61bf Mon Sep 17 00:00:00 2001 From: Michael C Date: Wed, 7 Jul 2021 03:47:08 -0400 Subject: [PATCH 07/24] replace if tests with assert --- test/cases/getIsUserVIP.ts | 25 +- test/cases/getLockCategories.ts | 62 ++-- test/cases/getLockCategoriesByHash.ts | 169 ++++------ test/cases/getSavedTimeForUser.ts | 15 +- test/cases/getSegmentInfo.ts | 305 +++++++---------- test/cases/getSkipSegments.ts | 437 +++++++++++------------- test/cases/getSkipSegmentsByHash.ts | 318 ++++++++---------- test/cases/getUserID.ts | 417 ++++++++++------------- test/cases/getUserInfo.ts | 138 ++++---- test/cases/lockCategoriesRecords.ts | 223 ++++--------- test/cases/oldGetSponsorTime.ts | 47 ++- test/cases/oldSubmitSponsorTimes.ts | 38 +-- test/cases/postClearCache.ts | 21 +- test/cases/postPurgeAllSegments.ts | 6 +- test/cases/postSkipSegments.ts | 460 +++++++++++--------------- test/cases/postWarning.ts | 63 ++-- test/cases/segmentShift.ts | 33 +- test/cases/setUsername.ts | 82 ++--- test/cases/shadowBanUser.ts | 98 +++--- test/cases/unBan.ts | 52 +-- test/cases/voteOnSponsorTime.ts | 366 +++++++------------- test/test.ts | 10 +- 22 files changed, 1344 insertions(+), 2041 deletions(-) diff --git a/test/cases/getIsUserVIP.ts b/test/cases/getIsUserVIP.ts index 7f491c3..a293fb8 100644 --- a/test/cases/getIsUserVIP.ts +++ b/test/cases/getIsUserVIP.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {getbaseURL, Done} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('getIsUserVIP', () => { before((done: Done) => { @@ -11,20 +12,20 @@ describe('getIsUserVIP', () => { it('Should be able to get a 200', (done: Done) => { fetch(getbaseURL() + "/api/isUserVIP?userID=supertestman") .then(res => { - if (res.status !== 200) done("non 200: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 200, "response should be 200"); + done(); }) - .catch(() => done("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should get a 400 if no userID', (done: Done) => { fetch(getbaseURL() + "/api/isUserVIP") .then(res => { - if (res.status !== 400) done("non 400: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 400, "response should be 400"); + done(); }) - .catch(() => done("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should say a VIP is a VIP', (done: Done) => { @@ -33,11 +34,11 @@ describe('getIsUserVIP', () => { if (res.status !== 200) done("non 200: " + res.status); else { const data = await res.json(); - if (data.vip === true) done(); // pass - else done("Result was non-vip when should have been vip"); + assert.strictEqual(data.vip, true); + done(); } }) - .catch(() => done("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should say a normal user is not a VIP', (done: Done) => { @@ -46,10 +47,10 @@ describe('getIsUserVIP', () => { if (res.status !== 200) done("non 200: " + res.status); else { const data = await res.json(); - if (data.vip === false) done(); // pass - else done("Result was vip when should have been non-vip"); + assert.strictEqual(data.vip, false); + done(); } }) - .catch(() => done("couldn't call endpoint")); + .catch(err => done(err)); }); }); diff --git a/test/cases/getLockCategories.ts b/test/cases/getLockCategories.ts index 177710e..eab9950 100644 --- a/test/cases/getLockCategories.ts +++ b/test/cases/getLockCategories.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {getHash} from '../../src/utils/getHash'; import {db} from '../../src/databases/databases'; +import assert from 'assert'; describe('getLockCategories', () => { @@ -27,58 +28,51 @@ describe('getLockCategories', () => { it('Should be able to get multiple locks', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories?videoID=getLock-1') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.categories.length !== 2) { - done(`Returned incorrect number of locks "${data.categories.length}"`); - } else if (data.categories[0] !== "sponsor") { - done(`Returned incorrect category "${data.categories[0]}"`); - } else if (data.categories[1] !== "interaction") { - done(`Returned incorrect category "${data.categories[1]}"`); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + const expected = { + categories: [ + "sponsor", + "interaction" + ] + }; + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get single locks', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories?videoID=getLock-2') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.categories.length !== 1) { - done('Returned incorrect number of locks "' + data.categories.length + '"'); - } else if (data.categories[0] !== "preview") { - done(`Returned incorrect category "${data.categories[0].category}"`); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + const expected = { + categories: [ + "preview" + ] + }; + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should return 404 if no lock exists', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories?videoID=getLock-0') .then(res => { - if (res.status !== 404) done('non 404 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should return 400 if no videoID specified', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories') .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); }); diff --git a/test/cases/getLockCategoriesByHash.ts b/test/cases/getLockCategoriesByHash.ts index 585c08e..7734e58 100644 --- a/test/cases/getLockCategoriesByHash.ts +++ b/test/cases/getLockCategoriesByHash.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {getHash} from '../../src/utils/getHash'; import {db} from '../../src/databases/databases'; +import assert from 'assert'; describe('getLockCategoriesByHash', () => { @@ -31,146 +32,116 @@ describe('getLockCategoriesByHash', () => { it('Should be able to get multiple locks in one object', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories/67a65') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done(`Returned incorrect number of videos "${data.length}"`); - } else if (data[0].videoID !== "getLockHash-1") { - done(`Returned incorrect videoID "${data[0].videoID}"`); - } else if (data[0].hash !== getHash("getLockHash-1", 1)) { - done(`Returned incorrect hash "${data[0].hash}"`); - } else if (data[0].categories[0] !== "sponsor") { - done(`Returned incorrect category "${data[0].categories[0]}"`); - } else if (data[0].categories[1] !== "interaction") { - done(`Returned incorrect category "${data[0].categories[1]}"`); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + const expected = [{ + videoID: "getLockHash-1", + hash: getHash("getLockHash-1", 1), + categories: [ + "sponsor", + "interaction" + ] + }]; + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get single lock', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories/dff09') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done('Returned incorrect number of videos "' + data.length + '"'); - } else if (data[0].videoID !== "getLockHash-2") { - done(`Returned incorrect videoID "${data[0].videoID}"`); - } else if (data[0].hash !== getHash("getLockHash-2", 1)) { - done(`Returned incorrect hashedVideoID hash "${data[0].hash}"`); - } else if (data[0].categories.length !== 1) { - done(`Returned incorrect number of categories "${data[0].categories.length}"`); - } else if (data[0].categories[0] !== "preview") { - done(`Returned incorrect category "${data[0].categories[0]}"`); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + const expected = [{ + videoID: "getLockHash-2", + hash: getHash("getLockHash-2", 1), + categories: [ + "preview" + ] + }]; + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get by half full hash', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories/bf1b122fd5630e0df8626d00c4a95c58') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done('Returned incorrect number of videos "' + data.length + '"'); - } else if (data[0].videoID !== "getLockHash-3") { - done(`Returned incorrect videoID "${data[0].videoID}"`); - } else if (data[0].hash !== getHash("getLockHash-3", 1)) { - done(`Returned incorrect hashedVideoID hash "${data[0].hash}"`); - } else if (data[0].categories.length !== 1) { - done(`Returned incorrect number of categories "${data[0].categories.length}"`); - } else if (data[0].categories[0] !== "nonmusic") { - done(`Returned incorrect category "${data[0].categories[0]}"`); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + const expected = [{ + videoID: "getLockHash-3", + hash: getHash("getLockHash-3", 1), + categories: [ + "nonmusic" + ] + }]; + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get multiple by similar hash with multiple categories', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories/b05a') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 2) { - done(`Returned incorrect number of locks "${data.length}"`); - } else if (data[0].videoID !== "fakehash-1") { - done(`Returned incorrect videoID "${data[0].videoID}"`); - } else if (data[1].videoID !== "fakehash-2") { - done(`Returned incorrect videoID "${data[1].videoID}"`); - } else if (data[0].hash !== "b05a20424f24a53dac1b059fb78d861ba9723645026be2174c93a94f9106bb35") { - done(`Returned incorrect hashedVideoID hash "${data[0].hash}"`); - } else if (data[1].hash !== "b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450") { - done(`Returned incorrect hashedVideoID hash "${data[1].hash}"`); - } else if (data[0].categories.length !== 1) { - done(`Returned incorrect number of categories "${data[0].categories.length}"`); - } else if (data[1].categories.length !== 2) { - done(`Returned incorrect number of categories "${data[1].categories.length}"`); - } else if (data[0].categories[0] !== "outro") { - done(`Returned incorrect category "${data[0].category}"`); - } else if (data[1].categories[0] !== "intro") { - done(`Returned incorrect category "${data[1].category}"`); - } else if (data[1].categories[1] !== "preview") { - done(`Returned incorrect category "${data[1].category}"`); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + const expected = [{ + videoID: "fakehash-1", + hash: "b05a20424f24a53dac1b059fb78d861ba9723645026be2174c93a94f9106bb35", + categories: [ + "outro" + ] + }, { + videoID: "fakehash-2", + hash: "b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450", + categories: [ + "intro", + "preview" + ] + }]; + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should return 404 once hash prefix varies', (done: Done) => { - fetch(getbaseURL() + '/api/lockCategories/aaaaaa') + fetch(getbaseURL() + '/api/lockCategories/b05aa') .then(res => { - if (res.status !== 404) done('non 404 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should return 404 if no lock exists', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories/aaaaaa') .then(res => { - if (res.status !== 404) done('non 404 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should return 400 if no videoID specified', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories/') .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should return 400 if full hash sent', (done: Done) => { fetch(getbaseURL() + '/api/lockCategories/b05a20424f24a53dac1b059fb78d861ba9723645026be2174c93a94f9106bb35') .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); }); diff --git a/test/cases/getSavedTimeForUser.ts b/test/cases/getSavedTimeForUser.ts index 94405f5..273f151 100644 --- a/test/cases/getSavedTimeForUser.ts +++ b/test/cases/getSavedTimeForUser.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('getSavedTimeForUser', () => { before(async () => { @@ -13,10 +14,16 @@ describe('getSavedTimeForUser', () => { it('Should be able to get a 200', (done: Done) => { fetch(getbaseURL() + "/api/getSavedTimeForUser?userID=testman") - .then(res => { - if (res.status !== 200) done("non 200"); - else done(); // pass + .then(async res => { + const data = await res.json(); + // (end-start)*minute * views + const savedMinutes = ((11-1)/60) * 50; + const expected = { + timeSaved: savedMinutes + }; + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => done("couldn't call endpoint")); + .catch((err) => done(err)); }); }); diff --git a/test/cases/getSegmentInfo.ts b/test/cases/getSegmentInfo.ts index 912619c..56fd4c8 100644 --- a/test/cases/getSegmentInfo.ts +++ b/test/cases/getSegmentInfo.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {db} from '../../src/databases/databases'; import {Done, getbaseURL} from '../utils'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; const ENOENTID = "0".repeat(64); const upvotedID = "a"+"0".repeat(63); @@ -43,231 +44,188 @@ describe('getSegmentInfo', () => { it('Should be able to retreive upvoted segment', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${upvotedID}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data[0].videoID === "upvoted" && data[0].votes === 2) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "upvoted"); + assert.strictEqual(data[0].votes, 2); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to retreive downvoted segment', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${downvotedID}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data[0].videoID === "downvoted" && data[0].votes === -2) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "downvoted"); + assert.strictEqual(data[0].votes, -2); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to retreive locked up segment', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${lockedupID}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data[0].videoID === "locked-up" && data[0].locked === 1 && data[0].votes === 2) { - done(); - } else { - done ("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "locked-up"); + assert.strictEqual(data[0].locked, 1); + assert.strictEqual(data[0].votes, 2); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to retreive infinite vote segment', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${infvotesID}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data[0].videoID === "infvotes" && data[0].votes === 100000) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "infvotes"); + assert.strictEqual(data[0].votes, 100000); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to retreive shadowhidden segment', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${shadowhiddenID}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data[0].videoID === "shadowhidden" && data[0].shadowHidden === 1) { - done(); - } else { - done ("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "shadowhidden"); + assert.strictEqual(data[0].shadowHidden, 1); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to retreive locked down segment', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${lockeddownID}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data[0].videoID === "locked-down" && data[0].votes === -2 && data[0].locked === 1) { - done(); - } else { - done ("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "locked-down"); + assert.strictEqual(data[0].votes, -2); + assert.strictEqual(data[0].locked, 1); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to retreive hidden segment', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${hiddenID}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data[0].videoID === "hidden" && data[0].hidden === 1) { - done(); - } else { - done ("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "hidden"); + assert.strictEqual(data[0].hidden, 1); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to retreive segment with old ID', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${oldID}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data[0].videoID === "oldID" && data[0].votes === 1) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "oldID"); + assert.strictEqual(data[0].votes, 1); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to retreive single segment in array', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUIDs=["${upvotedID}"]`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].videoID === "upvoted" && data[0].votes === 2) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].videoID, "upvoted"); + assert.strictEqual(data[0].votes, 2); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to retreive multiple segments in array', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUIDs=["${upvotedID}", "${downvotedID}"]`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 2 && - (data[0].videoID === "upvoted" && data[0].votes === 2) && - (data[1].videoID === "downvoted" && data[1].votes === -2)) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].videoID, "upvoted"); + assert.strictEqual(data[0].votes, 2); + assert.strictEqual(data[1].videoID, "downvoted"); + assert.strictEqual(data[1].votes, -2); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be possible to send unexpected query parameters', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${upvotedID}&fakeparam=hello&category=sponsor`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data[0].videoID === "upvoted" && data[0].votes === 2) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "upvoted"); + assert.strictEqual(data[0].votes, 2); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should return 400 if array passed to UUID', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=["${upvotedID}", "${downvotedID}"]`) .then(res => { - if (res.status !== 400) done("non 400 respone code: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 400 if bad array passed to UUIDs', (done: Done) => { fetch(getbaseURL() + "/api/segmentInfo?UUIDs=[not-quoted,not-quoted]") .then(res => { - if (res.status !== 400) done("non 404 respone code: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 400 if bad UUID passed', (done: Done) => { fetch(getbaseURL() + "/api/segmentInfo?UUID=notarealuuid") .then(res => { - if (res.status !== 400) done("non 400 respone code: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 400 if bad UUIDs passed in array', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUIDs=["notarealuuid", "anotherfakeuuid"]`) .then(res => { - if (res.status !== 400) done("non 400 respone code: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return good UUID when mixed with bad UUIDs', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUIDs=["${upvotedID}", "anotherfakeuuid"]`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].videoID === "upvoted" && data[0].votes === 2) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].videoID, "upvoted"); + assert.strictEqual(data[0].votes, 2); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should cut off array at 10', function(done: Done) { @@ -275,34 +233,31 @@ describe('getSegmentInfo', () => { const filledIDArray = `["${upvotedID}", "${downvotedID}", "${lockedupID}", "${shadowhiddenID}", "${lockeddownID}", "${hiddenID}", "${fillerID1}", "${fillerID2}", "${fillerID3}", "${fillerID4}", "${fillerID5}"]`; fetch(getbaseURL() + `/api/segmentInfo?UUIDs=${filledIDArray}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - // last segment should be fillerID4 - if (data.length === 10 && data[0].videoID === "upvoted" && data[0].votes === 2 && data[9].videoID === "filler" && data[9].UUID === fillerID4) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 10); + assert.strictEqual(data[0].videoID, "upvoted"); + assert.strictEqual(data[0].votes, 2); + assert.strictEqual(data[9].videoID, "filler"); + assert.strictEqual(data[9].UUID, fillerID4); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should not duplicate reponses', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUIDs=["${upvotedID}", "${upvotedID}", "${upvotedID}", "${upvotedID}", "${upvotedID}", "${upvotedID}", "${upvotedID}", "${upvotedID}", "${upvotedID}", "${upvotedID}", "${downvotedID}"]`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 2 && data[0].videoID === "upvoted" && data[0].votes === 2 && data[1].videoID === "downvoted" && data[1].votes === -2) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].videoID, "upvoted"); + assert.strictEqual(data[0].votes, 2); + assert.strictEqual(data[1].videoID, "downvoted"); + assert.strictEqual(data[1].votes, -2); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 400 if UUID not found', (done: Done) => { @@ -311,41 +266,33 @@ describe('getSegmentInfo', () => { if (res.status !== 400) done("non 400 respone code: " + res.status); else done(); // pass }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to retreive multiple segments with multiple parameters', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${upvotedID}&UUID=${downvotedID}`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 2 && - (data[0].videoID === "upvoted" && data[0].votes === 2) && - (data[1].videoID === "downvoted" && data[1].votes === -2)) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].videoID, "upvoted"); + assert.strictEqual(data[1].videoID, "downvoted"); + assert.strictEqual(data[0].votes, 2); + assert.strictEqual(data[1].votes, -2); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should not parse repeated UUID if UUIDs present', (done: Done) => { fetch(getbaseURL() + `/api/segmentInfo?UUID=${downvotedID}&UUID=${lockedupID}&UUIDs=["${upvotedID}"]`) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && - (data[0].videoID === "upvoted" && data[0].votes === 2)) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data[0].videoID, "upvoted"); + assert.strictEqual(data[0].votes, 2); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); }); diff --git a/test/cases/getSkipSegments.ts b/test/cases/getSkipSegments.ts index 06e64f2..a48fb62 100644 --- a/test/cases/getSkipSegments.ts +++ b/test/cases/getSkipSegments.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {db} from '../../src/databases/databases'; import {Done, getbaseURL} from '../utils'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('getSkipSegments', () => { before(async () => { @@ -29,372 +30,314 @@ describe('getSkipSegments', () => { it('Should be able to get a time by category 1', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&category=sponsor") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0" && data[0].videoDuration === 100) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } - }) - .catch(() => "Couldn't call endpoint"); + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0"); + assert.strictEqual(data[0].videoDuration, 100); + done(); + }) + .catch(err => done(err)); }); it('Should be able to get a time by category and action type', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&category=sponsor&actionType=mute") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].segment[0] === 12 && data[0].segment[1] === 14 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0-2" && data[0].videoDuration === 100) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 12); + assert.strictEqual(data[0].segment[1], 14); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0-2"); + assert.strictEqual(data[0].videoDuration, 100); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to get a time by category and multiple action types', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&category=sponsor&actionType=mute&actionType=skip") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 2 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0" - && data[1].UUID === "1-uuid-0-2" && data[0].videoDuration === 100) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0"); + assert.strictEqual(data[1].UUID, "1-uuid-0-2"); + assert.strictEqual(data[0].videoDuration, 100); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to get a time by category and multiple action types (JSON array)', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments?videoID=testtesttest&category=sponsor&actionTypes=["mute","skip"]') .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 2 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0" - && data[1].UUID === "1-uuid-0-2" && data[0].videoDuration === 100) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0"); + assert.strictEqual(data[1].UUID, "1-uuid-0-2"); + assert.strictEqual(data[0].videoDuration, 100); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to get a time by category for a different service 1', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest2&category=sponsor&service=PeerTube") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0-1" && data[0].videoDuration === 120) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0-1"); + assert.strictEqual(data[0].videoDuration, 120); + done(); }) - .catch(() => "Couldn't call endpoint"); + .catch(err => done(err)); }); it('Should be able to get a time by category 2', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&category=intro") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].segment[0] === 20 && data[0].segment[1] === 33 - && data[0].category === "intro" && data[0].UUID === "1-uuid-2") { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 20); + assert.strictEqual(data[0].segment[1], 33); + assert.strictEqual(data[0].category, "intro"); + assert.strictEqual(data[0].UUID, "1-uuid-2"); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get a time by categories array', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&categories=[\"sponsor\"]") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0" && data[0].videoDuration === 100) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0"); + assert.strictEqual(data[0].videoDuration, 100); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get a time by categories array 2', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&categories=[\"intro\"]") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].segment[0] === 20 && data[0].segment[1] === 33 - && data[0].category === "intro" && data[0].UUID === "1-uuid-2" && data[0].videoDuration === 101) { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 20); + assert.strictEqual(data[0].segment[1], 33); + assert.strictEqual(data[0].category, "intro"); + assert.strictEqual(data[0].UUID, "1-uuid-2"); + assert.strictEqual(data[0].videoDuration, 101); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 404 if all submissions are hidden', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=onlyHiddenSegments") .then(res => { - if (res.status !== 404) done("non 404 respone code: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get multiple times by category', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=multiple&categories=[\"intro\"]") .then(async res => { - if (res.status !== 200)done("Status code was: " + res.status); - else { - const body = await res.text(); - const data = JSON.parse(body); - if (data.length === 2) { - let success = true; - for (const segment of data) { - if ((segment.segment[0] !== 20 || segment.segment[1] !== 33 - || segment.category !== "intro" || segment.UUID !== "1-uuid-7") && - (segment.segment[0] !== 1 || segment.segment[1] !== 11 - || segment.category !== "intro" || segment.UUID !== "1-uuid-6")) { - success = false; - break; - } - } - - if (success) done(); - else done("Received incorrect body: " + body); - } else { - done("Received incorrect body: " + body); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "intro"); + assert.strictEqual(data[0].UUID, "1-uuid-6"); + assert.strictEqual(data[1].segment[0], 20); + assert.strictEqual(data[1].segment[1], 33); + assert.strictEqual(data[1].category, "intro"); + assert.strictEqual(data[1].UUID, "1-uuid-7"); + done(); }) - .catch(err => ("Couldn't call endpoint\n\n" + err)); + .catch(err => done(err)); }); it('Should be able to get multiple times by multiple categories', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&categories=[\"sponsor\", \"intro\"]") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const body = await res.text(); - const data = JSON.parse(body); - if (data.length === 2) { - - let success = true; - for (const segment of data) { - if ((segment.segment[0] !== 20 || segment.segment[1] !== 33 - || segment.category !== "intro" || segment.UUID !== "1-uuid-2") && - (segment.segment[0] !== 1 || segment.segment[1] !== 11 - || segment.category !== "sponsor" || segment.UUID !== "1-uuid-0")) { - success = false; - break; - } - } - - if (success) done(); - else done("Received incorrect body: " + body); - } else { - done("Received incorrect body: " + body); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0"); + assert.strictEqual(data[1].segment[0], 20); + assert.strictEqual(data[1].segment[1], 33); + assert.strictEqual(data[1].category, "intro"); + assert.strictEqual(data[1].UUID, "1-uuid-2"); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be possible to send unexpected query parameters', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&fakeparam=hello&category=sponsor") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const body = await res.text(); - const data = JSON.parse(body); - if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0") { - done(); - } else { - done("Received incorrect body: " + body); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0"); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Low voted submissions should be hidden', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=test3&category=sponsor") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const body = await res.text(); - const data = JSON.parse(body); - if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-4") { - done(); - } else { - done("Received incorrect body: " + body); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-4"); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 404 if no segment found', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=notarealvideo") .then(res => { - if (res.status !== 404) done("non 404 respone code: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 400 if bad categories argument', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&categories=[not-quoted,not-quoted]") .then(res => { - if (res.status !== 400) done("non 400 respone code: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able send a comma in a query param', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest,test&category=sponsor") .then(async res => { - if (res.status !== 200) done ("Status code was: " + res.status); - else { - const body = await res.text(); - const data = JSON.parse(body); - if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-1") { - done(); - } else { - done("Received incorrect body: " + body); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-1"); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should always get locked segment', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=locked&category=intro") .then(async res => { - if (res.status !== 200) done ("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].segment[0] === 20 && data[0].segment[1] === 33 - && data[0].category === "intro" && data[0].UUID === "1-uuid-locked-8") { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 20); + assert.strictEqual(data[0].segment[1], 33); + assert.strictEqual(data[0].category, "intro"); + assert.strictEqual(data[0].UUID, "1-uuid-locked-8"); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get multiple categories with repeating parameters', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&category=sponsor&category=intro") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const body = await res.text(); - const data = JSON.parse(body); - if (data.length === 2) { - - let success = true; - for (const segment of data) { - if ((segment.segment[0] !== 20 || segment.segment[1] !== 33 - || segment.category !== "intro" || segment.UUID !== "1-uuid-2") && - (segment.segment[0] !== 1 || segment.segment[1] !== 11 - || segment.category !== "sponsor" || segment.UUID !== "1-uuid-0")) { - success = false; - break; - } - } - - if (success) done(); - else done("Received incorrect body: " + body); - } else { - done("Received incorrect body: " + body); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0"); + assert.strictEqual(data[1].segment[0], 20); + assert.strictEqual(data[1].segment[1], 33); + assert.strictEqual(data[1].category, "intro"); + assert.strictEqual(data[1].UUID, "1-uuid-2"); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get, categories param overriding repeating category', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&categories=[\"sponsor\"]&category=intro") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const data = await res.json(); - if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0") { - done(); - } else { - done("Received incorrect body: " + (await res.text())); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segment[0], 1); + assert.strictEqual(data[0].segment[1], 11); + assert.strictEqual(data[0].category, "sponsor"); + assert.strictEqual(data[0].UUID, "1-uuid-0"); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get specific segments with requiredSegments', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments?videoID=requiredSegmentVid-raw&requiredSegments=["requiredSegmentVid-raw-2","requiredSegmentVid-raw-3"]') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 2) done("expected 2 segments, got " + body.length); - else if (body[0].UUID !== 'requiredSegmentVid-raw-2' - || body[1].UUID !== 'requiredSegmentVid-raw-3') done("Did not recieve the correct segments\n" + JSON.stringify(body, null, 2)); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].UUID, "requiredSegmentVid-raw-2"); + assert.strictEqual(data[1].UUID, "requiredSegmentVid-raw-3"); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get specific segments with repeating requiredSegment', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments?videoID=requiredSegmentVid-raw&requiredSegment=requiredSegmentVid-raw-2&requiredSegment=requiredSegmentVid-raw-3') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 2) done("expected 2 segments, got " + body.length); - else if (body[0].UUID !== 'requiredSegmentVid-raw-2' - || body[1].UUID !== 'requiredSegmentVid-raw-3') done("Did not recieve the correct segments\n" + JSON.stringify(body, null, 2)); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].UUID, 'requiredSegmentVid-raw-2'); + assert.strictEqual(data[1].UUID, 'requiredSegmentVid-raw-3'); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); }); diff --git a/test/cases/getSkipSegmentsByHash.ts b/test/cases/getSkipSegmentsByHash.ts index d1da36e..e4112ae 100644 --- a/test/cases/getSkipSegmentsByHash.ts +++ b/test/cases/getSkipSegmentsByHash.ts @@ -5,6 +5,7 @@ import {getHash} from '../../src/utils/getHash'; import {ImportMock,} from 'ts-mock-imports'; import * as YouTubeAPIModule from '../../src/utils/youtubeApi'; import {YouTubeApiMock} from '../youtubeMock'; +import assert from 'assert'; const mockManager = ImportMock.mockStaticClass(YouTubeAPIModule, 'YouTubeAPI'); const sinonStub = mockManager.mock('listVideos'); @@ -31,36 +32,35 @@ describe('getSegmentsByHash', () => { it('Should be able to get a 200', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/3272f?categories=["sponsor", "intro"]') .then(res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else done(); // pass + assert.strictEqual(res.status, 200); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 404 if no segments are found even if a video for the given hash is known', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/3272f?categories=["shilling"]') .then(async res => { - if (res.status !== 404) done("non 404 status code, was " + res.status); - else { - const body = await res.text(); - if (body === '[]') done(); // pass - else done("Response had videos"); - } + assert.strictEqual(res.status, 404); + const expected = '[]'; + const body = await res.text(); + assert.strictEqual(body, expected); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get an empty array if no videos', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/11111?categories=["shilling"]') .then(async res => { - if (res.status !== 404) done("non 404 status code, was " + res.status); - else { - const body = await res.text(); - if (JSON.parse(body).length === 0 && body === '[]') done(); // pass - else done("non empty array returned"); - } + assert.strictEqual(res.status, 404); + const body = await res.text(); + const expected = '[]'; + assert.strictEqual(JSON.parse(body).length, 0); + assert.strictEqual(body, expected); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get an empty array if only hidden videos', (done: Done) => { @@ -73,175 +73,159 @@ describe('getSegmentsByHash', () => { else done("non empty array returned"); } }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 400 prefix too short', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/11?categories=["shilling"]') .then(res => { - if (res.status !== 400) done("non 400 status code, was " + res.status); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 400 prefix too long', (done: Done) => { - const prefix = new Array(50).join('1'); - if (prefix.length <= 32) { // default value, config can change this - done('failed to generate a long enough string for the test ' + prefix.length); - return; - } + const prefix = '1'.repeat(50); + assert.ok(prefix.length > 33, "failed to generate long enough string"); fetch(getbaseURL() + '/api/skipSegments/' + prefix + '?categories=["shilling"]') .then(res => { - if (res.status !== 400) done("non 400 status code, was " + res.status); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); - it('Should not return 400 prefix in range', (done: Done) => { - fetch(getbaseURL() + '/api/skipSegments/11111?categories=["shilling"]') + it('Should return 404 prefix in range', (done: Done) => { + const prefix = '1'.repeat(5); + fetch(getbaseURL() + '/api/skipSegments/'+prefix+'?categories=["shilling"]') .then(res => { - if (res.status === 400) done("prefix length 5 gave 400 " + res.status); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 404 for no hash', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/?categories=["shilling"]') .then(res => { - if (res.status !== 404) done("expected 404, got " + res.status); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 400 for bad format categories', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/fdaf?categories=shilling') .then(res => { - if (res.status !== 400) done("expected 400 got " + res.status); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get multiple videos', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/fdaf?categories=["sponsor","intro"]') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 2) done("expected 2 videos, got " + body.length); - else if (body[0].segments.length !== 2) done("expected 2 segments for first video, got " + body[0].segments.length); - else if (body[1].segments.length !== 1) done("expected 1 segment for second video, got " + body[1].segments.length); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segments.length, 2); + assert.strictEqual(data[1].segments.length, 1); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get 200 for no categories (default sponsor)', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/fdaf') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 2) done("expected 2 videos, got " + body.length); - else if (body[0].segments.length !== 1) done("expected 1 segments for first video, got " + body[0].segments.length); - else if (body[1].segments.length !== 1) done("expected 1 segments for second video, got " + body[1].segments.length); - else if (body[0].segments[0].category !== 'sponsor' - || body[0].segments[0].UUID !== 'getSegmentsByHash-0-0' - || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor"); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segments.length, 1); + assert.strictEqual(data[1].segments.length, 1); + assert.strictEqual(data[0].segments[0].category, 'sponsor'); + assert.strictEqual(data[0].segments[0].UUID, 'getSegmentsByHash-0-0'); + assert.strictEqual(data[1].segments[0].category, 'sponsor'); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get 200 for no categories (default sponsor) with action type', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/fdaf?actionType=skip') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 2) done("expected 2 videos, got " + body.length); - else if (body[0].segments.length !== 1) done("expected 1 segments for first video, got " + body[0].segments.length); - else if (body[1].segments.length !== 1) done("expected 1 segments for second video, got " + body[1].segments.length); - else if (body[0].segments[0].category !== 'sponsor' - || body[0].segments[0].UUID !== 'getSegmentsByHash-0-0' - || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor"); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segments.length, 1); + assert.strictEqual(data[1].segments.length, 1); + assert.strictEqual(data[0].segments[0].category, 'sponsor'); + assert.strictEqual(data[0].segments[0].UUID, 'getSegmentsByHash-0-0'); + assert.strictEqual(data[1].segments[0].category, 'sponsor'); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get 200 for no categories (default sponsor) with multiple action types', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/fdaf?actionType=skip&actionType=mute') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 2) done("expected 2 videos, got " + body.length); - else if (body[0].segments.length !== 2) done("expected 2 segments for first video, got " + body[0].segments.length); - else if (body[1].segments.length !== 1) done("expected 1 segments for second video, got " + body[1].segments.length); - else if (body[0].segments[0].category !== 'sponsor' - || body[0].segments[0].UUID !== 'getSegmentsByHash-0-0' - || body[0].segments[1].UUID !== 'getSegmentsByHash-0-2' - || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor"); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segments.length, 2); + assert.strictEqual(data[1].segments.length, 1); + assert.strictEqual(data[0].segments[0].category, 'sponsor'); + assert.strictEqual(data[0].segments[0].UUID, 'getSegmentsByHash-0-0'); + assert.strictEqual(data[0].segments[1].UUID, 'getSegmentsByHash-0-2'); + assert.strictEqual(data[1].segments[0].category, 'sponsor'); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get 200 for no categories (default sponsor) with multiple action types (JSON array)', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/fdaf?actionTypes=["skip","mute"]') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 2) done("expected 2 videos, got " + body.length); - else if (body[0].segments.length !== 2) done("expected 2 segments for first video, got " + body[0].segments.length); - else if (body[1].segments.length !== 1) done("expected 1 segments for second video, got " + body[1].segments.length); - else if (body[0].segments[0].category !== 'sponsor' - || body[0].segments[0].UUID !== 'getSegmentsByHash-0-0' - || body[0].segments[1].UUID !== 'getSegmentsByHash-0-2' - || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor"); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[0].segments.length, 2); + assert.strictEqual(data[1].segments.length, 1); + assert.strictEqual(data[0].segments[0].category, 'sponsor'); + assert.strictEqual(data[0].segments[0].UUID, 'getSegmentsByHash-0-0'); + assert.strictEqual(data[0].segments[1].UUID, 'getSegmentsByHash-0-2'); + assert.strictEqual(data[1].segments[0].category, 'sponsor'); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get 200 for no categories (default sponsor) for a non YouTube service', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/fdaf?service=PeerTube') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 1) done("expected 1 video, got " + body.length); - else if (body[0].segments.length !== 1) done("expected 1 segments for first video, got " + body[0].segments.length); - else if (body[0].segments[0].UUID !== 'getSegmentsByHash-0-0-1') done("both segments are not sponsor"); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segments.length, 1); + assert.strictEqual(data[0].segments[0].UUID, 'getSegmentsByHash-0-0-1'); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should only return one segment when fetching highlight segments', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/c962?category=highlight') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 1) done("expected 1 video, got " + body.length); - else if (body[0].segments.length !== 1) done("expected 1 segment, got " + body[0].segments.length); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segments.length, 1); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to post a segment and get it using endpoint', (done: Done) => { @@ -260,23 +244,17 @@ describe('getSegmentsByHash', () => { }], }), }) - .then(async res => { - if (res.status === 200) { - fetch(getbaseURL() + '/api/skipSegments/' + getHash(testID, 1).substring(0, 3)) - .then(async res => { - if (res.status !== 200) done("(get) non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 1) done("(get) expected 1 video, got " + body.length); - else if (body[0].segments.length !== 1) done("(get) expected 1 segments for first video, got " + body[0].segments.length); - else if (body[0].segments[0].category !== 'sponsor') done("(get) segment should be sponsor, was " + body[0].segments[0].category); - else done(); - } - }) - .catch(() => done("(get) Couldn't call endpoint")); - } else { - done("(post) non 200 status code, was " + res.status); - } + .then(async () => { + fetch(getbaseURL() + '/api/skipSegments/' + getHash(testID, 1).substring(0, 3)) + .then(async res => { + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segments.length, 1); + assert.strictEqual(data[0].segments[0].category, 'sponsor'); + done(); + }) + .catch(err => done('(get) ' + err)); }) .catch(err => done('(post) ' + err)); }); @@ -284,64 +262,48 @@ describe('getSegmentsByHash', () => { it('Should be able to get multiple categories with repeating parameters', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments/fdaff4?&category=sponsor&category=intro") .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const body = await res.json(); - if (body.length !== 1) done("expected 1 video, got " + body.length); - - const data = body[0].segments; - if (data.length === 2) { - let success = true; - for (const segment of data) { - if ((segment.segment[0] !== 1 || segment.segment[1] !== 10 - || segment.category !== "sponsor" || segment.UUID !== "getSegmentsByHash-0-0") && - (segment.segment[0] !== 20 || segment.segment[1] !== 30 - || segment.category !== "intro" || segment.UUID !== "getSegmentsByHash-0-1")) { - success = false; - break; - } - } - - if (success) done(); - else done("Received incorrect body: " + JSON.stringify(body)); - } else { - done("Received incorrect body: " + JSON.stringify(body)); - } - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segments[0].segment[0], 1); + assert.strictEqual(data[0].segments[0].segment[1], 10); + assert.strictEqual(data[0].segments[0].category, "sponsor"); + assert.strictEqual(data[0].segments[0].UUID, "getSegmentsByHash-0-0"); + assert.strictEqual(data[0].segments[1].segment[0], 20); + assert.strictEqual(data[0].segments[1].segment[1], 30); + assert.strictEqual(data[0].segments[1].category, "intro"); + assert.strictEqual(data[0].segments[1].UUID, "getSegmentsByHash-0-1"); + done(); }) - .catch(() => ("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get specific segments with requiredSegments', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/d518?requiredSegments=["requiredSegmentVid-2","requiredSegmentVid-3"]') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 1) done("expected 1 video, got " + body.length); - else if (body[0].segments.length !== 2) done("expected 2 segments for video, got " + body[0].segments.length); - else if (body[0].segments[0].UUID !== 'requiredSegmentVid-2' - || body[0].segments[1].UUID !== 'requiredSegmentVid-3') done("Did not recieve the correct segments\n" + JSON.stringify(body, null, 2)); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segments.length, 2); + assert.strictEqual(data[0].segments[0].UUID, 'requiredSegmentVid-2'); + assert.strictEqual(data[0].segments[0].UUID, 'requiredSegmentVid-2'); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get specific segments with repeating requiredSegment', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/d518?requiredSegment=requiredSegmentVid-2&requiredSegment=requiredSegmentVid-3') .then(async res => { - if (res.status !== 200) done("non 200 status code, was " + res.status); - else { - const body = await res.json(); - if (body.length !== 1) done("expected 1 video, got " + body.length); - else if (body[0].segments.length !== 2) done("expected 2 segments for video, got " + body[0].segments.length); - else if (body[0].segments[0].UUID !== 'requiredSegmentVid-2' - || body[0].segments[1].UUID !== 'requiredSegmentVid-3') done("Did not recieve the correct segments\n" + JSON.stringify(body, null, 2)); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.length, 1); + assert.strictEqual(data[0].segments.length, 2); + assert.strictEqual(data[0].segments[0].UUID, 'requiredSegmentVid-2'); + assert.strictEqual(data[0].segments[1].UUID, 'requiredSegmentVid-3'); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); }); diff --git a/test/cases/getUserID.ts b/test/cases/getUserID.ts index e0c7c5a..64863f9 100644 --- a/test/cases/getUserID.ts +++ b/test/cases/getUserID.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('getUserID', () => { before(async () => { @@ -23,379 +24,293 @@ describe('getUserID', () => { it('Should be able to get a 200', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=fuzzy+user+01') .then(async res => { - if (res.status !== 200) done('non 200 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 200); + done(); }) - .catch(() => done('couldn\'t call endpoint')); + .catch(err => done(err)); }); it('Should be able to get a 400 (No username parameter)', (done: Done) => { fetch(getbaseURL() + '/api/userID') .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done('couldn\'t call endpoint')); + .catch(err => done(err)); }); it('Should be able to get a 200 (username is public id)', (done: Done) => { fetch(getbaseURL() + '/api/userID?username='+getHash("getuserid_user_06")) .then(async res => { - if (res.status !== 200) done('non 200 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 200); + done(); }) - .catch(() => done('couldn\'t call endpoint')); + .catch(err => done(err)); }); it('Should be able to get a 400 (username longer than 64 chars)', (done: Done) => { fetch(getbaseURL() + '/api/userID?username='+getHash("getuserid_user_06")+'0') .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done('couldn\'t call endpoint')); + .catch(err => done(err)); }); it('Should be able to get single username', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=fuzzy+user+01') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "fuzzy user 01") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_01")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "fuzzy user 01", + userID: getHash("getuserid_user_01") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get multiple fuzzy user info from start', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=fuzzy+user') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 2) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "fuzzy user 01") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_01")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else if (data[1].userName !== "fuzzy user 02") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[1].userID !== getHash("getuserid_user_02")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "fuzzy user 01", + userID: getHash("getuserid_user_01") + }, { + userName: "fuzzy user 02", + userID: getHash("getuserid_user_02") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get multiple fuzzy user info from middle', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=user') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 3) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "fuzzy user 01") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_01")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else if (data[1].userName !== "fuzzy user 02") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[1].userID !== getHash("getuserid_user_02")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else if (data[2].userName !== "specific user 03") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[2].userID !== getHash("getuserid_user_03")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "fuzzy user 01", + userID: getHash("getuserid_user_01") + }, { + userName: "fuzzy user 02", + userID: getHash("getuserid_user_02") + }, { + userName: "specific user 03", + userID: getHash("getuserid_user_03") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get with public ID', (done: Done) => { const userID = getHash("getuserid_user_06"); fetch(getbaseURL() + '/api/userID?username='+userID) .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== userID) { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== userID) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: userID, + userID + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get with fuzzy public ID', (done: Done) => { const userID = getHash("getuserid_user_06"); fetch(getbaseURL() + '/api/userID?username='+userID.substr(10,60)) .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== userID) { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== userID) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: userID, + userID + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get repeating username', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=repeating') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 2) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "repeating") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_04")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else if (data[1].userName !== "repeating") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[1].userID !== getHash("getuserid_user_05")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "repeating", + userID: getHash("getuserid_user_04") + }, { + userName: "repeating", + userID: getHash("getuserid_user_05") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get repeating fuzzy username', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=peat') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 2) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "repeating") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_04")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else if (data[1].userName !== "repeating") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[1].userID !== getHash("getuserid_user_05")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "repeating", + userID: getHash("getuserid_user_04") + }, { + userName: "repeating", + userID: getHash("getuserid_user_05") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should avoid ReDOS with _', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=_redos_') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "_redos_") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_09")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "_redos_", + userID: getHash("getuserid_user_09") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should avoid ReDOS with %', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=%redos%') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "%redos%") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_08")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "%redos%", + userID: getHash("getuserid_user_08") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should return 404 if escaped backslashes present', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=%redos\\\\_') .then(res => { - if (res.status !== 404) done('non 404 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should return 404 if backslashes present', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=\\%redos\\_') .then(res => { - if (res.status !== 404) done('non 404 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should return user if just backslashes', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=\\\\\\') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "\\\\\\") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_11")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "\\\\\\", + userID: getHash("getuserid_user_11") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should not allow usernames more than 64 characters', (done: Done) => { fetch(getbaseURL() + '/api/userID?username='+'0'.repeat(65)) .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should not allow usernames less than 3 characters', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=aa') .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('should allow exact match', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=a&exact=true') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 1) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "a") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_12")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "a", + userID: getHash("getuserid_user_12") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get repeating username with exact username', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=repeating&exact=true') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 2) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "repeating") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_04")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else if (data[1].userName !== "repeating") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[1].userID !== getHash("getuserid_user_05")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "repeating", + userID: getHash("getuserid_user_04") + }, { + userName: "repeating", + userID: getHash("getuserid_user_05") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should not get exact unless explicitly set to true', (done: Done) => { fetch(getbaseURL() + '/api/userID?username=user&exact=1') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.length !== 3) { - done('Returned incorrect number of users "' + data.length + '"'); - } else if (data[0].userName !== "fuzzy user 01") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[0].userID !== getHash("getuserid_user_01")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else if (data[1].userName !== "fuzzy user 02") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[1].userID !== getHash("getuserid_user_02")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else if (data[2].userName !== "specific user 03") { - done('Returned incorrect username "' + data.userName + '"'); - } else if (data[2].userID !== getHash("getuserid_user_03")) { - done('Returned incorrect userID "' + data.userID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = [{ + userName: "fuzzy user 01", + userID: getHash("getuserid_user_01") + }, { + userName: "fuzzy user 02", + userID: getHash("getuserid_user_02") + }, { + userName: "specific user 03", + userID: getHash("getuserid_user_03") + }]; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); }); diff --git a/test/cases/getUserInfo.ts b/test/cases/getUserInfo.ts index 2c21250..eefb285 100644 --- a/test/cases/getUserInfo.ts +++ b/test/cases/getUserInfo.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('getUserInfo', () => { before(async () => { @@ -27,136 +28,109 @@ describe('getUserInfo', () => { it('Should be able to get a 200', (done: Done) => { fetch(getbaseURL() + '/api/userInfo?userID=getuserinfo_user_01') .then(res => { - if (res.status !== 200) done('non 200 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 200); + done(); }) - .catch(() => done('couldn\'t call endpoint')); + .catch(err => done(err)); }); it('Should be able to get a 400 (No userID parameter)', (done: Done) => { fetch(getbaseURL() + '/api/userInfo') .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done('couldn\'t call endpoint')); + .catch(err => done(err)); }); it('Should be able to get user info', (done: Done) => { fetch(getbaseURL() + '/api/userInfo?userID=getuserinfo_user_01') .then(async res => { - if (res.status !== 200) { - done("non 200"); - } else { - const data = await res.json(); - if (data.userName !== 'Username user 01') { - done('Returned incorrect userName "' + data.userName + '"'); - } else if (data.minutesSaved !== 5) { - done('Returned incorrect minutesSaved "' + data.minutesSaved + '"'); - } else if (data.viewCount !== 30) { - done('Returned incorrect viewCount "' + data.viewCount + '"'); - } else if (data.ignoredViewCount !== 20) { - done('Returned incorrect ignoredViewCount "' + data.ignoredViewCount + '"'); - } else if (data.segmentCount !== 3) { - done('Returned incorrect segmentCount "' + data.segmentCount + '"'); - } else if (data.ignoredSegmentCount !== 2) { - done('Returned incorrect ignoredSegmentCount "' + data.ignoredSegmentCount + '"'); - } else if (data.reputation !== -2) { - done('Returned incorrect reputation "' + data.reputation + '"'); - } else if (data.lastSegmentID !== "uuid000005") { - done('Returned incorrect last segment "' + data.lastSegmentID + '"'); - } else { - done(); // pass - } - } + assert.strictEqual(res.status, 200); + const expected = { + userName: 'Username user 01', + userID: "66e7c974039ffb870a500a33eca3a3989861018909b938c313cf1a8a366800b8", + minutesSaved: 5, + viewCount: 30, + ignoredViewCount: 20, + segmentCount: 3, + ignoredSegmentCount: 2, + reputation: -2, + lastSegmentID: "uuid000005", + vip: false, + warnings: 0 + }; + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should get warning data', (done: Done) => { fetch(getbaseURL() + '/api/userInfo?userID=getuserinfo_warning_0') .then(async res => { - if (res.status !== 200) { - done('non 200 (' + res.status + ')'); - } else { - const data = await res.json(); - if (data.warnings !== 1) done('wrong number of warnings: ' + data.warnings + ', not ' + 1); - else done(); // pass - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.warnings, 1); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should get warning data with public ID', (done: Done) => { fetch(getbaseURL() + '/api/userInfo?publicUserID=' + getHash("getuserinfo_warning_0")) .then(async res => { - if (res.status !== 200) { - done('non 200 (' + res.status + ')'); - } else { - const data = await res.json(); - if (data.warnings !== 1) done('wrong number of warnings: ' + data.warnings + ', not ' + 1); - else done(); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.warnings, 1); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should get multiple warnings', (done: Done) => { fetch(getbaseURL() + '/api/userInfo?userID=getuserinfo_warning_1') .then(async res => { - if (res.status !== 200) { - done('non 200 (' + res.status + ')'); - } else { - const data = await res.json(); - if (data.warnings !== 2) done('wrong number of warnings: ' + data.warnings + ', not ' + 2); - else done(); // pass - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.warnings, 2); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should not get warnings if none', (done: Done) => { fetch(getbaseURL() + '/api/userInfo?userID=getuserinfo_warning_2') .then(async res => { - if (res.status !== 200) { - done('non 200 (' + res.status + ')'); - } else { - const data = await res.json(); - if (data.warnings !== 0) done('wrong number of warnings: ' + data.warnings + ', not ' + 0); - else done(); // pass - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.warnings, 0); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should done(userID for userName (No userName set)', (done: Done) => { fetch(getbaseURL() + '/api/userInfo?userID=getuserinfo_user_02') .then(async res => { - if (res.status !== 200) { - done('non 200 (' + res.status + ')'); - } else { - const data = await res.json(); - if (data.userName !== 'c2a28fd225e88f74945794ae85aef96001d4a1aaa1022c656f0dd48ac0a3ea0f') { - done('Did not done(userID for userName'); - } - done(); // pass - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.userName, 'c2a28fd225e88f74945794ae85aef96001d4a1aaa1022c656f0dd48ac0a3ea0f'); + done(); }) - .catch(() => ('couldn\'t call endpoint')); + .catch(err => done(err)); }); it('Should return null segment if none', (done: Done) => { fetch(getbaseURL() + '/api/userInfo?userID=getuserinfo_null') .then(async res => { - if (res.status !== 200) { - done('non 200 (' + res.status + ')'); - } else { - const data = await res.json(); - if (data.lastSegmentID !== null) done('returned segment ' + data.warnings + ', not ' + null); - else done(); // pass - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.lastSegmentID, null); + done(); }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return zeroes if userid does not exist', (done: Done) => { @@ -170,6 +144,6 @@ describe('getUserInfo', () => { } done(); // pass }) - .catch(() => ("couldn't call endpoint")); + .catch(err => done(err)); }); }); diff --git a/test/cases/lockCategoriesRecords.ts b/test/cases/lockCategoriesRecords.ts index 2cb9070..6088154 100644 --- a/test/cases/lockCategoriesRecords.ts +++ b/test/cases/lockCategoriesRecords.ts @@ -2,7 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {getHash} from '../../src/utils/getHash'; import {db} from '../../src/databases/databases'; - +import assert from 'assert'; describe('lockCategoriesRecords', () => { before(async () => { @@ -42,14 +42,12 @@ describe('lockCategoriesRecords', () => { 'intro', ], }; - const expected = { submitted: [ 'outro', 'shilling', ], }; - fetch(getbaseURL() + "/api/lockCategories", { method: 'POST', headers: { @@ -58,16 +56,10 @@ describe('lockCategoriesRecords', () => { body: JSON.stringify(json) }) .then(async res => { - if (res.status === 200) { - const data = await res.json(); - if (JSON.stringify(data) === JSON.stringify(expected)) { - done(); - } else { - done("Incorrect response: expected " + JSON.stringify(expected) + " got " + JSON.stringify(data)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) .catch(err => done(err)); }); @@ -85,7 +77,6 @@ describe('lockCategoriesRecords', () => { 'intro', ], }; - fetch(getbaseURL() + "/api/lockCategories", { method: 'POST', headers: { @@ -94,16 +85,10 @@ describe('lockCategoriesRecords', () => { body: JSON.stringify(json) }) .then(async res => { - if (res.status === 200) { - const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['no-segments-video-id-1']); - if (result.length !== 4) { - done("Expected 4 entrys in db, got " + result.length); - } else { - done(); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['no-segments-video-id-1']); + assert.strictEqual(result.length, 4); + done(); }) .catch(err => done(err)); }); @@ -116,7 +101,6 @@ describe('lockCategoriesRecords', () => { 'word_word', ], }; - fetch(getbaseURL() + "/api/lockCategories", { method: 'POST', headers: { @@ -125,16 +109,10 @@ describe('lockCategoriesRecords', () => { body: JSON.stringify(json), }) .then(async res => { - if (res.status === 200) { - const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['underscore']); - if (result.length !== 1) { - done("Expected 1 entrys in db, got " + result.length); - } else { - done(); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['underscore']); + assert.strictEqual(result.length, 1); + done(); }) .catch(err => done(err)); }); @@ -147,7 +125,6 @@ describe('lockCategoriesRecords', () => { 'wordWord', ], }; - fetch(getbaseURL() + "/api/lockCategories", { method: 'POST', headers: { @@ -156,16 +133,10 @@ describe('lockCategoriesRecords', () => { body: JSON.stringify(json), }) .then(async res => { - if (res.status === 200) { - const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['bothCases']); - if (result.length !== 1) { - done("Expected 1 entrys in db, got " + result.length); - } else { - done(); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['bothCases']); + assert.strictEqual(result.length, 1); + done(); }) .catch(err => done(err)); }); @@ -187,16 +158,10 @@ describe('lockCategoriesRecords', () => { body: JSON.stringify(json), }) .then(async res => { - if (res.status === 200) { - const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['specialChar']); - if (result.length !== 0) { - done("Expected 0 entrys in db, got " + result.length); - } else { - done(); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['specialChar']); + assert.strictEqual(result.length, 0); + done(); }) .catch(err => done(err)); }); @@ -209,12 +174,9 @@ describe('lockCategoriesRecords', () => { }, body: JSON.stringify({}), }) - .then(async res => { - if (res.status === 400) { - done(); - } else { - done("Status code was " + res.status); - } + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); @@ -225,7 +187,6 @@ describe('lockCategoriesRecords', () => { userID: 'test', categories: [], }; - fetch(getbaseURL() + "/api/lockCategories", { method: 'POST', headers: { @@ -233,12 +194,9 @@ describe('lockCategoriesRecords', () => { }, body: JSON.stringify(json), }) - .then(async res => { - if (res.status === 400) { - done(); - } else { - done("Status code was " + res.status); - } + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); @@ -257,12 +215,9 @@ describe('lockCategoriesRecords', () => { }, body: JSON.stringify(json), }) - .then(async res => { - if (res.status === 400) { - done(); - } else { - done("Status code was " + res.status); - } + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); @@ -281,12 +236,9 @@ describe('lockCategoriesRecords', () => { }, body: JSON.stringify(json), }) - .then(async res => { - if (res.status === 400) { - done(); - } else { - done("Status code was " + res.status); - } + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); @@ -305,12 +257,9 @@ describe('lockCategoriesRecords', () => { }, body: JSON.stringify(json), }) - .then(async res => { - if (res.status === 400) { - done(); - } else { - done("Status code was " + res.status); - } + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); @@ -329,12 +278,9 @@ describe('lockCategoriesRecords', () => { }, body: JSON.stringify(json), }) - .then(async res => { - if (res.status === 400) { - done(); - } else { - done("Status code was " + res.status); - } + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); @@ -355,12 +301,9 @@ describe('lockCategoriesRecords', () => { }, body: JSON.stringify(json), }) - .then(async res => { - if (res.status === 403) { - done(); - } else { - done("Status code was " + res.status); - } + .then(res => { + assert.strictEqual(res.status, 403); + done(); }) .catch(err => done(err)); }); @@ -382,16 +325,10 @@ describe('lockCategoriesRecords', () => { body: JSON.stringify(json), }) .then(async res => { - if (res.status === 200) { - const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['delete-record']); - if (result.length === 0) { - done(); - } else { - done("Didn't delete record"); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['delete-record']); + assert.strictEqual(result.length, 0); + done(); }) .catch(err => done(err)); }); @@ -413,16 +350,10 @@ describe('lockCategoriesRecords', () => { body: JSON.stringify(json), }) .then(async res => { - if (res.status === 200) { - const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['delete-record-1']); - if (result.length === 1) { - done(); - } else { - done("Didn't delete record"); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const result = await db.prepare('all', 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', ['delete-record-1']); + assert.strictEqual(result.length, 1); + done(); }) .catch(err => done(err)); }); @@ -449,11 +380,8 @@ describe('lockCategoriesRecords', () => { }), }) .then(async res => { - if (res.status === 403) { - done(); - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 403); + done(); }) .catch(err => done(err)); }); @@ -477,11 +405,8 @@ describe('lockCategoriesRecords', () => { },), }) .then(async res => { - if (res.status === 403) { - done(); - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 403); + done(); }) .catch(err => done(err)); }); @@ -503,11 +428,8 @@ describe('lockCategoriesRecords', () => { }), }) .then(async res => { - if (res.status === 200) { - done(); - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + done(); }) .catch(err => done(err)); }); @@ -528,11 +450,8 @@ describe('lockCategoriesRecords', () => { }), }) .then(async res => { - if (res.status === 200) { - done(); - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + done(); }) .catch(err => done(err)); }); @@ -549,29 +468,11 @@ describe('lockCategoriesRecords', () => { fetch(getbaseURL() + "/api/lockCategories?videoID=" + "no-segments-video-id") .then(async res => { - if (res.status === 200) { - const data = await res.json(); - if (JSON.stringify(data) === JSON.stringify(expected)) { - done(); - } else { - done("Incorrect response: expected " + JSON.stringify(expected) + " got " + JSON.stringify(data)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.deepStrictEqual(data, expected); + done(); }) .catch(err => done(err)); }); - - it('Should be able to get hashedVideoID from lock', (done: Done) => { - const hashedVideoID = getHash('no-segments-video-id', 1); - db.prepare('get', 'SELECT "hashedVideoID" FROM "lockCategories" WHERE "videoID" = ?', ['no-segments-video-id']) - .then(result => { - if (result !== hashedVideoID) { - done(); - } else { - done("Got unexpected video hash " + result); - } - }); - }); }); diff --git a/test/cases/oldGetSponsorTime.ts b/test/cases/oldGetSponsorTime.ts index 9a19fa2..cbd5e65 100644 --- a/test/cases/oldGetSponsorTime.ts +++ b/test/cases/oldGetSponsorTime.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {db} from '../../src/databases/databases'; import {Done, getbaseURL} from '../utils'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('getVideoSponsorTime (Old get method)', () => { before(async () => { @@ -13,27 +14,27 @@ describe('getVideoSponsorTime (Old get method)', () => { it('Should be able to get a time', (done: Done) => { fetch(getbaseURL() + "/api/getVideoSponsorTimes?videoID=old-testtesttest") .then(res => { - if (res.status !== 200) done("non 200 (" + res.status + ")"); - else done(); // pass + assert.strictEqual(res.status, 200); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should return 404 if no segment found', (done: Done) => { fetch(getbaseURL() + "/api/getVideoSponsorTimes?videoID=notarealvideo") .then(res => { - if (res.status !== 404) done("non 404 respone code: " + res.status); - else done(); // pass + assert.strictEqual(res.status, 404); + done(); }) - .catch(() => done("couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be possible to send unexpected query parameters', (done: Done) => { fetch(getbaseURL() + "/api/getVideoSponsorTimes?videoID=old-testtesttest&fakeparam=hello") .then(res => { - if (res.status !== 200) done("non 200"); - else done(); // pass + assert.strictEqual(res.status, 200); + done(); }) .catch(() => done("couldn't callendpoint")); }); @@ -41,30 +42,24 @@ describe('getVideoSponsorTime (Old get method)', () => { it('Should be able send a comma in a query param', (done: Done) => { fetch(getbaseURL() + "/api/getVideoSponsorTimes?videoID=old-testtesttest,test") .then(async res => { - const body = await res.text(); - if (res.status !== 200) done("non 200 response: " + res.status); - else if (JSON.parse(body).UUIDs[0] === 'uuid-1') done(); // pass - else done("couldn't parse response"); + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.UUIDs[0], "uuid-1"); + done(); }) - .catch(() => done("couln't call endpoint")); + .catch(err => done(err)); }); it('Should be able to get the correct time', (done: Done) => { fetch(getbaseURL() + "/api/getVideoSponsorTimes?videoID=old-testtesttest") .then(async res => { - if (res.status !== 200) done("non 200"); - else { - const parsedBody = await res.json(); - if (parsedBody.sponsorTimes[0][0] === 1 - && parsedBody.sponsorTimes[0][1] === 11 - && parsedBody.UUIDs[0] === 'uuid-0') { - done(); // pass - } else { - done("Wrong data was returned + " + JSON.stringify(parsedBody)); - } - } - + assert.strictEqual(res.status, 200); + const data = await res.json(); + assert.strictEqual(data.sponsorTimes[0][0], 1); + assert.strictEqual(data.sponsorTimes[0][1], 11); + assert.strictEqual(data.UUIDs[0], 'uuid-0'); + done(); }) - .catch(() => done("couldn't call endpoint")); + .catch(err => done(err)); }); }); diff --git a/test/cases/oldSubmitSponsorTimes.ts b/test/cases/oldSubmitSponsorTimes.ts index 746f7f3..68ca032 100644 --- a/test/cases/oldSubmitSponsorTimes.ts +++ b/test/cases/oldSubmitSponsorTimes.ts @@ -1,23 +1,19 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; - +import assert from 'assert'; describe('postVideoSponsorTime (Old submission method)', () => { it('Should be able to submit a time (GET)', (done: Done) => { fetch(getbaseURL() + "/api/postVideoSponsorTimes?videoID=dQw4w9WgXcQ&startTime=1&endTime=10&userID=testtesttesttesttesttesttesttesttest") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcQ"]); - if (row.startTime === 1 && row.endTime === 10 && row.category === "sponsor") { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcQ"]); + assert.strictEqual(row.startTime, 1); + assert.strictEqual(row.endTime, 10); + assert.strictEqual(row.category, "sponsor"); + done(); }) .catch(err => done(err)); }); @@ -31,16 +27,12 @@ describe('postVideoSponsorTime (Old submission method)', () => { }, }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcE"]); - if (row.startTime === 1 && row.endTime === 11 && row.category === "sponsor") { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcE"]); + assert.strictEqual(row.startTime, 1); + assert.strictEqual(row.endTime, 11); + assert.strictEqual(row.category, "sponsor"); + done(); }) .catch(err => done(err)); }); @@ -49,8 +41,8 @@ describe('postVideoSponsorTime (Old submission method)', () => { fetch(getbaseURL() + "/api/postVideoSponsorTimes?startTime=1&endTime=10&userID=testtesttesttesttesttesttesttesttest") .then(async res => { - if (res.status === 400) done(); - else done("Status code was: " + res.status); + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); diff --git a/test/cases/postClearCache.ts b/test/cases/postClearCache.ts index 9a21a4e..3e976e5 100644 --- a/test/cases/postClearCache.ts +++ b/test/cases/postClearCache.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('postClearCache', () => { before(async () => { @@ -16,8 +17,8 @@ describe('postClearCache', () => { method: 'POST' }) .then(res => { - if (res.status === 200) done(); - else done("Status code was " + res.status); + assert.strictEqual(res.status, 200); + done(); }) .catch(err => done(err)); }); @@ -28,8 +29,8 @@ describe('postClearCache', () => { method: 'POST' }) .then(res => { - if (res.status === 200) done(); - else done("Status code was " + res.status); + assert.strictEqual(res.status, 200); + done(); }) .catch(err => done(err)); }); @@ -40,8 +41,8 @@ describe('postClearCache', () => { method: 'POST' }) .then(async res => { - if (res.status !== 403) done('non 403 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 403); + done(); }) .catch(err => done(err)); }); @@ -52,8 +53,8 @@ describe('postClearCache', () => { method: 'POST' }) .then(async res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); @@ -64,8 +65,8 @@ describe('postClearCache', () => { method: 'POST' }) .then(async res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); diff --git a/test/cases/postPurgeAllSegments.ts b/test/cases/postPurgeAllSegments.ts index a907ddc..a900893 100644 --- a/test/cases/postPurgeAllSegments.ts +++ b/test/cases/postPurgeAllSegments.ts @@ -3,6 +3,7 @@ import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; import {IDatabase} from '../../src/databases/IDatabase'; +import assert from 'assert'; async function dbSponsorTimesAdd(db: IDatabase, videoID: string, startTime: number, endTime: number, UUID: string, category: string) { const votes = 0, @@ -57,7 +58,8 @@ describe('postPurgeAllSegments', function () { }), }) .then(async res => { - done(res.status === 403 ? undefined : res.status); + assert.strictEqual(res.status, 403); + done(); }) .catch(err => done(err)); }); @@ -74,7 +76,7 @@ describe('postPurgeAllSegments', function () { }), }) .then(async res => { - if (res.status !== 200) return done(`Status code was ${res.status}`); + assert.strictEqual(res.status, 200); done(await dbSponsorTimesCompareExpect(db, 'vsegpurge01', 1) || await dbSponsorTimesCompareExpect(db, 'vseg-not-purged01', 0)); }) .catch(err => done(err)); diff --git a/test/cases/postSkipSegments.ts b/test/cases/postSkipSegments.ts index 88e2b75..614c9a7 100644 --- a/test/cases/postSkipSegments.ts +++ b/test/cases/postSkipSegments.ts @@ -6,6 +6,7 @@ import {db} from '../../src/databases/databases'; import {ImportMock} from 'ts-mock-imports'; import * as YouTubeAPIModule from '../../src/utils/youtubeApi'; import {YouTubeApiMock} from '../youtubeMock'; +import assert from 'assert'; const mockManager = ImportMock.mockStaticClass(YouTubeAPIModule, 'YouTubeAPI'); const sinonStub = mockManager.mock('listVideos'); @@ -62,16 +63,12 @@ describe('postSkipSegments', () => { }, }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcR"]); - if (row.startTime === 2 && row.endTime === 10 && row.category === "sponsor") { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcR"]); + assert.strictEqual(row.startTime, 2); + assert.strictEqual(row.endTime, 10); + assert.strictEqual(row.category, "sponsor"); + done(); }) .catch(err => done(err)); }); @@ -93,16 +90,13 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcF"]); - if (row.startTime === 0 && row.endTime === 10 && row.locked === 0 && row.category === "sponsor") { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcF"]); + assert.strictEqual(row.startTime, 0); + assert.strictEqual(row.endTime, 10); + assert.strictEqual(row.locked, 0); + assert.strictEqual(row.category, "sponsor"); + done(); }) .catch(err => done(err)); }); @@ -125,16 +119,14 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "actionType" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcV"]); - if (row.startTime === 0 && row.endTime === 10 && row.locked === 0 && row.category === "sponsor" && row.actionType === "mute") { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "actionType" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcV"]); + assert.strictEqual(row.startTime, 0); + assert.strictEqual(row.endTime, 10); + assert.strictEqual(row.locked, 0); + assert.strictEqual(row.category, "sponsor"); + assert.strictEqual(row.actionType, "mute"); + done(); }) .catch(err => done(err)); }); @@ -157,16 +149,14 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXZX"]); - if (row.startTime === 0 && row.endTime === 10 && row.locked === 0 && row.category === "sponsor" && row.videoDuration === 4980) { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXZX"]); + assert.strictEqual(row.startTime, 0); + assert.strictEqual(row.endTime, 10); + assert.strictEqual(row.locked, 0); + assert.strictEqual(row.category, "sponsor"); + assert.strictEqual(row.videoDuration, 4980); + done(); }) .catch(err => done(err)); }); @@ -189,16 +179,14 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXZH"]); - if (row.startTime === 1 && row.endTime === 10 && row.locked === 0 && row.category === "sponsor" && row.videoDuration === 4980.20) { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXZH"]); + assert.strictEqual(row.startTime, 1); + assert.strictEqual(row.endTime, 10); + assert.strictEqual(row.locked, 0); + assert.strictEqual(row.category, "sponsor"); + assert.strictEqual(row.videoDuration, 4980.20); + done(); }) .catch(err => done(err)); }); @@ -221,16 +209,14 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, ["noDuration"]); - if (row.startTime === 0 && row.endTime === 10 && row.locked === 0 && row.category === "sponsor" && row.videoDuration === 100) { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, ["noDuration"]); + assert.strictEqual(row.startTime, 0); + assert.strictEqual(row.endTime, 10); + assert.strictEqual(row.locked, 0); + assert.strictEqual(row.category, "sponsor"); + assert.strictEqual(row.videoDuration, 100); + done(); }) .catch(err => done(err)); }); @@ -256,23 +242,21 @@ describe('postSkipSegments', () => { }], }), }); - - if (res.status === 200) { - const lockCategoriesRow = await db.prepare('get', `SELECT * from "lockCategories" WHERE videoID = ?`, ["noDuration"]); - const videoRows = await db.prepare('all', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" - FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 0`, ["noDuration"]); - const videoRow = videoRows[0]; - const hiddenVideoRows = await db.prepare('all', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" - FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 1`, ["noDuration"]); - if (lockCategoriesRow === undefined && videoRows.length === 1 && hiddenVideoRows.length === 1 && videoRow.startTime === 1 && videoRow.endTime === 10 - && videoRow.locked === 0 && videoRow.category === "sponsor" && videoRow.videoDuration === 100) { - return; - } else { - return "Submitted times were not saved. Actual submission: " + JSON.stringify(videoRow); - } - } else { - return "Status code was " + res.status; - } + assert.strictEqual(res.status, 200); + const lockCategoriesRow = await db.prepare('get', `SELECT * from "lockCategories" WHERE videoID = ?`, ["noDuration"]); + const videoRows = await db.prepare('all', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" + FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 0`, ["noDuration"]); + const videoRow = videoRows[0]; + const hiddenVideoRows = await db.prepare('all', `SELECT "startTime", "endTime", "locked", "category", "videoDuration" + FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 1`, ["noDuration"]); + assert.ok(!lockCategoriesRow); + assert.strictEqual(videoRows.length, 1); + assert.strictEqual(hiddenVideoRows.length, 1); + assert.strictEqual(videoRow.startTime, 1); + assert.strictEqual(videoRow.endTime, 10); + assert.strictEqual(videoRow.locked, 0); + assert.strictEqual(videoRow.category, "sponsor"); + assert.strictEqual(videoRow.videoDuration, 100); } catch (e) { return e; } @@ -284,13 +268,10 @@ describe('postSkipSegments', () => { method: 'POST', }) .then(async res => { - if (res.status === 403) done(); // pass - else { - const body = await res.text(); - done("non 403 status code: " + res.status + " (" + body + ")"); - } + assert.strictEqual(res.status, 403); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to submit a single time under a different service (JSON method)', (done: Done) => { @@ -311,16 +292,14 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "service" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcG"]); - if (row.startTime === 0 && row.endTime === 10 && row.locked === 0 && row.category === "sponsor" && row.service === "PeerTube") { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "service" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcG"]); + assert.strictEqual(row.startTime, 0); + assert.strictEqual(row.endTime, 10); + assert.strictEqual(row.locked, 0); + assert.strictEqual(row.category, "sponsor"); + assert.strictEqual(row.service, "PeerTube"); + done(); }) .catch(err => done(err)); }); @@ -342,16 +321,13 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["vipuserIDSubmission"]); - if (row.startTime === 0 && row.endTime === 10 && row.locked === 1 && row.category === "sponsor") { - done(); - } else { - done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["vipuserIDSubmission"]); + assert.strictEqual(row.startTime, 0); + assert.strictEqual(row.endTime, 10); + assert.strictEqual(row.locked, 1); + assert.strictEqual(row.category, "sponsor"); + done(); }) .catch(err => done(err)); }); @@ -365,7 +341,7 @@ describe('postSkipSegments', () => { }, body: JSON.stringify({ userID: "testtesttesttesttesttesttesttesttest", - videoID: "dQw4w9WgXcQ", + videoID: "dQw4w9WgXcT", segments: [{ segment: [3, 10], category: "sponsor", @@ -376,23 +352,19 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 200) { - const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcR"]); - let success = true; - if (rows.length === 2) { - for (const row of rows) { - if ((row.startTime !== 3 || row.endTime !== 10 || row.category !== "sponsor") && - (row.startTime !== 30 || row.endTime !== 60 || row.category !== "intro")) { - success = false; - break; - } - } - } - if (success) done(); - else done("Submitted times were not saved. Actual submissions: " + JSON.stringify(rows)); - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcT"]); + const expected = [{ + startTime: 3, + endTime: 10, + category: "sponsor" + }, { + startTime: 30, + endTime: 60, + category: "intro" + }]; + assert.deepStrictEqual(rows, expected); + done(); }) .catch(err => done(err)); }).timeout(5000); @@ -423,25 +395,27 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 200) { - const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, ["L_jWHffIx5E"]); - let success = true; - if (rows.length === 4) { - for (const row of rows) { - if ((row.startTime !== 3 || row.endTime !== 3000 || row.category !== "sponsor") && - (row.startTime !== 3002 || row.endTime !== 3050 || row.category !== "intro") && - (row.startTime !== 45 || row.endTime !== 100 || row.category !== "interaction") && - (row.startTime !== 99 || row.endTime !== 170 || row.category !== "sponsor")) { - success = false; - break; - } - } - } - if (success) done(); - else done("Submitted times were not saved. Actual submissions: " + JSON.stringify(rows)); - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, ["L_jWHffIx5E"]); + const expected = [{ + startTime: 3, + endTime: 3000, + category: "sponsor" + }, { + startTime: 3002, + endTime: 3050, + category: "intro" + }, { + startTime: 45, + endTime: 100, + category: "interaction" + }, { + startTime: 99, + endTime: 170, + category: "sponsor" + }]; + assert.deepStrictEqual(rows, expected); + done(); }) .catch(err => done(err)); }).timeout(5000); @@ -472,27 +446,10 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 403) { - const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, ["n9rIGdXnSJc"]); - let success = true; - if (rows.length === 4) { - for (const row of rows) { - if ((row.startTime === 0 || row.endTime === 2000 || row.category === "interaction") || - (row.startTime === 3000 || row.endTime === 4000 || row.category === "sponsor") || - (row.startTime === 1500 || row.endTime === 2750 || row.category === "sponsor") || - (row.startTime === 4050 || row.endTime === 4750 || row.category === "intro")) { - success = false; - break; - } - } - } - - if (success) done(); - else - done("Submitted times were not saved. Actual submissions: " + JSON.stringify(rows)); - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 403); + const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, ["n9rIGdXnSJc"]); + assert.deepStrictEqual(rows, []); + done(); }) .catch(err => done(err)); }).timeout(5000); @@ -520,23 +477,23 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 403) { - const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, ["80percent_video"]); - let success = rows.length == 2; - for (const row of rows) { - if ((row.startTime === 2000 || row.endTime === 4000 || row.category === "sponsor") || - (row.startTime === 1500 || row.endTime === 2750 || row.category === "sponsor") || - (row.startTime === 4050 || row.endTime === 4750 || row.category === "sponsor")) { - success = false; - break; - } - } - if (success) done(); - else - done("Submitted times were not saved. Actual submissions: " + JSON.stringify(rows)); - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 403); + const expected = [{ + category: "sponsor", + startTime: 2000, + endTime: 4000 + }, { + category: "sponsor", + startTime: 1500, + endTime: 2750 + }, { + category: "sponsor", + startTime: 4050, + endTime: 4750 + }]; + const rows = await db.prepare('all', `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, ["80percent_video"]); + assert.notDeepStrictEqual(rows, expected); + done(); }) .catch(err => done(err)); }).timeout(5000); @@ -546,14 +503,11 @@ describe('postSkipSegments', () => { + "/api/skipSegments?videoID=qqwerty&startTime=30&endTime=30.5&userID=testtesttesttesttesttesttesttesttesting&category=intro", { method: 'POST', }) - .then(async res => { - if (res.status === 200) done(); // pass - else { - const body = await res.text(); - done("non 200 status code: " + res.status + " (" + body + ")"); - } + .then(res => { + assert.strictEqual(res.status, 200); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be rejected if segment starts and ends at the same time', (done: Done) => { @@ -561,14 +515,11 @@ describe('postSkipSegments', () => { + "/api/skipSegments?videoID=qqwerty&startTime=90&endTime=90&userID=testtesttesttesttesttesttesttesttesting&category=intro", { method: 'POST', }) - .then(async res => { - if (res.status === 400) done(); // pass - else { - const body = await res.text(); - done("non 400 status code: " + res.status + " (" + body + ")"); - } + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be accepted if highlight segment starts and ends at the same time', (done: Done) => { @@ -576,14 +527,11 @@ describe('postSkipSegments', () => { + "/api/skipSegments?videoID=qqwerty&startTime=30&endTime=30&userID=testtesttesttesttesttesttesttesttesting&category=highlight", { method: 'POST', }) - .then(async res => { - if (res.status === 200) done(); // pass - else { - const body = await res.text(); - done("non 200 status code: " + res.status + " (" + body + ")"); - } + .then(res => { + assert.strictEqual(res.status, 200); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be rejected if highlight segment doesn\'t start and end at the same time', (done: Done) => { @@ -591,14 +539,11 @@ describe('postSkipSegments', () => { + "/api/skipSegments?videoID=qqwerty&startTime=30&endTime=30.5&userID=testtesttesttesttesttesttesttesttesting&category=highlight", { method: 'POST', }) - .then(async res => { - if (res.status === 400) done(); // pass - else { - const body = await res.text(); - done("non 400 status code: " + res.status + " (" + body + ")"); - } + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be rejected if a sponsor is less than 1 second', (done: Done) => { @@ -606,40 +551,31 @@ describe('postSkipSegments', () => { + "/api/skipSegments?videoID=qqwerty&startTime=30&endTime=30.5&userID=testtesttesttesttesttesttesttesttesting", { method: 'POST', }) - .then(async res => { - if (res.status === 400) done(); // pass - else { - const body = await res.text(); - done("non 403 status code: " + res.status + " (" + body + ")"); - } + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be rejected if over 80% of the video', (done: Done) => { fetch(getbaseURL() + "/api/postVideoSponsorTimes?videoID=qqwerty&startTime=30&endTime=1000000&userID=testtesttesttesttesttesttesttesttesting") - .then(async res => { - if (res.status === 403) done(); // pass - else { - const body = await res.text(); - done("non 403 status code: " + res.status + " (" + body + ")"); - } + .then(res => { + assert.strictEqual(res.status, 403); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it("Should be rejected if NB's predicted probability is <70%.", (done: Done) => { fetch(getbaseURL() + "/api/postVideoSponsorTimes?videoID=LevkAjUE6d4&startTime=40&endTime=60&userID=testtesttesttesttesttesttesttesttesting") - .then(async res => { - if (res.status === 200) done(); // pass - else { - const body = await res.text(); - done("non 200 status code: " + res.status + " (" + body + ")"); - } + .then(res => { + assert.strictEqual(res.status, 200); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be rejected with custom message if user has to many active warnings', (done: Done) => { @@ -659,16 +595,10 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 403) { - const errorMessage = await res.text(); - if (errorMessage === 'Reason01') { - done(); // success - } else { - done("Status code was 403 but message was: " + errorMessage); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 403); + const errorMessage = await res.text(); + assert.strictEqual(errorMessage, 'Reason01'); + done(); }) .catch(err => done(err)); }); @@ -736,7 +666,7 @@ describe('postSkipSegments', () => { if (res.status === 400) done(); else done(true); }) - .catch(() => done(true)); + .catch(err => done(err)); }); it('Should be rejected with default message if user has to many active warnings', (done: Done) => { @@ -756,16 +686,10 @@ describe('postSkipSegments', () => { }), }) .then(async res => { - if (res.status === 403) { - const errorMessage = await res.text(); - if (errorMessage !== '') { - done(); // success - } else { - done("Status code was 403 but message was: " + errorMessage); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 403); + const errorMessage = await res.text(); + assert.notStrictEqual(errorMessage, ''); + done(); }) .catch(err => done(err)); }); @@ -788,11 +712,11 @@ describe('postSkipSegments', () => { }], }), }) - .then(async res => { - if (res.status === 400) done(); - else done(true); + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done(true)); + .catch(err => done(err)); }); it('Should return 400 for missing params (JSON method) 2', (done: Done) => { fetch(getbaseURL() @@ -806,11 +730,11 @@ describe('postSkipSegments', () => { videoID: "dQw4w9WgXcQ", }), }) - .then(async res => { - if (res.status === 400) done(); - else done(true); + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done(true)); + .catch(err => done(err)); }); it('Should return 400 for missing params (JSON method) 3', (done: Done) => { fetch(getbaseURL() @@ -831,11 +755,11 @@ describe('postSkipSegments', () => { }], }), }) - .then(async res => { - if (res.status === 400) done(); - else done(true); + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done(true)); + .catch(err => done(err)); }); it('Should return 400 for missing params (JSON method) 4', (done: Done) => { fetch(getbaseURL() @@ -855,11 +779,11 @@ describe('postSkipSegments', () => { }], }), }) - .then(async res => { - if (res.status === 400) done(); - else done(true); + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done(true)); + .catch(err => done(err)); }); it('Should return 400 for missing params (JSON method) 5', (done: Done) => { fetch(getbaseURL() @@ -873,10 +797,10 @@ describe('postSkipSegments', () => { videoID: "dQw4w9WgXcQ", }), }) - .then(async res => { - if (res.status === 400) done(); - else done(true); + .then(res => { + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done(true)); + .catch(err => done(err)); }); }); diff --git a/test/cases/postWarning.ts b/test/cases/postWarning.ts index 8231148..0e6d3dc 100644 --- a/test/cases/postWarning.ts +++ b/test/cases/postWarning.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('postWarning', () => { before(async () => { @@ -23,18 +24,12 @@ describe('postWarning', () => { body: JSON.stringify(json), }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "userID", "issueTime", "issuerUserID", enabled, "reason" FROM warnings WHERE "userID" = ?`, [json.userID]); - if (row?.enabled == 1 && row?.issuerUserID == getHash(json.issuerUserID) && row?.reason === json.reason) { - done(); - } else { - done("Warning missing from database"); - } - } else { - const body = await res.text(); - console.log(body); - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "userID", "issueTime", "issuerUserID", enabled, "reason" FROM warnings WHERE "userID" = ?`, [json.userID]); + assert.strictEqual(row.enabled, 1); + assert.strictEqual(row.issuerUserID, getHash(json.issuerUserID)); + assert.strictEqual(row.reason, json.reason); + done(); }) .catch(err => done(err)); }); @@ -54,18 +49,11 @@ describe('postWarning', () => { body: JSON.stringify(json), }) .then(async res => { - if (res.status === 409) { - const row = await db.prepare('get', `SELECT "userID", "issueTime", "issuerUserID", enabled FROM warnings WHERE "userID" = ?`, [json.userID]); - if (row?.enabled == 1 && row?.issuerUserID == getHash(json.issuerUserID)) { - done(); - } else { - done("Warning missing from database"); - } - } else { - const body = await res.text(); - console.log(body); - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 409); + const row = await db.prepare('get', `SELECT "userID", "issueTime", "issuerUserID", enabled FROM warnings WHERE "userID" = ?`, [json.userID]); + assert.strictEqual(row.enabled, 1); + assert.strictEqual(row.issuerUserID, getHash(json.issuerUserID)); + done(); }) .catch(err => done(err)); }); @@ -86,18 +74,10 @@ describe('postWarning', () => { body: JSON.stringify(json), }) .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "userID", "issueTime", "issuerUserID", enabled FROM warnings WHERE "userID" = ?`, [json.userID]); - if (row?.enabled == 0) { - done(); - } else { - done("Warning missing from database"); - } - } else { - const body = await res.text(); - console.log(body); - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "userID", "issueTime", "issuerUserID", enabled FROM warnings WHERE "userID" = ?`, [json.userID]); + assert.strictEqual(row.enabled, 0); + done(); }) .catch(err => done(err)); }); @@ -116,14 +96,9 @@ describe('postWarning', () => { }, body: JSON.stringify(json), }) - .then(async res => { - if (res.status === 403) { - done(); - } else { - const body = await res.text(); - console.log(body); - done("Status code was " + res.status); - } + .then(res => { + assert.strictEqual(res.status, 403); + done(); }) .catch(err => done(err)); }); diff --git a/test/cases/segmentShift.ts b/test/cases/segmentShift.ts index 4a0cae6..db5ad98 100644 --- a/test/cases/segmentShift.ts +++ b/test/cases/segmentShift.ts @@ -3,6 +3,7 @@ import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; import {IDatabase} from '../../src/databases/IDatabase'; +import assert from 'assert'; async function dbSponsorTimesAdd(db: IDatabase, videoID: string, startTime: number, endTime: number, UUID: string, category: string) { const votes = 0, @@ -22,25 +23,18 @@ async function dbSponsorTimesSetByUUID(db: IDatabase, UUID: string, startTime: n await db.prepare('run', `UPDATE "sponsorTimes" SET "startTime" = ?, "endTime" = ? WHERE "UUID" = ?`, [startTime, endTime, UUID]); } -async function dbSponsorTimesCompareExpect(db: IDatabase, expect: any) { +async function dbSponsorTimesCompareExpect(db: IDatabase, expect: any): Promise { for (let i = 0, len = expect.length; i < len; i++) { const expectSeg = expect[i]; const seg = await db.prepare('get', `SELECT "startTime", "endTime" FROM "sponsorTimes" WHERE "UUID" = ?`, [expectSeg.UUID]); if ('removed' in expect) { - if (expect.removed === true && seg.votes === -2) { - return; - } else { - return `${expectSeg.UUID} doesnt got removed`; - } - } - if (seg.startTime !== expectSeg.startTime) { - return `${expectSeg.UUID} startTime is incorrect. seg.startTime is ${seg.startTime} expected ${expectSeg.startTime}`; - } - if (seg.endTime !== expectSeg.endTime) { - return `${expectSeg.UUID} endTime is incorrect. seg.endTime is ${seg.endTime} expected ${expectSeg.endTime}`; + assert.ok(expect.removed); + assert.strictEqual(seg.votes, -2); + assert.deepStrictEqual(seg, expectSeg); + assert.strictEqual(seg.startTime, expectSeg.startTime); + assert.strictEqual(seg.endTime, expectSeg.endTime); } } - return; } describe('segmentShift', function () { @@ -79,7 +73,8 @@ describe('segmentShift', function () { }), }) .then(async res => { - done(res.status === 403 ? undefined : res.status); + assert.strictEqual(res.status, 403); + done(); }) .catch(err => done(err)); }); @@ -98,7 +93,7 @@ describe('segmentShift', function () { }), }) .then(async res => { - if (res.status !== 200) return done(`Status code was ${res.status}`); + assert.strictEqual(res.status, 200); const expect = [ { UUID: 'vsegshifttest01uuid01', @@ -140,7 +135,7 @@ describe('segmentShift', function () { }), }) .then(async res => { - if (res.status !== 200) return done(`Status code was ${res.status}`); + assert.strictEqual(res.status, 200); const expect = [ { UUID: 'vsegshifttest01uuid01', @@ -182,7 +177,7 @@ describe('segmentShift', function () { }), }) .then(async res => { - if (res.status !== 200) return done(`Status code was ${res.status}`); + assert.strictEqual(res.status, 200); const expect = [ { UUID: 'vsegshifttest01uuid01', @@ -224,7 +219,7 @@ describe('segmentShift', function () { }), }) .then(async res => { - if (res.status !== 200) return done(`Status code was ${res.status}`); + assert.strictEqual(res.status, 200); const expect = [ { UUID: 'vsegshifttest01uuid01', @@ -266,7 +261,7 @@ describe('segmentShift', function () { }), }) .then(async res => { - if (res.status !== 200) return done(`Status code was ${res.status}`); + assert.strictEqual(res.status, 200); const expect = [ { UUID: 'vsegshifttest01uuid01', diff --git a/test/cases/setUsername.ts b/test/cases/setUsername.ts index b3e5ad4..58a0e5b 100644 --- a/test/cases/setUsername.ts +++ b/test/cases/setUsername.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import { Done, getbaseURL } from '../utils'; import { db, privateDB } from '../../src/databases/databases'; import { getHash } from '../../src/utils/getHash'; +import assert from 'assert'; const adminPrivateUserID = 'testUserId'; const user00PrivateUserID = 'setUsername_00'; @@ -51,21 +52,10 @@ function wellFormatUserName(userName: string) { } async function testUserNameChangelog(userID: string, newUserName: string, oldUserName: string, byAdmin: boolean, done: Done) { - const log = await getLastLogUserNameChange(userID); - - if (newUserName !== log.newUserName) { - return done(`UserID '${userID}' incorrect log on newUserName: ${newUserName} !== ${log.newUserName}`); - } - - if (oldUserName !== log.oldUserName) { - return done(`UserID '${userID}' incorrect log on oldUserName: ${oldUserName} !== ${log.oldUserName}`); - } - - if (byAdmin !== Boolean(log.updatedByAdmin)) { - return done(`UserID '${userID}' incorrect log on updatedByAdmin: ${byAdmin} !== ${log.updatedByAdmin}`); - } - + assert.strictEqual(newUserName, log.newUserName); + assert.strictEqual(oldUserName, log.oldUserName); + assert.strictEqual(byAdmin, Boolean(log.updatedByAdmin)); return done(); } @@ -86,9 +76,9 @@ describe('setUsername', () => { }) .then(async res => { const usernameInfo = await getUsernameInfo(getHash(user00PrivateUserID)); - if (res.status !== 200) done(`Status code was ${res.status}`); - if (usernameInfo.userName !== username00) done(`Username did not change. Currently is ${usernameInfo.userName}`); - if (usernameInfo.locked == "1") done(`Username was locked when it shouldn't have been`); + assert.strictEqual(res.status, 200); + assert.strictEqual(usernameInfo.userName, username00); + assert.notStrictEqual(usernameInfo.locked, 1, "username should not be locked"); done(); }) .catch(() => done(`couldn't call endpoint`)); @@ -99,10 +89,8 @@ describe('setUsername', () => { method: 'POST', }) .then(async res => { - if (res.status !== 200) done(`Status code was ${res.status}`); - else { - testUserNameChangelog(user01PrivateUserID, decodeURIComponent('Changed%20Username'), username01, false, done); - } + assert.strictEqual(res.status, 200); + testUserNameChangelog(user01PrivateUserID, decodeURIComponent('Changed%20Username'), username01, false, done); }) .catch(() => done(`couldn't call endpoint`)); }); @@ -112,8 +100,8 @@ describe('setUsername', () => { method: 'POST', }) .then(res => { - if (res.status !== 400) done(`Status code was ${res.status}`); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) .catch(() => done(`couldn't call endpoint`)); }); @@ -123,8 +111,8 @@ describe('setUsername', () => { method: 'POST', }) .then(res => { - if (res.status !== 400) done(`Status code was ${res.status}`); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) .catch(() => done(`couldn't call endpoint`)); }); @@ -135,8 +123,8 @@ describe('setUsername', () => { method: 'POST', }) .then(res => { - if (res.status !== 400) done(`Status code was ${res.status}`); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) .catch(() => done(`couldn't call endpoint`)); }); @@ -147,14 +135,10 @@ describe('setUsername', () => { method: 'POST', }) .then(async res => { - if (res.status !== 200) done(`Status code was ${res.status}`); - else { - const userNameInfo = await getUsernameInfo(getHash(user02PrivateUserID)); - if (userNameInfo.userName === newUsername) { - done(`Username '${username02}' got changed to '${newUsername}'`); - } - else done(); - } + assert.strictEqual(res.status, 200); + const userNameInfo = await getUsernameInfo(getHash(user02PrivateUserID)); + assert.notStrictEqual(userNameInfo.userName, newUsername); + done(); }) .catch(() => done(`couldn't call endpoint`)); }); @@ -166,8 +150,8 @@ describe('setUsername', () => { }) .then(async () => { const usernameInfo = await getUsernameInfo(getHash(user03PrivateUserID)); - if (usernameInfo.userName !== newUsername) done(`Username did not change`); - if (usernameInfo.locked == "1") done(`Username was locked when it shouldn't have been`); + assert.strictEqual(usernameInfo.userName, newUsername, "Username should change"); + assert.notStrictEqual(usernameInfo.locked, 1, "Username should not be locked"); testUserNameChangelog(user03PrivateUserID, newUsername, username03, false, done); }) .catch(() => done(`couldn't call endpoint`)); @@ -180,9 +164,9 @@ describe('setUsername', () => { }) .then(async () => { const usernameInfo = await getUsernameInfo(getHash(user04PrivateUserID)); - if (usernameInfo.userName === newUsername) done(`Username '${username04}' got changed to '${usernameInfo}'`); - if (usernameInfo.locked == "0") done(`Username was unlocked when it shouldn't have been`); - else done(); + assert.notStrictEqual(usernameInfo.userName, newUsername, "Username should not be changed"); + assert.strictEqual(usernameInfo.locked, 1, "username should be locked"); + done(); }) .catch(() => done(`couldn't call endpoint`)); }); @@ -194,7 +178,7 @@ describe('setUsername', () => { }) .then(async () => { const usernameInfo = await getUsernameInfo(getHash(user05PrivateUserID)); - if (usernameInfo.userName === newUsername) done(`Username contains unicode control characters`); + assert.notStrictEqual(usernameInfo.userName, newUsername, "Username should not contain control characters"); testUserNameChangelog(user05PrivateUserID, wellFormatUserName(newUsername), username05, false, done); }) .catch(() => done(`couldn't call endpoint`)); @@ -206,8 +190,8 @@ describe('setUsername', () => { method: 'POST', }) .then(async res => { - if (res.status !== 403) done(`Status code was ${res.status}`); - else done(); + assert.strictEqual(res.status, 403); + done(); }) .catch(() => done(`couldn't call endpoint`)); }); @@ -219,9 +203,9 @@ describe('setUsername', () => { }) .then(async () => { const usernameInfo = await getUsernameInfo(getHash(user06PrivateUserID)); - if (usernameInfo.userName !== newUsername) done(`Failed to change username from '${username06}' to '${newUsername}'`); - if (usernameInfo.locked == "0") done(`Username was not locked`); - else testUserNameChangelog(user06PrivateUserID, newUsername, username06, true, done); + assert.strictEqual(usernameInfo.userName, newUsername, "username should be changed"); + assert.strictEqual(usernameInfo.locked, 1, "Username should be locked"); + testUserNameChangelog(user06PrivateUserID, newUsername, username06, true, done); }) .catch(() => done(`couldn't call endpoint`)); }); @@ -233,9 +217,9 @@ describe('setUsername', () => { }) .then(async () => { const usernameInfo = await getUsernameInfo(getHash(user06PrivateUserID)); - if (usernameInfo.userName !== newUsername) done(`Failed to change username from '${username06}' to '${newUsername}'`); - if (usernameInfo.locked == "0") done(`Username was unlocked when it shouldn't have been`); - else testUserNameChangelog(user07PrivateUserID, newUsername, username07, true, done); + assert.strictEqual(usernameInfo.userName, newUsername, "Username should be changed"); + assert.strictEqual(usernameInfo.locked, 1, "Username should be locked"); + testUserNameChangelog(user07PrivateUserID, newUsername, username07, true, done); }) .catch(() => done(`couldn't call endpoint`)); }); diff --git a/test/cases/shadowBanUser.ts b/test/cases/shadowBanUser.ts index 49e05a4..6989097 100644 --- a/test/cases/shadowBanUser.ts +++ b/test/cases/shadowBanUser.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {db} from '../../src/databases/databases'; import {Done, getbaseURL} from '../utils'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('shadowBanUser', () => { before(async () => { @@ -28,19 +29,14 @@ describe('shadowBanUser', () => { method: 'POST' }) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const videoRow = await db.prepare('all', `SELECT "shadowHidden" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned", 1]); - const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned"]); - - if (shadowRow && videoRow?.length === 3) { - done(); - } else { - done("Ban failed " + JSON.stringify(videoRow) + " " + JSON.stringify(shadowRow)); - } - } + assert.strictEqual(res.status, 200); + const videoRow = await db.prepare('all', `SELECT "shadowHidden" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned", 1]); + const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned"]); + assert.ok(shadowRow); + assert.strictEqual(videoRow.length, 3); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to unban user without unhiding submissions', (done: Done) => { @@ -48,19 +44,14 @@ describe('shadowBanUser', () => { method: 'POST' }) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const videoRow = await db.prepare('all', `SELECT "shadowHidden" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned", 1]); - const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned"]); - - if (!shadowRow && videoRow?.length === 3) { - done(); - } else { - done("Unban failed " + JSON.stringify(videoRow) + " " + JSON.stringify(shadowRow)); - } - } + assert.strictEqual(res.status, 200); + const videoRow = await db.prepare('all', `SELECT "shadowHidden" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned", 1]); + const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned"]); + assert.ok(!shadowRow); + assert.strictEqual(videoRow.length, 3); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to ban user and hide submissions from only some categories', (done: Done) => { @@ -68,19 +59,15 @@ describe('shadowBanUser', () => { method: 'POST' }) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const videoRow: {category: string, shadowHidden: number}[] = (await db.prepare('all', `SELECT "shadowHidden", "category" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned2", 1])); - const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned2"]); - - if (shadowRow && 2 == videoRow?.length && 2 === videoRow?.filter((elem) => elem?.category === "sponsor")?.length) { - done(); - } else { - done("Ban failed " + JSON.stringify(videoRow) + " " + JSON.stringify(shadowRow)); - } - } + assert.strictEqual(res.status, 200); + const videoRow: {category: string, shadowHidden: number}[] = (await db.prepare('all', `SELECT "shadowHidden", "category" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned2", 1])); + const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned2"]); + assert.ok(shadowRow); + assert.strictEqual(videoRow.length, 2); + assert.strictEqual(videoRow.filter((elem) => elem.category === "sponsor").length, 2); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to unban user and unhide submissions', (done: Done) => { @@ -88,19 +75,14 @@ describe('shadowBanUser', () => { method: 'POST' }) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const videoRow = await db.prepare('all', `SELECT "shadowHidden" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned2", 1]); - const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned2"]); - - if (!shadowRow && videoRow?.length === 0) { - done(); - } else { - done("Unban failed " + JSON.stringify(videoRow) + " " + JSON.stringify(shadowRow)); - } - } + assert.strictEqual(res.status, 200); + const videoRow = await db.prepare('all', `SELECT "shadowHidden" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned2", 1]); + const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned2"]); + assert.ok(!shadowRow); + assert.strictEqual(videoRow?.length, 0); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); it('Should be able to unban user and unhide some submissions', (done: Done) => { @@ -108,19 +90,15 @@ describe('shadowBanUser', () => { method: 'POST' }) .then(async res => { - if (res.status !== 200) done("Status code was: " + res.status); - else { - const videoRow = await db.prepare('all', `SELECT "shadowHidden", "category" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned3", 1]); - const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned3"]); - - if (!shadowRow && videoRow?.length === 1 && videoRow[0]?.category === "intro") { - done(); - } else { - done("Unban failed " + JSON.stringify(videoRow) + " " + JSON.stringify(shadowRow)); - } - } + assert.strictEqual(res.status, 200); + const videoRow = await db.prepare('all', `SELECT "shadowHidden", "category" FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?`, ["shadowBanned3", 1]); + const shadowRow = await db.prepare('get', `SELECT * FROM "shadowBannedUsers" WHERE "userID" = ?`, ["shadowBanned3"]); + assert.ok(!shadowRow); + assert.strictEqual(videoRow.length, 1); + assert.strictEqual(videoRow[0].category, "intro"); + done(); }) - .catch(() => done("Couldn't call endpoint")); + .catch(err => done(err)); }); }); diff --git a/test/cases/unBan.ts b/test/cases/unBan.ts index 19a6a16..6231cbe 100644 --- a/test/cases/unBan.ts +++ b/test/cases/unBan.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import * as utils from '../utils'; import { getHash } from '../../src/utils/getHash'; import { db } from '../../src/databases/databases'; +import assert from 'assert'; describe('unBan', () => { before(async () => { @@ -31,19 +32,10 @@ describe('unBan', () => { }, }) .then(async res => { - if (res.status === 200) { - const result = await db.prepare('all', 'SELECT * FROM "sponsorTimes" WHERE "videoID" = ? AND "userID" = ? AND "shadowHidden" = ?', ['unBan-videoID-0', 'testMan-unBan', 1]); - if (result.length !== 0) { - console.log(result); - done("Expected 0 banned entrys in db, got " + result.length); - } else { - done(); - } - } else { - const body = await res.text(); - console.log(body); - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const result = await db.prepare('all', 'SELECT * FROM "sponsorTimes" WHERE "videoID" = ? AND "userID" = ? AND "shadowHidden" = ?', ['unBan-videoID-0', 'testMan-unBan', 1]); + assert.strictEqual(result.length, 0); + done(); }) .catch(err => done(err)); }); @@ -56,19 +48,10 @@ describe('unBan', () => { }, }) .then(async res => { - if (res.status === 200) { - const result = await db.prepare('all', 'SELECT * FROM "sponsorTimes" WHERE "videoID" = ? AND "userID" = ? AND "shadowHidden" = ?', ['unBan-videoID-1', 'testWoman-unBan', 1]); - if (result.length !== 1) { - console.log(result); - done("Expected 1 banned entry1 in db, got " + result.length); - } else { - done(); - } - } else { - const body = await res.text(); - console.log(body); - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const result = await db.prepare('all', 'SELECT * FROM "sponsorTimes" WHERE "videoID" = ? AND "userID" = ? AND "shadowHidden" = ?', ['unBan-videoID-1', 'testWoman-unBan', 1]); + assert.strictEqual(result.length, 1); + done(); }) .catch(err => done(err)); }); @@ -81,19 +64,10 @@ describe('unBan', () => { }, }) .then(async res => { - if (res.status === 200) { - const result = await db.prepare('all', 'SELECT * FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?', ['testEntity-unBan', 1]); - if (result.length !== 1) { - console.log(result); - done("Expected 1 banned entry1 in db, got " + result.length); - } else { - done(); - } - } else { - const body = await res.text(); - console.log(body); - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const result = await db.prepare('all', 'SELECT * FROM "sponsorTimes" WHERE "userID" = ? AND "shadowHidden" = ?', ['testEntity-unBan', 1]); + assert.strictEqual(result.length, 1); + done(); }) .catch(err => done(err)); }); diff --git a/test/cases/voteOnSponsorTime.ts b/test/cases/voteOnSponsorTime.ts index 8e0cc1e..54c727d 100644 --- a/test/cases/voteOnSponsorTime.ts +++ b/test/cases/voteOnSponsorTime.ts @@ -6,6 +6,7 @@ import {getHash} from '../../src/utils/getHash'; import {ImportMock} from 'ts-mock-imports'; import * as YouTubeAPIModule from '../../src/utils/youtubeApi'; import {YouTubeApiMock} from '../youtubeMock'; +import assert from 'assert'; const mockManager = ImportMock.mockStaticClass(YouTubeAPIModule, 'YouTubeAPI'); const sinonStub = mockManager.mock('listVideos'); @@ -66,16 +67,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID&UUID=vote-uuid-0&type=1") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-0"]); - if (row.votes === 3) { - done(); - } else { - done("Vote did not succeed. Submission went from 2 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-0"]); + assert.strictEqual(row.votes, 3); + done(); }) .catch(err => done(err)); }); @@ -84,16 +79,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-2&type=0") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-2"]); - if (row.votes < 10) { - done(); - } else { - done("Vote did not succeed. Submission went from 10 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-2"]); + assert.ok(row.votes < 10); + done(); }) .catch(err => done(err)); }); @@ -102,16 +91,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID3&UUID=vote-uuid-2&type=0") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-2"]); - if (row.votes === 9) { - done(); - } else { - done("Vote did not fail. Submission went from 9 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-2"]); + assert.strictEqual(row.votes, 9); + done(); }) .catch(err => done(err)); }); @@ -120,16 +103,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID4&UUID=vote-uuid-1.6&type=0") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-1.6"]); - if (row.votes === 10) { - done(); - } else { - done("Vote did not fail. Submission went from 10 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-1.6"]); + assert.strictEqual(row.votes, 10); + done(); }) .catch(err => done(err)); }); @@ -138,16 +115,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=hasNotSubmittedID&UUID=vote-uuid-1&type=1") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-1"]); - if (row.votes === 2) { - done(); - } else { - done("Vote did not fail. Submission went from 2 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-1"]); + assert.strictEqual(row.votes, 2); + done(); }) .catch(err => done(err)); }); @@ -156,16 +127,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=hasNotSubmittedID&UUID=vote-uuid-1.5&type=0") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-1.5"]); - if (row.votes === 10) { - done(); - } else { - done("Vote did not fail. Submission went from 10 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-1.5"]); + assert.strictEqual(row.votes, 10); + done(); }) .catch(err => done(err)); }); @@ -174,16 +139,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=VIPUser&UUID=vote-uuid-3&type=0") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-3"]); - if (row.votes <= -2) { - done(); - } else { - done("Vote did not succeed. Submission went from 100 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-3"]); + assert.ok(row.votes <= -2); + done(); }) .catch(err => done(err)); }); @@ -192,16 +151,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=own-submission-id&UUID=own-submission-uuid&type=0") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["own-submission-uuid"]); - if (row.votes <= -2) { - done(); - } else { - done("Vote did not succeed. Submission went from 500 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["own-submission-uuid"]); + assert.ok(row.votes <= -2); + done(); }) .catch(err => done(err)); }); @@ -210,16 +163,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID2&UUID=not-own-submission-uuid&type=0") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["not-own-submission-uuid"]); - if (row.votes === 499) { - done(); - } else { - done("Vote did not succeed. Submission went from 500 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["not-own-submission-uuid"]); + assert.strictEqual(row.votes, 499); + done(); }) .catch(err => done(err)); }); @@ -228,19 +175,16 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-4&category=intro") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-4"]); - const categoryRows = await db.prepare('all', `SELECT votes, category FROM "categoryVotes" WHERE "UUID" = ?`, ["vote-uuid-4"]); - if (row.category === "sponsor" && categoryRows.length === 2 - && categoryRows[0]?.votes === 1 && categoryRows[0]?.category === "intro" - && categoryRows[1]?.votes === 1 && categoryRows[1]?.category === "sponsor") { - done(); - } else { - done("Submission changed to " + row.category + " instead of staying as sponsor. Vote was applied as " + categoryRows[0]?.category + " with " + categoryRows[0]?.votes + " votes and there were " + categoryRows.length + " rows."); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-4"]); + const categoryRows = await db.prepare('all', `SELECT votes, category FROM "categoryVotes" WHERE "UUID" = ?`, ["vote-uuid-4"]); + assert.strictEqual(row.category, "sponsor"); + assert.strictEqual(categoryRows.length, 2); + assert.strictEqual(categoryRows[0].votes, 1); + assert.strictEqual(categoryRows[0].category, "intro"); + assert.strictEqual(categoryRows[1].votes, 1); + assert.strictEqual(categoryRows[1].category, "sponsor"); + done(); }) .catch(err => done(err)); }); @@ -249,16 +193,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID2&UUID=incorrect-category&category=fakecategory") .then(async res => { - if (res.status === 400) { - const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["incorrect-category"]); - if (row.category === "sponsor") { - done(); - } else { - done("Vote did not succeed. Submission went from sponsor to " + row.category); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 400); + const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["incorrect-category"]); + assert.strictEqual(row.category, "sponsor"); + done(); }) .catch(err => done(err)); }); @@ -267,16 +205,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID2&UUID=incorrect-category&category=highlight") .then(async res => { - if (res.status === 400) { - const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["incorrect-category"]); - if (row.category === "sponsor") { - done(); - } else { - done("Vote did not succeed. Submission went from sponsor to " + row.category); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 400); + const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["incorrect-category"]); + assert.strictEqual(row.category, "sponsor"); + done(); }) .catch(err => done(err)); }); @@ -296,13 +228,12 @@ describe('voteOnSponsorTime', () => { if (row?.category === "outro") outroVotes += row?.votes; if (row?.category === "sponsor") sponsorVotes += row?.votes; } - if (submissionRow.category === "sponsor" && categoryRows.length === 3 - && introVotes === 0 && outroVotes === 1 && sponsorVotes === 1) { - done(); - } else { - done("Submission changed to " + submissionRow.category + " instead of staying as sponsor. There were " - + introVotes + " intro votes, " + outroVotes + " outro votes and " + sponsorVotes + " sponsor votes."); - } + assert.strictEqual(submissionRow.category, "sponsor"); + assert.strictEqual(categoryRows.length, 3); + assert.strictEqual(introVotes, 0); + assert.strictEqual(outroVotes, 1); + assert.strictEqual(sponsorVotes, 1); + done(); } else { done("Status code was " + res.status); } @@ -317,11 +248,8 @@ describe('voteOnSponsorTime', () => { + "/api/voteOnSponsorTime?userID=randomID2&UUID=incorrect-category-change&category=" + inputCat) .then(async () => { const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["incorrect-category-change"]); - if (row.category === assertCat) { - callback(); - } else { - done("Vote did not succeed. Submission went from sponsor to " + row.category); - } + assert.strictEqual(row.category, assertCat); + callback(); }) .catch(err => done(err)); }; @@ -335,17 +263,12 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=VIPUser&UUID=vote-uuid-5&category=outro") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]); - const row2 = await db.prepare('get', `SELECT votes FROM "categoryVotes" WHERE "UUID" = ? and category = ?`, ["vote-uuid-5", "outro"]); - if (row.category === "outro" && row2.votes === 500) { - done(); - } else { - done("Vote did not succeed. Submission went from intro to " + row.category + ". Category votes are " + row2.votes + " and should be 500."); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]); + const row2 = await db.prepare('get', `SELECT votes FROM "categoryVotes" WHERE "UUID" = ? and category = ?`, ["vote-uuid-5", "outro"]); + assert.strictEqual(row.category, "outro"); + assert.strictEqual(row2.votes, 500); + done(); }) .catch(err => done(err)); }); @@ -354,16 +277,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=testman&UUID=vote-uuid-5_1&category=outro") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]); - if (row.category === "outro") { - done(); - } else { - done("Vote did not succeed. Submission went from intro to " + row.category + "."); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]); + assert.strictEqual(row.category, "outro"); + done(); }) .catch(err => done(err)); }); @@ -372,11 +289,8 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID3&UUID=invalid-uuid&category=intro") .then(async res => { - if (res.status === 400) { - done(); - } else { - done("Status code was " + res.status + " instead of 400."); - } + assert.strictEqual(res.status, 400); + done(); }) .catch(err => done(err)); }); @@ -385,12 +299,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-5&type=1") .then(async res => { + assert.strictEqual(res.status, 403); const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]); - if (res.status === 403 && row.votes === -3) { - done(); - } else { - done("Status code was " + res.status + ", row is " + JSON.stringify(row)); - } + assert.strictEqual(row.votes, -3); + done(); }) .catch(err => done(err)); }); @@ -399,12 +311,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-5&type=0") .then(async res => { + assert.strictEqual(res.status, 200); const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]); - if (res.status === 200 && row.votes === -3) { - done(); - } else { - done("Status code was " + res.status + ", row is " + JSON.stringify(row)); - } + assert.strictEqual(row.votes, -3); + done(); }) .catch(err => done(err)); }); @@ -413,16 +323,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=VIPUser&UUID=vote-uuid-5&type=1") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]); - if (row.votes > -3) { - done(); - } else { - done("Vote did not succeed. Votes raised from -3 to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-5"]); + assert.ok(row.votes > -3); + done(); }) .catch(err => done(err)); }); @@ -431,11 +335,8 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=warn-voteuser01&UUID=warnvote-uuid-0&type=1") .then(async res => { - if (res.status === 403) { - done(); // success - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 403); + done(); }) .catch(err => done(err)); }); @@ -444,12 +345,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID&UUID=no-sponsor-segments-uuid-0&type=0") .then(async res => { + assert.strictEqual(res.status, 200); const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["no-sponsor-segments-uuid-0"]); - if (res.status === 200 && row.votes === 2) { - done(); - } else { - done("Status code was " + res.status + " instead of 200, row was " + JSON.stringify(row)); - } + assert.strictEqual(row.votes, 2); + done(); }) .catch(err => done(err)); }); @@ -458,12 +357,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID&UUID=no-sponsor-segments-uuid-0&type=1") .then(async res => { + assert.strictEqual(res.status, 200); const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["no-sponsor-segments-uuid-0"]); - if (res.status === 200 && row.votes === 3) { - done(); - } else { - done("Status code was " + res.status + " instead of 403, row was " + JSON.stringify(row)); - } + assert.strictEqual(row.votes, 3); + done(); }) .catch(err => done(err)); }); @@ -472,12 +369,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID&UUID=no-sponsor-segments-uuid-0&category=outro") .then(async res => { + assert.strictEqual(res.status, 200); const row = await db.prepare('get', `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, ["no-sponsor-segments-uuid-0"]); - if (res.status === 200 && row.category === "sponsor") { - done(); - } else { - done("Status code was " + res.status + " instead of 200, row was " + JSON.stringify(row)); - } + assert.strictEqual(row.category, "sponsor"); + done(); }) .catch(err => done(err)); }); @@ -486,16 +381,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=VIPUser&UUID=segment-locking-uuid-1&type=1") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "locked" FROM "sponsorTimes" WHERE "UUID" = ?`, ["segment-locking-uuid-1"]); - if (row?.locked) { - done(); - } else { - done("Segment not locked"); - } - } else { - done("Status code was " + res.status + " instead of 200"); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "locked" FROM "sponsorTimes" WHERE "UUID" = ?`, ["segment-locking-uuid-1"]); + assert.ok(row.locked); + done(); }) .catch(err => done(err)); }); @@ -504,16 +393,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=VIPUser&UUID=segment-locking-uuid-1&type=0") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "locked" FROM "sponsorTimes" WHERE "UUID" = ?`, ["segment-locking-uuid-1"]); - if (!row?.locked) { - done(); - } else { - done("Segment not locked"); - } - } else { - done("Status code was " + res.status + " instead of 200"); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "locked" FROM "sponsorTimes" WHERE "UUID" = ?`, ["segment-locking-uuid-1"]); + assert.ok(!row.locked); + done(); }) .catch(err => done(err)); }); @@ -522,16 +405,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=VIPUser&UUID=segment-hidden-uuid-1&type=1") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "hidden" FROM "sponsorTimes" WHERE "UUID" = ?`, ["segment-hidden-uuid-1"]); - if (!row?.hidden) { - done(); - } else { - done("Segment not unhidden"); - } - } else { - done("Status code was " + res.status + " instead of 200"); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "hidden" FROM "sponsorTimes" WHERE "UUID" = ?`, ["segment-hidden-uuid-1"]); + assert.ok(!row?.hidden); + done(); }) .catch(err => done(err)); }); @@ -540,16 +417,10 @@ describe('voteOnSponsorTime', () => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=randomID2&UUID=vote-uuid-2&type=20") .then(async res => { - if (res.status === 200) { - const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-2"]); - if (row.votes === 10) { - done(); - } else { - done("Vote did not succeed. Submission went from 10 votes to " + row.votes); - } - } else { - done("Status code was " + res.status); - } + assert.strictEqual(res.status, 200); + const row = await db.prepare('get', `SELECT "votes" FROM "sponsorTimes" WHERE "UUID" = ?`, ["vote-uuid-2"]); + assert.strictEqual(row.votes, 10); + done(); }) .catch(err => done(err)); }); @@ -557,19 +428,18 @@ describe('voteOnSponsorTime', () => { it('Should not be able to vote with type 10', (done: Done) => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=VIPUser&UUID=segment-locking-uuid-1&type=10") .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done('couldn\'t call endpoint')); + .catch(err => done(err)); }); it('Should not be able to vote with type 11', (done: Done) => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=VIPUser&UUID=segment-locking-uuid-1&type=11") .then(res => { - if (res.status !== 400) done('non 400 (' + res.status + ')'); - else done(); // pass + assert.strictEqual(res.status, 400); + done(); }) - .catch(() => done('couldn\'t call endpoint')); + .catch(err => done(err)); }); - }); diff --git a/test/test.ts b/test/test.ts index bba97ab..ddd6257 100644 --- a/test/test.ts +++ b/test/test.ts @@ -12,9 +12,7 @@ import rateLimit from 'express-rate-limit'; async function init() { ImportMock.mockFunction(rateLimitMiddlewareModule, 'rateLimitMiddleware', rateLimit({ - skip: () => { - return true; - } + skip: () => true })); // delete old test database @@ -35,10 +33,10 @@ async function init() { // Add each .ts file to the mocha instance fs.readdirSync(testDir) - .filter(function(file) { + .filter((file) => // Only keep the .ts files - return file.substr(-3) === '.ts'; - }) + file.substr(-3) === '.ts' + ) .forEach(function(file) { mocha.addFile( path.join(testDir, file) From 2d38ef921e0503e7c81f15e5f4a7b6e0aa1b8758 Mon Sep 17 00:00:00 2001 From: Michael C Date: Thu, 8 Jul 2021 00:59:15 -0400 Subject: [PATCH 08/24] use deepStringEqual instead of deepAssert --- test/cases/lockCategoriesRecords.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/cases/lockCategoriesRecords.ts b/test/cases/lockCategoriesRecords.ts index 38f40d8..49337d3 100644 --- a/test/cases/lockCategoriesRecords.ts +++ b/test/cases/lockCategoriesRecords.ts @@ -5,6 +5,12 @@ import {db} from '../../src/databases/databases'; import assert from 'assert'; import {LockCategory} from '../../src/types/segments.model'; +const deepStringEqual = (a: string[], b: string[]): boolean => { + if (a.length !== b.length) return false; + a.forEach((e) => { if (!b.includes(e)) return false; }); + return true; +}; + describe('lockCategoriesRecords', () => { before(async () => { const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)'; @@ -565,7 +571,7 @@ describe('lockCategoriesRecords', () => { .then(async res => { assert.strictEqual(res.status, 200); const data = await res.json(); - assert.deepStrictEqual(data, expected); + assert.ok(deepStringEqual(data.categories, expected.categories)); done(); }) .catch(err => done(err)); From 81cae514a00922e168c75e68c31dd45df3463681 Mon Sep 17 00:00:00 2001 From: Michael C Date: Fri, 9 Jul 2021 00:31:42 -0400 Subject: [PATCH 09/24] Update dependencies --- package-lock.json | 1031 +++++++++++++++++++++++---------------------- package.json | 48 +-- 2 files changed, 538 insertions(+), 541 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2a1e3db..0cbfd17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,38 +10,34 @@ "license": "MIT", "dependencies": { "@ajayyy/lru-diskcache": "^1.1.9", - "abort-controller": "^3.0.0", - "better-sqlite3": "^7.1.5", - "dotenv": "^8.2.0", + "@types/request": "^2.48.6", + "better-sqlite3": "^7.4.1", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "express-rate-limit": "^5.1.3", - "http": "0.0.0", - "node-fetch": "^2.6.0", - "pg": "^8.5.1", - "redis": "^3.1.1", - "sync-mysql": "^3.0.1", - "uuid": "^3.3.2" + "express-rate-limit": "^5.3.0", + "node-fetch": "^2.6.1", + "pg": "^8.6.0", + "redis": "^3.1.2", + "sync-mysql": "^3.0.1" }, "devDependencies": { - "@types/better-sqlite3": "^5.4.0", - "@types/express": "^4.17.8", - "@types/express-rate-limit": "^5.1.0", - "@types/mocha": "^8.2.2", - "@types/node": "^14.11.9", - "@types/node-fetch": "^2.5.7", - "@types/pg": "^7.14.10", - "@types/redis": "^2.8.28", - "@types/request": "^2.48.5", - "@typescript-eslint/eslint-plugin": "^4.28.1", - "@typescript-eslint/parser": "^4.28.1", + "@types/better-sqlite3": "^5.4.3", + "@types/express": "^4.17.13", + "@types/express-rate-limit": "^5.1.3", + "@types/mocha": "^8.2.3", + "@types/node": "^16.3.0", + "@types/node-fetch": "^2.5.11", + "@types/pg": "^8.6.1", + "@types/redis": "^2.8.31", + "@typescript-eslint/eslint-plugin": "^4.28.2", + "@typescript-eslint/parser": "^4.28.2", "eslint": "^7.30.0", - "mocha": "^8.4.0", + "mocha": "^9.0.2", "nodemon": "^2.0.2", - "sinon": "^9.2.0", - "ts-mock-imports": "^1.3.0", - "ts-node": "^9.0.0", - "typescript": "^4.0.3" + "sinon": "^11.1.1", + "ts-mock-imports": "^1.3.7", + "ts-node": "^10.0.0", + "typescript": "^4.3.5" } }, "node_modules/@ajayyy/lru-diskcache": { @@ -271,9 +267,9 @@ } }, "node_modules/@nodelib/fs.walk": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", - "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -284,37 +280,27 @@ } }, "node_modules/@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.7.0" } }, - "node_modules/@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, "node_modules/@sinonjs/samsam": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.2.0.tgz", - "integrity": "sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.0.2.tgz", + "integrity": "sha512-jxPRPp9n93ci7b8hMfJOFDPRLFYadN6FSpeROFTR4UNF4i5b+EK6m4QXPO46BDhFgRy1JuS87zAnFOzCUwMJcQ==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.6.0", @@ -328,10 +314,34 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz", + "integrity": "sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==", + "dev": true + }, "node_modules/@types/better-sqlite3": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-5.4.0.tgz", - "integrity": "sha512-nzm7lJ7l3jBmGUbtkL8cdOMhPkN6Pw2IM+b0V7iIKba+YKiLrjkIy7vVLsBIVnd7+lgzBzrHsXZxCaFTcmw5Ow==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-5.4.3.tgz", + "integrity": "sha512-d4T8Htgz3sQL3u5oVwkWipZLBYUooKEA4fhU9Sp4F6VDIhifQo1NR/IDtnAIID0Y9IXV3TQnNhv6S+m8TnkEdg==", "dev": true, "dependencies": { "@types/integer": "*" @@ -350,8 +360,7 @@ "node_modules/@types/caseless": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", - "dev": true + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" }, "node_modules/@types/connect": { "version": "3.4.33", @@ -363,30 +372,30 @@ } }, "node_modules/@types/express": { - "version": "4.17.8", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz", - "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==", + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", "devOptional": true, "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "*", + "@types/express-serve-static-core": "^4.17.18", "@types/qs": "*", "@types/serve-static": "*" } }, "node_modules/@types/express-rate-limit": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/express-rate-limit/-/express-rate-limit-5.1.0.tgz", - "integrity": "sha512-vmg7S3hUnfFmp06V01DrTB41mbQYXMV/F4aF5KKnfCIeSlnizatXaqO9UgR6LvNEEd3eMpuUTLxR6nv3d4hZ6g==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@types/express-rate-limit/-/express-rate-limit-5.1.3.tgz", + "integrity": "sha512-H+TYy3K53uPU2TqPGFYaiWc2xJV6+bIFkDd/Ma2/h67Pa6ARk9kWE0p/K9OH1Okm0et9Sfm66fmXoAxsH2PHXg==", "dev": true, "dependencies": { "@types/express": "*" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz", - "integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==", + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", "devOptional": true, "dependencies": { "@types/node": "*", @@ -401,9 +410,9 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", + "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", "dev": true }, "node_modules/@types/mime": { @@ -413,21 +422,20 @@ "devOptional": true }, "node_modules/@types/mocha": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", - "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", + "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==", "dev": true }, "node_modules/@types/node": { - "version": "14.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.9.tgz", - "integrity": "sha512-iXuiZ65PL5c8VAlF426GVJGKcsnAb2rW2037LJe3G6eM6nz35bK9QAUOH3Ic3kF4ZcKLpM02sFkSzCflIpoIKA==", - "devOptional": true + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.0.tgz", + "integrity": "sha512-OydMCocGMGqw/1BnWbhtK+AtwyWTOigtrQlRe57OQmTNcI3HKlVI5FGlh+c4mSqInMPLynFrTlYjfajPu9O/eQ==" }, "node_modules/@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.11.tgz", + "integrity": "sha512-2upCKaqVZETDRb8A2VTaRymqFBEgH8u6yr96b/u3+1uQEPDRo3mJLEiPk7vdXBHRtjwkjqzFYMJXrt0Z9QsYjQ==", "dev": true, "dependencies": { "@types/node": "*", @@ -435,13 +443,13 @@ } }, "node_modules/@types/pg": { - "version": "7.14.10", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-7.14.10.tgz", - "integrity": "sha512-m6G0mrpj71YgVgHJF0cIHC3OZTKiQSUzTkMj869a+YWXF2tdbmO2PmIpNnDkiFPhHWcoGq2bk5P2e0CZX0F9Mg==", + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", "dev": true, "dependencies": { "@types/node": "*", - "pg-protocol": "^1.2.0", + "pg-protocol": "*", "pg-types": "^2.2.0" } }, @@ -458,19 +466,18 @@ "devOptional": true }, "node_modules/@types/redis": { - "version": "2.8.28", - "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.28.tgz", - "integrity": "sha512-8l2gr2OQ969ypa7hFOeKqtFoY70XkHxISV0pAwmQ2nm6CSPb1brmTmqJCGGrekCo+pAZyWlNXr+Kvo6L/1wijA==", + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.31.tgz", + "integrity": "sha512-daWrrTDYaa5iSDFbgzZ9gOOzyp2AJmYK59OlG/2KGBgYWF3lfs8GDKm1c//tik5Uc93hDD36O+qLPvzDolChbA==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/request": { - "version": "2.48.5", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz", - "integrity": "sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==", - "dev": true, + "version": "2.48.6", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.6.tgz", + "integrity": "sha512-vrZaV3Ij7j/l/3hz6OttZFtpRCu7zlq7XgkYHJP6FwVEAZkGQ095WqyJV08/GlW9eyXKVcp/xmtruHm8eHpw1g==", "dependencies": { "@types/caseless": "*", "@types/node": "*", @@ -482,7 +489,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -503,19 +509,18 @@ } }, "node_modules/@types/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz", + "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.1.tgz", - "integrity": "sha512-9yfcNpDaNGQ6/LQOX/KhUFTR1sCKH+PBr234k6hI9XJ0VP5UqGxap0AnNwBnWFk1MNyWBylJH9ZkzBXC+5akZQ==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz", + "integrity": "sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==", "dev": true, "dependencies": { - "@typescript-eslint/experimental-utils": "4.28.1", - "@typescript-eslint/scope-manager": "4.28.1", + "@typescript-eslint/experimental-utils": "4.28.2", + "@typescript-eslint/scope-manager": "4.28.2", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.1.0", @@ -590,15 +595,15 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.1.tgz", - "integrity": "sha512-n8/ggadrZ+uyrfrSEchx3jgODdmcx7MzVM2sI3cTpI/YlfSm0+9HEUaWw3aQn2urL2KYlWYMDgn45iLfjDYB+Q==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz", + "integrity": "sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.28.1", - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/typescript-estree": "4.28.1", + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -614,14 +619,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.1.tgz", - "integrity": "sha512-UjrMsgnhQIIK82hXGaD+MCN8IfORS1CbMdu7VlZbYa8LCZtbZjJA26De4IPQB7XYZbL8gJ99KWNj0l6WD0guJg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.2.tgz", + "integrity": "sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "4.28.1", - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/typescript-estree": "4.28.1", + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", "debug": "^4.3.1" }, "engines": { @@ -664,13 +669,13 @@ "dev": true }, "node_modules/@typescript-eslint/scope-manager": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.1.tgz", - "integrity": "sha512-o95bvGKfss6705x7jFGDyS7trAORTy57lwJ+VsYwil/lOUxKQ9tA7Suuq+ciMhJc/1qPwB3XE2DKh9wubW8YYA==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz", + "integrity": "sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/visitor-keys": "4.28.1" + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2" }, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -681,9 +686,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.1.tgz", - "integrity": "sha512-4z+knEihcyX7blAGi7O3Fm3O6YRCP+r56NJFMNGsmtdw+NCdpG5SgNz427LS9nQkRVTswZLhz484hakQwB8RRg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.2.tgz", + "integrity": "sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==", "dev": true, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -694,13 +699,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.1.tgz", - "integrity": "sha512-GhKxmC4sHXxHGJv8e8egAZeTZ6HI4mLU6S7FUzvFOtsk7ZIDN1ksA9r9DyOgNqowA9yAtZXV0Uiap61bIO81FQ==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz", + "integrity": "sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/visitor-keys": "4.28.1", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -771,12 +776,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.1.tgz", - "integrity": "sha512-K4HMrdFqr9PFquPu178SaSb92CaWe2yErXyPumc8cYWxFmhgJsNY9eSePmO05j0JhBvf2Cdhptd6E6Yv9HVHcg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz", + "integrity": "sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.1", + "@typescript-eslint/types": "4.28.2", "eslint-visitor-keys": "^2.0.0" }, "engines": { @@ -799,17 +804,6 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -919,9 +913,9 @@ "dev": true }, "node_modules/anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", @@ -1020,8 +1014,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "node_modules/babel-runtime": { "version": "6.26.0", @@ -1059,9 +1052,9 @@ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" }, "node_modules/better-sqlite3": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-7.1.5.tgz", - "integrity": "sha512-HX5dN0zLllJLQOJP2tXqV42bvjXPnbe/Nl5o6nD1jj99h0148B39zbfGZVoJBLtDAd/CJc4Zdm8K+GhHIq84IQ==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-7.4.1.tgz", + "integrity": "sha512-sk1kW3PsWE7W7G9qbi5TQxCROlQVR8YWlp4srbyrwN5DrLeamKfrm3JExwOiNSAYyJv8cw5/2HOfvF/ipZj4qg==", "hasInstallScript": true, "dependencies": { "bindings": "^1.5.0", @@ -1312,24 +1305,24 @@ } }, "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "dependencies": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "glob-parent": "~5.1.0", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { - "fsevents": "~2.3.1" + "fsevents": "~2.3.2" } }, "node_modules/chownr": { @@ -1437,7 +1430,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1539,6 +1531,12 @@ "node": ">=0.10.0" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, "node_modules/cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -1608,7 +1606,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -1695,14 +1692,6 @@ "node": ">=4" } }, - "node_modules/dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", - "engines": { - "node": ">=8" - } - }, "node_modules/duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -2172,14 +2161,6 @@ "node": ">= 0.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", @@ -2269,9 +2250,9 @@ } }, "node_modules/express-rate-limit": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.1.3.tgz", - "integrity": "sha512-TINcxve5510pXj4n9/1AMupkj3iWxl3JuZaWhCdYDlZeoCPqweGZrxbrlqTCFb1CT5wli7s8e2SH/Qz2c9GorA==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.3.0.tgz", + "integrity": "sha512-qJhfEgCnmteSeZAeuOKQ2WEIFTX5ajrzE0xS6gCOBCoRQcU+xEzQmgYQQTpzCcqUAAzTEtu4YEih4pnLfvNtew==" }, "node_modules/express/node_modules/safe-buffer": { "version": "5.1.2", @@ -2285,9 +2266,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz", - "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -2588,9 +2569,9 @@ "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2733,11 +2714,6 @@ "he": "bin/he" } }, - "node_modules/http": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/http/-/http-0.0.0.tgz", - "integrity": "sha1-huYybSnF0Dnen6xYSkVon5KfT3I=" - }, "node_modules/http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -3005,6 +2981,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -3024,9 +3012,9 @@ "dev": true }, "node_modules/js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -3056,9 +3044,9 @@ } }, "node_modules/just-extend": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, "node_modules/klaw": { @@ -3155,15 +3143,19 @@ "dev": true }, "node_modules/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lowercase-keys": { @@ -3347,34 +3339,33 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "node_modules/mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.2.tgz", + "integrity": "sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA==", "dev": true, - "license": "MIT", "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", + "chokidar": "3.5.2", "debug": "4.3.1", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.1.23", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -3384,7 +3375,7 @@ "mocha": "bin/mocha" }, "engines": { - "node": ">= 10.12.0" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", @@ -3535,9 +3526,9 @@ } }, "node_modules/nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -3566,13 +3557,13 @@ } }, "node_modules/nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.0.tgz", + "integrity": "sha512-W5WlHu+wvo3PaKLsJJkgPup2LrsXCcm7AWwyNZkUnn5rwPkuPBi3Iwk5SQtN0mv+K65k7nKKjwNQ30wg3wLAQQ==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/fake-timers": "^7.0.4", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", "path-to-regexp": "^1.7.0" @@ -3906,26 +3897,34 @@ } }, "node_modules/pg": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", - "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz", + "integrity": "sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==", "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.4.0", - "pg-pool": "^3.2.2", - "pg-protocol": "^1.4.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.3.0", + "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, "engines": { "node": ">= 8.0.0" + }, + "peerDependencies": { + "pg-native": ">=2.0.0" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } } }, "node_modules/pg-connection-string": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", - "integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" }, "node_modules/pg-int8": { "version": "1.0.1", @@ -3936,14 +3935,17 @@ } }, "node_modules/pg-pool": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", - "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz", + "integrity": "sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==", + "peerDependencies": { + "pg": ">=8.0" + } }, "node_modules/pg-protocol": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz", - "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" }, "node_modules/pg-types": { "version": "2.2.0", @@ -4233,9 +4235,9 @@ } }, "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { "picomatch": "^2.2.1" @@ -4245,9 +4247,9 @@ } }, "node_modules/redis": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.1.tgz", - "integrity": "sha512-QhkKhOuzhogR1NDJfBD34TQJz2ZJwDhhIC6ZmvpftlmfYShHHQXjjNspAJ+Z2HH5NwSBVYBVganbiZ8bgFMHjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", "dependencies": { "denque": "^1.5.0", "redis-commands": "^1.7.0", @@ -4455,9 +4457,9 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { "randombytes": "^2.1.0" @@ -4543,27 +4545,21 @@ } }, "node_modules/sinon": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.0.tgz", - "integrity": "sha512-eSNXz1XMcGEMHw08NJXSyTHIu6qTCOiN8x9ODACmZpNQpr0aXTBXBnI4xTzQzR+TEpOmLiKowGf9flCuKIzsbw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.1.tgz", + "integrity": "sha512-ZSSmlkSyhUWbkF01Z9tEbxZLF/5tRC9eojCdFh33gtQaP7ITQVaMWQHGuFM7Cuf/KEfihuh1tTl3/ABju3AQMg==", "dev": true, "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.2.0", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^7.1.0", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" } }, "node_modules/slash": { @@ -5014,18 +5010,27 @@ } }, "node_modules/ts-mock-imports": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-mock-imports/-/ts-mock-imports-1.3.0.tgz", - "integrity": "sha512-cCrVcRYsp84eDvPict0ZZD/D7ppQ0/JSx4ve6aEU8DjlsaWRJWV6ADMovp2sCuh6pZcduLFoIYhKTDU2LARo7Q==", - "dev": true + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ts-mock-imports/-/ts-mock-imports-1.3.7.tgz", + "integrity": "sha512-zy4B3QSGaOhjaX9j0h9YKwM1oHG4Kd1KIUJBeXlXIQrFnATNLgh4+NyRcaAHsPeqwe3TWeRtHXkNXPxySEKk3w==", + "dev": true, + "peerDependencies": { + "sinon": ">= 4.1.2", + "typescript": ">=2.6.1" + } }, "node_modules/ts-node": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", - "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", + "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", "dev": true, "dependencies": { + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.1", "arg": "^4.1.0", + "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "source-map-support": "^0.5.17", @@ -5033,12 +5038,27 @@ }, "bin": { "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" }, "engines": { - "node": ">=10.0.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "@swc/core": ">=1.2.45", + "@swc/wasm": ">=1.2.45", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, "node_modules/ts-node/node_modules/diff": { @@ -5133,9 +5153,9 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "node_modules/typescript": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", - "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5276,14 +5296,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -5340,9 +5352,9 @@ } }, "node_modules/workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true }, "node_modules/wrap-ansi": { @@ -5743,9 +5755,9 @@ "dev": true }, "@nodelib/fs.walk": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", - "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", @@ -5753,37 +5765,27 @@ } }, "@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", + "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0" } }, - "@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, "@sinonjs/samsam": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.2.0.tgz", - "integrity": "sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.0.2.tgz", + "integrity": "sha512-jxPRPp9n93ci7b8hMfJOFDPRLFYadN6FSpeROFTR4UNF4i5b+EK6m4QXPO46BDhFgRy1JuS87zAnFOzCUwMJcQ==", "dev": true, "requires": { "@sinonjs/commons": "^1.6.0", @@ -5797,10 +5799,34 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz", + "integrity": "sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==", + "dev": true + }, "@types/better-sqlite3": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-5.4.0.tgz", - "integrity": "sha512-nzm7lJ7l3jBmGUbtkL8cdOMhPkN6Pw2IM+b0V7iIKba+YKiLrjkIy7vVLsBIVnd7+lgzBzrHsXZxCaFTcmw5Ow==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-5.4.3.tgz", + "integrity": "sha512-d4T8Htgz3sQL3u5oVwkWipZLBYUooKEA4fhU9Sp4F6VDIhifQo1NR/IDtnAIID0Y9IXV3TQnNhv6S+m8TnkEdg==", "dev": true, "requires": { "@types/integer": "*" @@ -5819,8 +5845,7 @@ "@types/caseless": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", - "dev": true + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" }, "@types/connect": { "version": "3.4.33", @@ -5832,30 +5857,30 @@ } }, "@types/express": { - "version": "4.17.8", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz", - "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==", + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", "devOptional": true, "requires": { "@types/body-parser": "*", - "@types/express-serve-static-core": "*", + "@types/express-serve-static-core": "^4.17.18", "@types/qs": "*", "@types/serve-static": "*" } }, "@types/express-rate-limit": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/express-rate-limit/-/express-rate-limit-5.1.0.tgz", - "integrity": "sha512-vmg7S3hUnfFmp06V01DrTB41mbQYXMV/F4aF5KKnfCIeSlnizatXaqO9UgR6LvNEEd3eMpuUTLxR6nv3d4hZ6g==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@types/express-rate-limit/-/express-rate-limit-5.1.3.tgz", + "integrity": "sha512-H+TYy3K53uPU2TqPGFYaiWc2xJV6+bIFkDd/Ma2/h67Pa6ARk9kWE0p/K9OH1Okm0et9Sfm66fmXoAxsH2PHXg==", "dev": true, "requires": { "@types/express": "*" } }, "@types/express-serve-static-core": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz", - "integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==", + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", "devOptional": true, "requires": { "@types/node": "*", @@ -5870,9 +5895,9 @@ "dev": true }, "@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", + "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", "dev": true }, "@types/mime": { @@ -5882,21 +5907,20 @@ "devOptional": true }, "@types/mocha": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", - "integrity": "sha512-Lwh0lzzqT5Pqh6z61P3c3P5nm6fzQK/MMHl9UKeneAeInVflBSz1O2EkX6gM6xfJd7FBXBY5purtLx7fUiZ7Hw==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", + "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==", "dev": true }, "@types/node": { - "version": "14.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.9.tgz", - "integrity": "sha512-iXuiZ65PL5c8VAlF426GVJGKcsnAb2rW2037LJe3G6eM6nz35bK9QAUOH3Ic3kF4ZcKLpM02sFkSzCflIpoIKA==", - "devOptional": true + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.0.tgz", + "integrity": "sha512-OydMCocGMGqw/1BnWbhtK+AtwyWTOigtrQlRe57OQmTNcI3HKlVI5FGlh+c4mSqInMPLynFrTlYjfajPu9O/eQ==" }, "@types/node-fetch": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", - "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.11.tgz", + "integrity": "sha512-2upCKaqVZETDRb8A2VTaRymqFBEgH8u6yr96b/u3+1uQEPDRo3mJLEiPk7vdXBHRtjwkjqzFYMJXrt0Z9QsYjQ==", "dev": true, "requires": { "@types/node": "*", @@ -5904,13 +5928,13 @@ } }, "@types/pg": { - "version": "7.14.10", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-7.14.10.tgz", - "integrity": "sha512-m6G0mrpj71YgVgHJF0cIHC3OZTKiQSUzTkMj869a+YWXF2tdbmO2PmIpNnDkiFPhHWcoGq2bk5P2e0CZX0F9Mg==", + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", "dev": true, "requires": { "@types/node": "*", - "pg-protocol": "^1.2.0", + "pg-protocol": "*", "pg-types": "^2.2.0" } }, @@ -5927,19 +5951,18 @@ "devOptional": true }, "@types/redis": { - "version": "2.8.28", - "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.28.tgz", - "integrity": "sha512-8l2gr2OQ969ypa7hFOeKqtFoY70XkHxISV0pAwmQ2nm6CSPb1brmTmqJCGGrekCo+pAZyWlNXr+Kvo6L/1wijA==", + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.31.tgz", + "integrity": "sha512-daWrrTDYaa5iSDFbgzZ9gOOzyp2AJmYK59OlG/2KGBgYWF3lfs8GDKm1c//tik5Uc93hDD36O+qLPvzDolChbA==", "dev": true, "requires": { "@types/node": "*" } }, "@types/request": { - "version": "2.48.5", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz", - "integrity": "sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==", - "dev": true, + "version": "2.48.6", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.6.tgz", + "integrity": "sha512-vrZaV3Ij7j/l/3hz6OttZFtpRCu7zlq7XgkYHJP6FwVEAZkGQ095WqyJV08/GlW9eyXKVcp/xmtruHm8eHpw1g==", "requires": { "@types/caseless": "*", "@types/node": "*", @@ -5951,7 +5974,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -5971,19 +5993,18 @@ } }, "@types/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz", + "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==" }, "@typescript-eslint/eslint-plugin": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.1.tgz", - "integrity": "sha512-9yfcNpDaNGQ6/LQOX/KhUFTR1sCKH+PBr234k6hI9XJ0VP5UqGxap0AnNwBnWFk1MNyWBylJH9ZkzBXC+5akZQ==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz", + "integrity": "sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.28.1", - "@typescript-eslint/scope-manager": "4.28.1", + "@typescript-eslint/experimental-utils": "4.28.2", + "@typescript-eslint/scope-manager": "4.28.2", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.1.0", @@ -6027,28 +6048,28 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.1.tgz", - "integrity": "sha512-n8/ggadrZ+uyrfrSEchx3jgODdmcx7MzVM2sI3cTpI/YlfSm0+9HEUaWw3aQn2urL2KYlWYMDgn45iLfjDYB+Q==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz", + "integrity": "sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.28.1", - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/typescript-estree": "4.28.1", + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, "@typescript-eslint/parser": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.1.tgz", - "integrity": "sha512-UjrMsgnhQIIK82hXGaD+MCN8IfORS1CbMdu7VlZbYa8LCZtbZjJA26De4IPQB7XYZbL8gJ99KWNj0l6WD0guJg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.2.tgz", + "integrity": "sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.28.1", - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/typescript-estree": "4.28.1", + "@typescript-eslint/scope-manager": "4.28.2", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/typescript-estree": "4.28.2", "debug": "^4.3.1" }, "dependencies": { @@ -6070,29 +6091,29 @@ } }, "@typescript-eslint/scope-manager": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.1.tgz", - "integrity": "sha512-o95bvGKfss6705x7jFGDyS7trAORTy57lwJ+VsYwil/lOUxKQ9tA7Suuq+ciMhJc/1qPwB3XE2DKh9wubW8YYA==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz", + "integrity": "sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/visitor-keys": "4.28.1" + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2" } }, "@typescript-eslint/types": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.1.tgz", - "integrity": "sha512-4z+knEihcyX7blAGi7O3Fm3O6YRCP+r56NJFMNGsmtdw+NCdpG5SgNz427LS9nQkRVTswZLhz484hakQwB8RRg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.2.tgz", + "integrity": "sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.1.tgz", - "integrity": "sha512-GhKxmC4sHXxHGJv8e8egAZeTZ6HI4mLU6S7FUzvFOtsk7ZIDN1ksA9r9DyOgNqowA9yAtZXV0Uiap61bIO81FQ==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz", + "integrity": "sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.1", - "@typescript-eslint/visitor-keys": "4.28.1", + "@typescript-eslint/types": "4.28.2", + "@typescript-eslint/visitor-keys": "4.28.2", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -6136,12 +6157,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.1.tgz", - "integrity": "sha512-K4HMrdFqr9PFquPu178SaSb92CaWe2yErXyPumc8cYWxFmhgJsNY9eSePmO05j0JhBvf2Cdhptd6E6Yv9HVHcg==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz", + "integrity": "sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.1", + "@typescript-eslint/types": "4.28.2", "eslint-visitor-keys": "^2.0.0" } }, @@ -6157,14 +6178,6 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -6246,9 +6259,9 @@ } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -6340,8 +6353,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "babel-runtime": { "version": "6.26.0", @@ -6381,9 +6393,9 @@ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" }, "better-sqlite3": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-7.1.5.tgz", - "integrity": "sha512-HX5dN0zLllJLQOJP2tXqV42bvjXPnbe/Nl5o6nD1jj99h0148B39zbfGZVoJBLtDAd/CJc4Zdm8K+GhHIq84IQ==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-7.4.1.tgz", + "integrity": "sha512-sk1kW3PsWE7W7G9qbi5TQxCROlQVR8YWlp4srbyrwN5DrLeamKfrm3JExwOiNSAYyJv8cw5/2HOfvF/ipZj4qg==", "requires": { "bindings": "^1.5.0", "prebuild-install": "^6.0.1", @@ -6572,19 +6584,19 @@ } }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" } }, "chownr": { @@ -6673,7 +6685,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -6759,6 +6770,12 @@ "capture-stack-trace": "^1.0.0" } }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -6812,8 +6829,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "delegates": { "version": "1.0.0", @@ -6873,11 +6889,6 @@ "is-obj": "^1.0.0" } }, - "dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" - }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -7222,11 +7233,6 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, "execa": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", @@ -7302,9 +7308,9 @@ } }, "express-rate-limit": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.1.3.tgz", - "integrity": "sha512-TINcxve5510pXj4n9/1AMupkj3iWxl3JuZaWhCdYDlZeoCPqweGZrxbrlqTCFb1CT5wli7s8e2SH/Qz2c9GorA==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.3.0.tgz", + "integrity": "sha512-qJhfEgCnmteSeZAeuOKQ2WEIFTX5ajrzE0xS6gCOBCoRQcU+xEzQmgYQQTpzCcqUAAzTEtu4YEih4pnLfvNtew==" }, "fast-deep-equal": { "version": "3.1.3", @@ -7313,9 +7319,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.6.tgz", - "integrity": "sha512-GnLuqj/pvQ7pX8/L4J84nijv6sAnlwvSDpMkJi9i7nPmPxGtRPkBSStfvDW5l6nMdX9VWe+pkKWFTgD+vF2QSQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -7556,9 +7562,9 @@ "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7664,11 +7670,6 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "http": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/http/-/http-0.0.0.tgz", - "integrity": "sha1-huYybSnF0Dnen6xYSkVon5KfT3I=" - }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -7856,6 +7857,12 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -7875,9 +7882,9 @@ "dev": true }, "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" @@ -7904,9 +7911,9 @@ } }, "just-extend": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, "klaw": { @@ -7988,12 +7995,13 @@ "dev": true }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "lowercase-keys": { @@ -8128,33 +8136,33 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.0.2.tgz", + "integrity": "sha512-FpspiWU+UT9Sixx/wKimvnpkeW0mh6ROAKkIaPokj3xZgxeRhcna/k5X57jJghEr8X+Cgu/Vegf8zCX5ugSuTA==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", + "chokidar": "3.5.2", "debug": "4.3.1", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.1.23", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -8272,9 +8280,9 @@ } }, "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", "dev": true }, "napi-build-utils": { @@ -8294,13 +8302,13 @@ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, "nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.0.tgz", + "integrity": "sha512-W5WlHu+wvo3PaKLsJJkgPup2LrsXCcm7AWwyNZkUnn5rwPkuPBi3Iwk5SQtN0mv+K65k7nKKjwNQ30wg3wLAQQ==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/fake-timers": "^7.0.4", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", "path-to-regexp": "^1.7.0" @@ -8563,23 +8571,23 @@ "dev": true }, "pg": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", - "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz", + "integrity": "sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==", "requires": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.4.0", - "pg-pool": "^3.2.2", - "pg-protocol": "^1.4.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.3.0", + "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" } }, "pg-connection-string": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", - "integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" }, "pg-int8": { "version": "1.0.1", @@ -8587,14 +8595,15 @@ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" }, "pg-pool": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", - "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz", + "integrity": "sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==", + "requires": {} }, "pg-protocol": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz", - "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" }, "pg-types": { "version": "2.2.0", @@ -8808,18 +8817,18 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" } }, "redis": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.1.tgz", - "integrity": "sha512-QhkKhOuzhogR1NDJfBD34TQJz2ZJwDhhIC6ZmvpftlmfYShHHQXjjNspAJ+Z2HH5NwSBVYBVganbiZ8bgFMHjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", "requires": { "denque": "^1.5.0", "redis-commands": "^1.7.0", @@ -8968,9 +8977,9 @@ } }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -9033,26 +9042,17 @@ } }, "sinon": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.0.tgz", - "integrity": "sha512-eSNXz1XMcGEMHw08NJXSyTHIu6qTCOiN8x9ODACmZpNQpr0aXTBXBnI4xTzQzR+TEpOmLiKowGf9flCuKIzsbw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.1.tgz", + "integrity": "sha512-ZSSmlkSyhUWbkF01Z9tEbxZLF/5tRC9eojCdFh33gtQaP7ITQVaMWQHGuFM7Cuf/KEfihuh1tTl3/ABju3AQMg==", "dev": true, "requires": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.2.0", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "dependencies": { - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - } + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^7.1.0", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" } }, "slash": { @@ -9424,18 +9424,24 @@ } }, "ts-mock-imports": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-mock-imports/-/ts-mock-imports-1.3.0.tgz", - "integrity": "sha512-cCrVcRYsp84eDvPict0ZZD/D7ppQ0/JSx4ve6aEU8DjlsaWRJWV6ADMovp2sCuh6pZcduLFoIYhKTDU2LARo7Q==", - "dev": true + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ts-mock-imports/-/ts-mock-imports-1.3.7.tgz", + "integrity": "sha512-zy4B3QSGaOhjaX9j0h9YKwM1oHG4Kd1KIUJBeXlXIQrFnATNLgh4+NyRcaAHsPeqwe3TWeRtHXkNXPxySEKk3w==", + "dev": true, + "requires": {} }, "ts-node": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", - "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", + "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", "dev": true, "requires": { + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.1", "arg": "^4.1.0", + "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "source-map-support": "^0.5.17", @@ -9509,9 +9515,9 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typescript": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", - "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true }, "undefsafe": { @@ -9620,11 +9626,6 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -9669,9 +9670,9 @@ "dev": true }, "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true }, "wrap-ansi": { diff --git a/package.json b/package.json index fd9280b..56386f6 100644 --- a/package.json +++ b/package.json @@ -16,37 +16,33 @@ "license": "MIT", "dependencies": { "@ajayyy/lru-diskcache": "^1.1.9", - "abort-controller": "^3.0.0", - "better-sqlite3": "^7.1.5", - "dotenv": "^8.2.0", + "@types/request": "^2.48.6", + "better-sqlite3": "^7.4.1", "express": "^4.17.1", "express-promise-router": "^4.1.0", - "express-rate-limit": "^5.1.3", - "http": "0.0.0", - "node-fetch": "^2.6.0", - "pg": "^8.5.1", - "redis": "^3.1.1", - "sync-mysql": "^3.0.1", - "uuid": "^3.3.2" + "express-rate-limit": "^5.3.0", + "node-fetch": "^2.6.1", + "pg": "^8.6.0", + "redis": "^3.1.2", + "sync-mysql": "^3.0.1" }, "devDependencies": { - "@types/better-sqlite3": "^5.4.0", - "@types/express": "^4.17.8", - "@types/express-rate-limit": "^5.1.0", - "@types/mocha": "^8.2.2", - "@types/node": "^14.11.9", - "@types/node-fetch": "^2.5.7", - "@types/pg": "^7.14.10", - "@types/redis": "^2.8.28", - "@types/request": "^2.48.5", - "@typescript-eslint/eslint-plugin": "^4.28.1", - "@typescript-eslint/parser": "^4.28.1", + "@types/better-sqlite3": "^5.4.3", + "@types/express": "^4.17.13", + "@types/express-rate-limit": "^5.1.3", + "@types/mocha": "^8.2.3", + "@types/node": "^16.3.0", + "@types/node-fetch": "^2.5.11", + "@types/pg": "^8.6.1", + "@types/redis": "^2.8.31", + "@typescript-eslint/eslint-plugin": "^4.28.2", + "@typescript-eslint/parser": "^4.28.2", "eslint": "^7.30.0", - "mocha": "^8.4.0", + "mocha": "^9.0.2", "nodemon": "^2.0.2", - "sinon": "^9.2.0", - "ts-mock-imports": "^1.3.0", - "ts-node": "^9.0.0", - "typescript": "^4.0.3" + "sinon": "^11.1.1", + "ts-mock-imports": "^1.3.7", + "ts-node": "^10.0.0", + "typescript": "^4.3.5" } } From e8d0da3ce3cbf484e6948ac4c80fc05d589db16d Mon Sep 17 00:00:00 2001 From: Michael C Date: Sat, 10 Jul 2021 16:30:30 -0400 Subject: [PATCH 10/24] add 400 conditions --- src/routes/postWarning.ts | 2 ++ test/cases/getLockCategoriesByHash.ts | 2 +- test/cases/getSkipSegments.ts | 1 + test/cases/getSkipSegmentsByHash.ts | 4 ++-- test/cases/getUserID.ts | 10 ++++++++++ test/cases/postPurgeAllSegments.ts | 15 +++++++++++++++ test/cases/postWarning.ts | 16 ++++++++++++++++ 7 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/routes/postWarning.ts b/src/routes/postWarning.ts index 015a9f8..583fbe2 100644 --- a/src/routes/postWarning.ts +++ b/src/routes/postWarning.ts @@ -6,6 +6,8 @@ import {getHash} from '../utils/getHash'; import { HashedUserID, UserID } from '../types/user.model'; export async function postWarning(req: Request, res: Response): Promise { + // exit early if no body passed in + if (!req.body.userID && !req.body.issuerUserID) return res.status(400).json({"message": "Missing parameters"}); // Collect user input data const issuerUserID: HashedUserID = getHash( req.body.issuerUserID); const userID: UserID = req.body.userID; diff --git a/test/cases/getLockCategoriesByHash.ts b/test/cases/getLockCategoriesByHash.ts index d31f7cf..0701210 100644 --- a/test/cases/getLockCategoriesByHash.ts +++ b/test/cases/getLockCategoriesByHash.ts @@ -2,7 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {getHash} from '../../src/utils/getHash'; import {db} from '../../src/databases/databases'; - +import assert from 'assert'; describe('getLockCategoriesByHash', () => { before(async () => { diff --git a/test/cases/getSkipSegments.ts b/test/cases/getSkipSegments.ts index 979d33b..57ec9d7 100644 --- a/test/cases/getSkipSegments.ts +++ b/test/cases/getSkipSegments.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {db} from '../../src/databases/databases'; import {Done, getbaseURL} from '../utils'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('getSkipSegments', () => { before(async () => { diff --git a/test/cases/getSkipSegmentsByHash.ts b/test/cases/getSkipSegmentsByHash.ts index d1da36e..d37eabb 100644 --- a/test/cases/getSkipSegmentsByHash.ts +++ b/test/cases/getSkipSegmentsByHash.ts @@ -108,10 +108,10 @@ describe('getSegmentsByHash', () => { .catch(() => done("Couldn't call endpoint")); }); - it('Should return 404 for no hash', (done: Done) => { + it('Should return 400 for no hash', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/?categories=["shilling"]') .then(res => { - if (res.status !== 404) done("expected 404, got " + res.status); + if (res.status !== 400) done("expected 400, got " + res.status); else done(); // pass }) .catch(() => done("Couldn't call endpoint")); diff --git a/test/cases/getUserID.ts b/test/cases/getUserID.ts index e0c7c5a..528804f 100644 --- a/test/cases/getUserID.ts +++ b/test/cases/getUserID.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('getUserID', () => { before(async () => { @@ -398,4 +399,13 @@ describe('getUserID', () => { }) .catch(() => ("couldn't call endpoint")); }); + + it('should return 400 if no username parameter specified', (done: Done) => { + fetch(getbaseURL() + '/api/userID') + .then(res => { + assert.strictEqual(res.status, 400); + done(); + }) + .catch(() => ("couldn't call endpoint")); + }); }); diff --git a/test/cases/postPurgeAllSegments.ts b/test/cases/postPurgeAllSegments.ts index a907ddc..0fd337a 100644 --- a/test/cases/postPurgeAllSegments.ts +++ b/test/cases/postPurgeAllSegments.ts @@ -3,6 +3,7 @@ import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; import {IDatabase} from '../../src/databases/IDatabase'; +import assert from 'assert'; async function dbSponsorTimesAdd(db: IDatabase, videoID: string, startTime: number, endTime: number, UUID: string, category: string) { const votes = 0, @@ -79,4 +80,18 @@ describe('postPurgeAllSegments', function () { }) .catch(err => done(err)); }); + + it('Should return 400 if missing body', function (done: Done) { + fetch(`${baseURL}${route}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + } + }) + .then(async res => { + assert.strictEqual(res.status, 400); + done(); + }) + .catch(err => done(err)); + }); }); diff --git a/test/cases/postWarning.ts b/test/cases/postWarning.ts index 8231148..f352165 100644 --- a/test/cases/postWarning.ts +++ b/test/cases/postWarning.ts @@ -2,6 +2,7 @@ import fetch from 'node-fetch'; import {Done, getbaseURL} from '../utils'; import {db} from '../../src/databases/databases'; import {getHash} from '../../src/utils/getHash'; +import assert from 'assert'; describe('postWarning', () => { before(async () => { @@ -127,4 +128,19 @@ describe('postWarning', () => { }) .catch(err => done(err)); }); + + it('Should return 400 if missing body', (done: Done) => { + fetch(getbaseURL() + + "/api/warnUser", { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + } + }) + .then(async res => { + assert.strictEqual(res.status, 400); + done(); + }) + .catch(err => done(err)); + }); }); From 6b5156468ca1ca60f97396f2e79a5cfbd9ebc9c4 Mon Sep 17 00:00:00 2001 From: Haidang666 Date: Fri, 9 Jul 2021 11:46:04 +0700 Subject: [PATCH 11/24] Add archive downvote segment cron --- DatabaseSchema.md | 23 +++++++++ databases/_upgrade_sponsorTimes_21.sql | 26 ++++++++++ package.json | 2 + src/config.ts | 3 +- src/cronjob/downvoteSegmentArchiveJob.ts | 63 ++++++++++++++++++++++++ src/cronjob/index.ts | 13 +++++ src/index.ts | 6 ++- src/types/config.model.ts | 15 ++++++ 8 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 databases/_upgrade_sponsorTimes_21.sql create mode 100644 src/cronjob/downvoteSegmentArchiveJob.ts create mode 100644 src/cronjob/index.ts diff --git a/DatabaseSchema.md b/DatabaseSchema.md index 485c4c3..26f2319 100644 --- a/DatabaseSchema.md +++ b/DatabaseSchema.md @@ -10,6 +10,7 @@ [shadowBannedUsers](#shadowBannedUsers) [unlistedVideos](#unlistedVideos) [config](#config) +[archivedSponsorTimes](#archivedSponsorTimes) ### vipUsers | Name | Type | | @@ -35,6 +36,7 @@ | timeSubmitted | INTEGER | not null | | views | INTEGER | not null | | category | TEXT | not null, default 'sponsor' | +| actionType | TEXT | not null, default 'skip' | | service | TEXT | not null, default 'Youtube' | | videoDuration | INTEGER | not null, default '0' | | hidden | INTEGER | not null, default '0' | @@ -140,7 +142,28 @@ | key | TEXT | not null, unique | | value | TEXT | not null | +### archivedSponsorTimes +| Name | Type | | +| -- | :--: | -- | +| videoID | TEXT | not null | +| startTime | REAL | not null | +| endTime | REAL | not null | +| votes | INTEGER | not null | +| locked | INTEGER | not null, default '0' | +| incorrectVotes | INTEGER | not null, default 1 | +| UUID | TEXT | not null, unique | +| userID | TEXT | not null | +| timeSubmitted | INTEGER | not null | +| views | INTEGER | not null | +| category | TEXT | not null, default 'sponsor' | +| actionType | TEXT | not null, default 'skip' | +| service | TEXT | not null, default 'Youtube' | +| videoDuration | INTEGER | not null, default '0' | +| hidden | INTEGER | not null, default '0' | +| reputation | REAL | not null, default '0' | +| shadowHidden | INTEGER | not null | +| hashedVideoID | TEXT | not null, default '', sha256 | # Private diff --git a/databases/_upgrade_sponsorTimes_21.sql b/databases/_upgrade_sponsorTimes_21.sql new file mode 100644 index 0000000..4e850bd --- /dev/null +++ b/databases/_upgrade_sponsorTimes_21.sql @@ -0,0 +1,26 @@ +BEGIN TRANSACTION; + +CREATE TABLE IF NOT EXISTS "archivedSponsorTimes" ( + "videoID" TEXT NOT NULL, + "startTime" REAL NOT NULL, + "endTime" REAL NOT NULL, + "votes" INTEGER NOT NULL, + "locked" INTEGER NOT NULL DEFAULT '0', + "incorrectVotes" INTEGER NOT NULL DEFAULT 1, + "UUID" TEXT NOT NULL UNIQUE, + "userID" TEXT NOT NULL, + "timeSubmitted" INTEGER NOT NULL, + "views" INTEGER NOT NULL, + "category" TEXT NOT NULL DEFAULT 'sponsor', + "service" TEXT NOT NULL DEFAULT 'Youtube', + "actionType" TEXT NOT NULL DEFAULT 'skip', + "videoDuration" INTEGER NOT NULL DEFAULT '0', + "hidden" INTEGER NOT NULL DEFAULT '0', + "reputation" REAL NOT NULL DEFAULT '0', + "shadowHidden" INTEGER NOT NULL, + "hashedVideoID" TEXT NOT NULL DEFAULT '' +); + +UPDATE "config" SET value = 21 WHERE key = 'version'; + +COMMIT; diff --git a/package.json b/package.json index 56386f6..fcba30c 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@ajayyy/lru-diskcache": "^1.1.9", "@types/request": "^2.48.6", "better-sqlite3": "^7.4.1", + "cron": "^1.8.2", "express": "^4.17.1", "express-promise-router": "^4.1.0", "express-rate-limit": "^5.3.0", @@ -28,6 +29,7 @@ }, "devDependencies": { "@types/better-sqlite3": "^5.4.3", + "@types/cron": "^1.7.3", "@types/express": "^4.17.13", "@types/express-rate-limit": "^5.1.3", "@types/mocha": "^8.2.3", diff --git a/src/config.ts b/src/config.ts index 1e900b9..9002df7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -77,7 +77,8 @@ addDefaults(config, { name: "vipUsers" }] }, - diskCache: null + diskCache: null, + crons: null }); // Add defaults diff --git a/src/cronjob/downvoteSegmentArchiveJob.ts b/src/cronjob/downvoteSegmentArchiveJob.ts new file mode 100644 index 0000000..c2f8f4e --- /dev/null +++ b/src/cronjob/downvoteSegmentArchiveJob.ts @@ -0,0 +1,63 @@ +import { CronJob } from "cron"; + +import { config as serverConfig } from "../config"; +import { Logger } from "../utils/logger"; +import { db } from "../databases/databases"; +import { DBSegment } from "../types/segments.model"; + +const jobConfig = serverConfig?.crons?.downvoteSegmentArchive; + +export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number, runTime?: number): Promise => { + const timeNow = runTime || new Date().getTime(); + const threshold = dayLimit * 86400000; + + Logger.info(`DownvoteSegmentArchiveJob starts at ${timeNow}`); + try { + // insert into archive sponsorTime + await db.prepare( + 'run', + `INSERT INTO "archivedSponsorTimes" + SELECT * + FROM "sponsorTimes" + WHERE votes < ? AND (? - timeSubmitted) > ?`, + [ + voteLimit, + timeNow, + threshold + ] + ) as DBSegment[]; + + } catch (err) { + Logger.error('Execption when insert segment in archivedSponsorTimes'); + Logger.error(err); + return 1; + } + + // remove from sponsorTime + try { + await db.prepare( + 'run', + 'DELETE FROM "sponsorTimes" WHERE votes < ? AND (? - timeSubmitted) > ?', + [ + voteLimit, + timeNow, + threshold + ] + ) as DBSegment[]; + + } catch (err) { + Logger.error('Execption when deleting segment in sponsorTimes'); + Logger.error(err); + return 1; + } + + Logger.info('DownvoteSegmentArchiveJob finished'); + return 0; +}; + +const DownvoteSegmentArchiveJob = new CronJob( + jobConfig?.schedule || new Date(1), + () => archiveDownvoteSegment(jobConfig?.timeThresholdInDays, jobConfig?.voteThreshold) +); + +export default DownvoteSegmentArchiveJob; diff --git a/src/cronjob/index.ts b/src/cronjob/index.ts new file mode 100644 index 0000000..46aa80c --- /dev/null +++ b/src/cronjob/index.ts @@ -0,0 +1,13 @@ +import { Logger } from "../utils/logger"; +import { config } from "../config"; +import DownvoteSegmentArchiveJob from "./downvoteSegmentArchiveJob"; + +export function startAllCrons (): void { + if (config?.crons?.enabled) { + Logger.info("Crons started"); + + DownvoteSegmentArchiveJob.start(); + } else { + Logger.info("Crons dissabled"); + } +} diff --git a/src/index.ts b/src/index.ts index 13576a7..babb1a9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,13 +2,17 @@ import {config} from "./config"; import {initDb} from './databases/databases'; import {createServer} from "./app"; import {Logger} from "./utils/logger"; +import {startAllCrons} from "./cronjob"; async function init() { await initDb(); createServer(() => { Logger.info("Server started on port " + config.port + "."); + + // ignite cron job after server created + startAllCrons(); }); } - + init(); \ No newline at end of file diff --git a/src/types/config.model.ts b/src/types/config.model.ts index 1dabdbe..cb5daa2 100644 --- a/src/types/config.model.ts +++ b/src/types/config.model.ts @@ -44,6 +44,7 @@ export interface SBSConfig { postgres?: PoolConfig; dumpDatabase?: DumpDatabase; diskCache: CacheOptions; + crons: CronJobOptions; } export interface WebhookConfig { @@ -81,3 +82,17 @@ export interface DumpDatabaseTable { name: string; order?: string; } + +export interface CronJobDefault { + schedule: string; +} + +export interface CronJobOptions { + enabled: boolean; + downvoteSegmentArchive: CronJobDefault & DownvoteSegmentArchiveCron; +} + +export interface DownvoteSegmentArchiveCron { + voteThreshold: number; + timeThresholdInDays: number; +} \ No newline at end of file From bbb1db014cb023af1ad7e208adeb7d172cc5089c Mon Sep 17 00:00:00 2001 From: Haidang666 Date: Fri, 9 Jul 2021 11:46:38 +0700 Subject: [PATCH 12/24] Add archive downvote function unit test --- test/cases/downvoteSegmentArchiveJob.ts | 167 ++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 test/cases/downvoteSegmentArchiveJob.ts diff --git a/test/cases/downvoteSegmentArchiveJob.ts b/test/cases/downvoteSegmentArchiveJob.ts new file mode 100644 index 0000000..c750526 --- /dev/null +++ b/test/cases/downvoteSegmentArchiveJob.ts @@ -0,0 +1,167 @@ +import assert from 'assert'; + +import { db } from '../../src/databases/databases'; +import { getHash } from '../../src/utils/getHash'; +import { archiveDownvoteSegment } from '../../src/cronjob/downvoteSegmentArchiveJob'; +import { DBSegment } from '../../src/types/segments.model'; + +const records = [ + ['testtesttest', 1, 11, 2, 0, '1-uuid-0', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 100, 0, 0, getHash('testtesttest', 1)], + ['testtesttest2', 1, 11, 2, 0, '1-uuid-0-1', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 120, 0, 0, getHash('testtesttest2', 1)], + ['testtesttest', 12, 14, 2, 0, '1-uuid-0-2', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'mute', 'ytb', 100, 0, 0, getHash('testtesttest', 1)], + ['testtesttest', 20, 33, 2, 0, '1-uuid-2', 'testman', new Date('December 17, 2021').getTime(), 50, 'intro', 'skip', 'ytb', 101, 0, 0, getHash('testtesttest', 1)], + ['testtesttest,test', 1, 11, 2, 0, '1-uuid-1', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 140, 0, 0, getHash('testtesttest,test', 1)], + + ['test3', 1, 11, 2, 0, '1-uuid-4', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 200, 0, 0, getHash('test3', 1)], + ['test3', 7, 22, -3, 0, '1-uuid-5', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 300, 0, 0, getHash('test3', 1)], + + ['multiple', 1, 11, 2, 0, '1-uuid-6', 'testman', new Date('December 17, 2021').getTime(), 50, 'intro', 'skip', 'ytb', 400, 0, 0, getHash('multiple', 1)], + ['multiple', 20, 33, -4, 0, '1-uuid-7', 'testman', new Date('October 1, 2021').getTime(), 50, 'intro', 'skip', 'ytb', 500, 0, 0, getHash('multiple', 1)], + + ['locked', 20, 33, 2, 1, '1-uuid-locked-8', 'testman', new Date('December 17, 2021').getTime(), 50, 'intro', 'skip', 'ytb', 230, 0, 0, getHash('locked', 1)], + ['locked', 20, 34, 100000, 0, '1-uuid-9', 'testman', new Date('December 17, 2021').getTime(), 50, 'intro', 'skip', 'ytb', 190, 0, 0, getHash('locked', 1)], + + ['onlyHiddenSegments', 20, 34, 100000, 0, 'onlyHiddenSegments', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 190, 1, 0, getHash('onlyHiddenSegments', 1)], + + ['requiredSegmentVid-raw', 60, 70, 2, 0, 'requiredSegmentVid-raw-1', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)], + ['requiredSegmentVid-raw', 60, 70, -1, 0, 'requiredSegmentVid-raw-2', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)], + ['requiredSegmentVid-raw', 80, 90, -2, 0, 'requiredSegmentVid-raw-3', 'testman', new Date('November 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)], + ['requiredSegmentVid-raw', 80, 90, 2, 0, 'requiredSegmentVid-raw-4', 'testman', new Date('December 17, 2021').getTime(), 50, 'sponsor', 'skip', 'ytb', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)] +]; + +describe('downvoteSegmentArchiveJob', () => { + beforeEach(async () => { + const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", views, category, "actionType", "service", "videoDuration", "hidden", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + + for (let i = 0; i < records.length; i += 1) { + await db.prepare('run', query, records[i]); + } + + return; + }); + + afterEach(async () => { + await db.prepare('run', 'DELETE FROM "sponsorTimes"'); + await db.prepare('run', 'DELETE FROM "archivedSponsorTimes"'); + }); + + const getArchivedSegment = (): Promise => { + return db.prepare('all', 'SELECT * FROM "archivedSponsorTimes"'); + }; + + const getSegmentsInMainTable = (dayLimit: number, voteLimit: number, now: number): Promise => { + return db.prepare( + 'all', + 'SELECT * FROM "sponsorTimes" WHERE votes < ? AND (? - timeSubmitted) > ?', + [ + voteLimit, + now, + dayLimit * 86400000, + ] + ); + }; + + const countSegmentInMainTable = (): Promise => { + return db.prepare( + 'get', + 'SELECT COUNT(*) as count FROM "sponsorTimes"' + ).then(res => res.count); + }; + + it('Should archive all records match', async () => { + const dayLimit = 20; + const voteLimit = 0; + const time = new Date('December 17, 2022').getTime(); + const res = await archiveDownvoteSegment(dayLimit, voteLimit, time); + assert.strictEqual(res, 0, 'Expection in archiveDownvoteSegment'); + + // check segments in archived table + const archivedSegment = await getArchivedSegment(); + assert.strictEqual(archivedSegment.length, 4, `Incorrect segment in archiveTable: ${archivedSegment.length} instead of 4`); + + // check segments not in main table + const segments = await getSegmentsInMainTable(dayLimit, voteLimit, time); + assert.strictEqual(segments.length, 0, `Incorrect segment in main table: ${segments.length} instead of 0`); + + // check number segments remain in main table + assert.strictEqual(await countSegmentInMainTable(), records.length - archivedSegment.length ,'Incorrect segment remain in main table'); + }); + + it('Should archive records with vote < -1 match', async () => { + const dayLimit = 20; + const voteLimit = -1; + const time = new Date('December 17, 2022').getTime(); + const res = await archiveDownvoteSegment(dayLimit, voteLimit, time); + assert.strictEqual(res, 0, ''); + + // check segments in archived table + const archivedSegment = await getArchivedSegment(); + assert.strictEqual(archivedSegment.length, 3, `Incorrect segment in archiveTable: ${archivedSegment.length} instead of 3`); + + // check segments not in main table + const segments = await getSegmentsInMainTable(dayLimit, voteLimit, time); + assert.strictEqual(segments.length, 0, `Incorrect segment in main table: ${segments.length} instead of 0`); + + // check number segments remain in main table + assert.strictEqual(await countSegmentInMainTable(), records.length - archivedSegment.length ,'Incorrect segment remain in main table'); + }); + + it('Should archive records with vote < -2 and day < 30 match', async () => { + const dayLimit = 30; + const voteLimit = -2; + const time = new Date('December 17, 2021').getTime(); + const res = await archiveDownvoteSegment(dayLimit, voteLimit, time); + assert.strictEqual(res, 0, ''); + + // check segments in archived table + const archivedSegment = await getArchivedSegment(); + assert.strictEqual(archivedSegment.length, 1, `Incorrect segment in archiveTable: ${archivedSegment.length} instead of 1`); + + assert.strictEqual(archivedSegment[0].votes, -4, `Incorrect segment vote in archiveTable: ${archivedSegment[0].votes} instead of -4`); + + // check segments not in main table + const segments = await getSegmentsInMainTable(dayLimit, voteLimit, time); + assert.strictEqual(segments.length, 0, `Incorrect segment in main table: ${segments.length} instead of 0`); + + // check number segments remain in main table + assert.strictEqual(await countSegmentInMainTable(), records.length - archivedSegment.length ,'Incorrect segment remain in main table'); + }); + + it('Should archive records with vote < -2 and day < 300 match', async () => { + const dayLimit = 300; + const voteLimit = -2; + const time = new Date('December 17, 2022').getTime(); + const res = await archiveDownvoteSegment(dayLimit, voteLimit, time); + assert.strictEqual(res, 0, ''); + + // check segments in archived table + const archivedSegment = await getArchivedSegment(); + assert.strictEqual(archivedSegment.length, 2, `Incorrect segment in archiveTable: ${archivedSegment.length} instead of 2`); + + // check segments not in main table + const segments = await getSegmentsInMainTable(dayLimit, voteLimit, time); + assert.strictEqual(segments.length, 0, `Incorrect segment in main table: ${segments.length} instead of 0`); + + // check number segments remain in main table + assert.strictEqual(await countSegmentInMainTable(), records.length - archivedSegment.length ,'Incorrect segment remain in main table'); + }); + + it('Should not archive any', async () => { + const dayLimit = 300; + const voteLimit = -2; + const time = new Date('December 17, 2021').getTime(); + const res = await archiveDownvoteSegment(dayLimit, voteLimit, time); + assert.strictEqual(res, 0, ''); + + // check segments in archived table + const archivedSegment = await getArchivedSegment(); + assert.strictEqual(archivedSegment.length, 0, `Incorrect segment in archiveTable: ${archivedSegment.length} instead of 0`); + + // check segments not in main table + const segments = await getSegmentsInMainTable(dayLimit, voteLimit, time); + assert.strictEqual(segments.length, 0, `Incorrect segment in main table: ${segments.length} instead of 0`); + + // check number segments remain in main table + assert.strictEqual(await countSegmentInMainTable(), records.length - archivedSegment.length ,'Incorrect segment remain in main table'); + }); +}); From d9a66a58949e001ae66405cb4b861dfb68e26c7a Mon Sep 17 00:00:00 2001 From: Michael C Date: Sat, 10 Jul 2021 00:26:18 -0400 Subject: [PATCH 13/24] quote & check for db version --- src/cronjob/downvoteSegmentArchiveJob.ts | 4 ++-- test/cases/downvoteSegmentArchiveJob.ts | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cronjob/downvoteSegmentArchiveJob.ts b/src/cronjob/downvoteSegmentArchiveJob.ts index c2f8f4e..f5e8e03 100644 --- a/src/cronjob/downvoteSegmentArchiveJob.ts +++ b/src/cronjob/downvoteSegmentArchiveJob.ts @@ -19,7 +19,7 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number `INSERT INTO "archivedSponsorTimes" SELECT * FROM "sponsorTimes" - WHERE votes < ? AND (? - timeSubmitted) > ?`, + WHERE "votes" < ? AND (? - "timeSubmitted") > ?`, [ voteLimit, timeNow, @@ -37,7 +37,7 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number try { await db.prepare( 'run', - 'DELETE FROM "sponsorTimes" WHERE votes < ? AND (? - timeSubmitted) > ?', + 'DELETE FROM "sponsorTimes" WHERE "votes" < ? AND (? - "timeSubmitted") > ?', [ voteLimit, timeNow, diff --git a/test/cases/downvoteSegmentArchiveJob.ts b/test/cases/downvoteSegmentArchiveJob.ts index c750526..6700272 100644 --- a/test/cases/downvoteSegmentArchiveJob.ts +++ b/test/cases/downvoteSegmentArchiveJob.ts @@ -40,6 +40,11 @@ describe('downvoteSegmentArchiveJob', () => { return; }); + it('Should update the database version when starting the application', async () => { + const version = (await db.prepare('get', 'SELECT key, value FROM config where key = ?', ['version'])).value; + assert.ok(version >= 21, "version should be greater or equal to 21"); + }); + afterEach(async () => { await db.prepare('run', 'DELETE FROM "sponsorTimes"'); await db.prepare('run', 'DELETE FROM "archivedSponsorTimes"'); @@ -52,7 +57,7 @@ describe('downvoteSegmentArchiveJob', () => { const getSegmentsInMainTable = (dayLimit: number, voteLimit: number, now: number): Promise => { return db.prepare( 'all', - 'SELECT * FROM "sponsorTimes" WHERE votes < ? AND (? - timeSubmitted) > ?', + 'SELECT * FROM "sponsorTimes" WHERE "votes" < ? AND (? - "timeSubmitted") > ?', [ voteLimit, now, From a8f7080bf287429f4cb51a225317c2db158d875b Mon Sep 17 00:00:00 2001 From: Michael C Date: Mon, 12 Jul 2021 00:32:51 -0400 Subject: [PATCH 14/24] fix typo in tests --- test/cases/getSkipSegmentsByHash.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cases/getSkipSegmentsByHash.ts b/test/cases/getSkipSegmentsByHash.ts index 33813fc..a32c208 100644 --- a/test/cases/getSkipSegmentsByHash.ts +++ b/test/cases/getSkipSegmentsByHash.ts @@ -11,7 +11,7 @@ const mockManager = ImportMock.mockStaticClass(YouTubeAPIModule, 'YouTubeAPI'); const sinonStub = mockManager.mock('listVideos'); sinonStub.callsFake(YouTubeApiMock.listVideos); -describe('getSegmentsByHash', () => { +describe('getSkipSegmentsByHash', () => { before(async () => { const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "service", "hidden", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; await db.prepare("run", query, ['getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']); @@ -109,7 +109,7 @@ describe('getSegmentsByHash', () => { it('Should return 400 for no hash', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/?categories=["shilling"]') .then(res => { - assert.strictEqual(res.status, 404); + assert.strictEqual(res.status, 400); done(); }) .catch(err => done(err)); From a23ec160c0b9509cfd6c05fcd41517fe02f22529 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 12 Jul 2021 11:05:12 -0400 Subject: [PATCH 15/24] Make reputation take into account more recent segments --- src/utils/redisKeys.ts | 2 +- src/utils/reputation.ts | 21 ++++++++++++++++----- test/cases/reputation.ts | 4 ++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/utils/redisKeys.ts b/src/utils/redisKeys.ts index fe37691..fb744c3 100644 --- a/src/utils/redisKeys.ts +++ b/src/utils/redisKeys.ts @@ -14,5 +14,5 @@ export function skipSegmentsHashKey(hashedVideoIDPrefix: VideoIDHash, service: S } export function reputationKey(userID: UserID): string { - return "reputation.user." + userID; + return "reputation.user.v2." + userID; } \ No newline at end of file diff --git a/src/utils/reputation.ts b/src/utils/reputation.ts index 3fe42c1..3d15cd8 100644 --- a/src/utils/reputation.ts +++ b/src/utils/reputation.ts @@ -7,12 +7,14 @@ interface ReputationDBResult { totalSubmissions: number, downvotedSubmissions: number, nonSelfDownvotedSubmissions: number, - upvotedSum: number, + votedSum: number, lockedSum: number, + semiOldUpvotedSubmissions: number, oldUpvotedSubmissions: number } export async function getReputation(userID: UserID): Promise { + const weekAgo = Date.now() - 1000 * 60 * 60 * 24 * 45; // 45 days ago const pastDate = Date.now() - 1000 * 60 * 60 * 24 * 45; // 45 days ago // 1596240000000 is August 1st 2020, a little after auto upvote was disabled const fetchFromDB = () => db.prepare("get", @@ -23,10 +25,11 @@ export async function getReputation(userID: UserID): Promise { WHERE b."userID" = ? AND b."votes" > 0 AND b."category" = "a"."category" AND b."videoID" = "a"."videoID" LIMIT 1) THEN 1 ELSE 0 END) AS "nonSelfDownvotedSubmissions", - SUM(CASE WHEN "votes" > 0 AND "timeSubmitted" > 1596240000000 THEN "votes" ELSE 0 END) AS "upvotedSum", + SUM(CASE WHEN "timeSubmitted" > 1596240000000 THEN "votes" ELSE 0 END) AS "votedSum", SUM(locked) AS "lockedSum", + SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "semiOldUpvotedSubmissions", SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "oldUpvotedSubmissions" - FROM "sponsorTimes" as "a" WHERE "userID" = ?`, [userID, pastDate, userID]) as Promise; + FROM "sponsorTimes" as "a" WHERE "userID" = ?`, [userID, weekAgo, pastDate, userID]) as Promise; const result = await QueryCacher.get(fetchFromDB, reputationKey(userID)); @@ -45,11 +48,19 @@ export async function getReputation(userID: UserID): Promise { return convertRange(Math.min(nonSelfDownvoteRatio, 0.4), 0.05, 0.4, -0.5, -2.5); } - if (result.oldUpvotedSubmissions < 3 || result.upvotedSum < 5) { + if (result.votedSum < 5) { return 0; } - return convertRange(Math.min(result.upvotedSum, 150), 5, 150, 0, 7) + convertRange(Math.min(result.lockedSum ?? 0, 50), 0, 50, 0, 20); + if (result.oldUpvotedSubmissions < 3) { + if (result.semiOldUpvotedSubmissions > 3) { + return convertRange(Math.min(result.votedSum, 150), 5, 150, 0, 2) + convertRange(Math.min(result.lockedSum ?? 0, 50), 0, 50, 0, 5); + } else { + return 0; + } + } + + return convertRange(Math.min(result.votedSum, 150), 5, 150, 0, 7) + convertRange(Math.min(result.lockedSum ?? 0, 50), 0, 50, 0, 20); } function convertRange(value: number, currentMin: number, currentMax: number, targetMin: number, targetMax: number): number { diff --git a/test/cases/reputation.ts b/test/cases/reputation.ts index e6029e2..de4d123 100644 --- a/test/cases/reputation.ts +++ b/test/cases/reputation.ts @@ -114,11 +114,11 @@ describe('reputation', () => { }); it("user with high reputation", async () => { - assert.strictEqual(await getReputation(getHash(userIDHighRep)), 0.24137931034482757); + assert.strictEqual(await getReputation(getHash(userIDHighRep)), 0.19310344827586207); }); it("user with high reputation and locked segments", async () => { - assert.strictEqual(await getReputation(getHash(userIDHighRepAndLocked)), 1.8413793103448277); + assert.strictEqual(await getReputation(getHash(userIDHighRepAndLocked)), 1.793103448275862); }); }); From d7b8c32c10b1d6a9862789b826cabe290b44788b Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Thu, 15 Jul 2021 12:32:00 -0400 Subject: [PATCH 16/24] Remove lock when undoing vote --- src/routes/voteOnSponsorTime.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/voteOnSponsorTime.ts b/src/routes/voteOnSponsorTime.ts index 7c9251e..eb873a0 100644 --- a/src/routes/voteOnSponsorTime.ts +++ b/src/routes/voteOnSponsorTime.ts @@ -428,7 +428,7 @@ export async function voteOnSponsorTime(req: Request, res: Response): Promise 0 && voteTypeEnum === voteTypes.normal) { // Unide and Lock this submission await db.prepare('run', 'UPDATE "sponsorTimes" SET locked = 1, hidden = 0 WHERE "UUID" = ?', [UUID]); - } else if (isVIP && incrementAmount < 0 && voteTypeEnum === voteTypes.normal) { + } else if (isVIP && incrementAmount <= 0 && voteTypeEnum === voteTypes.normal) { // Unlock if a VIP downvotes it await db.prepare('run', 'UPDATE "sponsorTimes" SET locked = 0 WHERE "UUID" = ?', [UUID]); } From 49e1e38f0516cebdaa824ff5350b84bc70c02318 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Thu, 15 Jul 2021 13:15:52 -0400 Subject: [PATCH 17/24] Enable info logs in production --- src/utils/logger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 5871d3b..24f21fa 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -40,7 +40,7 @@ class Logger { private _settings = { ERROR: true, WARN: true, - INFO: false, + INFO: true, DEBUG: false, }; From 72e17b06fc2ced4527a11d5fc4ec1ce18f581831 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Thu, 15 Jul 2021 13:55:02 -0400 Subject: [PATCH 18/24] Don't break if cron schedule is missing --- src/cronjob/downvoteSegmentArchiveJob.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cronjob/downvoteSegmentArchiveJob.ts b/src/cronjob/downvoteSegmentArchiveJob.ts index f5e8e03..478e490 100644 --- a/src/cronjob/downvoteSegmentArchiveJob.ts +++ b/src/cronjob/downvoteSegmentArchiveJob.ts @@ -56,8 +56,12 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number }; const DownvoteSegmentArchiveJob = new CronJob( - jobConfig?.schedule || new Date(1), + jobConfig?.schedule || "0 0 * * * 0", () => archiveDownvoteSegment(jobConfig?.timeThresholdInDays, jobConfig?.voteThreshold) ); +if (serverConfig?.crons?.enabled && jobConfig && !jobConfig.schedule) { + Logger.error("Invalid cron schedule for downvoteSegmentArchive"); +} + export default DownvoteSegmentArchiveJob; From 27f406f757021c0681f72e0fd758f7e58c9c463a Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Thu, 15 Jul 2021 14:02:08 -0400 Subject: [PATCH 19/24] Fix username existence check --- src/routes/setUsername.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/setUsername.ts b/src/routes/setUsername.ts index cbf2ad3..b31d6c1 100644 --- a/src/routes/setUsername.ts +++ b/src/routes/setUsername.ts @@ -62,7 +62,7 @@ export async function setUsername(req: Request, res: Response): Promise 0) { + if (row?.userName != undefined) { //already exists, update this row oldUserName = row.userName; await db.prepare('run', `UPDATE "userNames" SET "userName" = ?, "locked" = ? WHERE "userID" = ?`, [userName, locked, userID]); From 83a77dfc7414e27ef82ffb40e87b4364af46e6fe Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Thu, 15 Jul 2021 14:03:30 -0400 Subject: [PATCH 20/24] Use strict equals --- src/routes/setUsername.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/setUsername.ts b/src/routes/setUsername.ts index b31d6c1..b6a5c29 100644 --- a/src/routes/setUsername.ts +++ b/src/routes/setUsername.ts @@ -62,7 +62,7 @@ export async function setUsername(req: Request, res: Response): Promise Date: Thu, 15 Jul 2021 16:06:04 -0400 Subject: [PATCH 21/24] Disable info logging on production --- src/utils/logger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 24f21fa..5871d3b 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -40,7 +40,7 @@ class Logger { private _settings = { ERROR: true, WARN: true, - INFO: true, + INFO: false, DEBUG: false, }; From 3f6baebd712f250f5a698157ec8a72107abe71e9 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Fri, 16 Jul 2021 16:19:00 -0400 Subject: [PATCH 22/24] Add friendlier message for short userID --- src/routes/postSkipSegments.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/routes/postSkipSegments.ts b/src/routes/postSkipSegments.ts index 2065d35..dde758f 100644 --- a/src/routes/postSkipSegments.ts +++ b/src/routes/postSkipSegments.ts @@ -338,11 +338,13 @@ export async function postSkipSegments(req: Request, res: Response): Promise p + (i !== 0 ? ', ' : '') + c, ''); - return res.status(400).send(`No valid ${fields} field(s) provided`); + const formattedFields = invalidFields.reduce((p, c, i) => p + (i !== 0 ? ', ' : '') + c, ''); + const formattedErrors = errors.reduce((p, c, i) => p + (i !== 0 ? '. ' : ' ') + c, ''); + return res.status(400).send(`No valid ${formattedFields} field(s) provided.${formattedErrors}`); } //hash the userID From b98d6fd8caab990095bc8f618e3e623509f1b672 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Fri, 16 Jul 2021 16:22:55 -0400 Subject: [PATCH 23/24] Ignore votes from short ids --- src/routes/voteOnSponsorTime.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/routes/voteOnSponsorTime.ts b/src/routes/voteOnSponsorTime.ts index eb873a0..12e4fc9 100644 --- a/src/routes/voteOnSponsorTime.ts +++ b/src/routes/voteOnSponsorTime.ts @@ -258,6 +258,10 @@ export async function voteOnSponsorTime(req: Request, res: Response): Promise Date: Fri, 16 Jul 2021 16:23:08 -0400 Subject: [PATCH 24/24] Update package lock --- package-lock.json | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/package-lock.json b/package-lock.json index 0cbfd17..e5ebcff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@ajayyy/lru-diskcache": "^1.1.9", "@types/request": "^2.48.6", "better-sqlite3": "^7.4.1", + "cron": "^1.8.2", "express": "^4.17.1", "express-promise-router": "^4.1.0", "express-rate-limit": "^5.3.0", @@ -22,6 +23,7 @@ }, "devDependencies": { "@types/better-sqlite3": "^5.4.3", + "@types/cron": "^1.7.3", "@types/express": "^4.17.13", "@types/express-rate-limit": "^5.1.3", "@types/mocha": "^8.2.3", @@ -371,6 +373,16 @@ "@types/node": "*" } }, + "node_modules/@types/cron": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@types/cron/-/cron-1.7.3.tgz", + "integrity": "sha512-iPmUXyIJG1Js+ldPYhOQcYU3kCAQ2FWrSkm1FJPoii2eYSn6wEW6onPukNTT0bfiflexNSRPl6KWmAIqS+36YA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "moment": ">=2.14.0" + } + }, "node_modules/@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -1537,6 +1549,14 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "node_modules/cron": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/cron/-/cron-1.8.2.tgz", + "integrity": "sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==", + "dependencies": { + "moment-timezone": "^0.5.x" + } + }, "node_modules/cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -3474,6 +3494,25 @@ "node": ">= 8" } }, + "node_modules/moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.33", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", + "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -5856,6 +5895,16 @@ "@types/node": "*" } }, + "@types/cron": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@types/cron/-/cron-1.7.3.tgz", + "integrity": "sha512-iPmUXyIJG1Js+ldPYhOQcYU3kCAQ2FWrSkm1FJPoii2eYSn6wEW6onPukNTT0bfiflexNSRPl6KWmAIqS+36YA==", + "dev": true, + "requires": { + "@types/node": "*", + "moment": ">=2.14.0" + } + }, "@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -6776,6 +6825,14 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "cron": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/cron/-/cron-1.8.2.tgz", + "integrity": "sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==", + "requires": { + "moment-timezone": "^0.5.x" + } + }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -8229,6 +8286,19 @@ } } }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "moment-timezone": { + "version": "0.5.33", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", + "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "requires": { + "moment": ">= 2.9.0" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",