diff --git a/src/routes/getLockCategories.ts b/src/routes/getLockCategories.ts index 77b8994..74b1a0b 100644 --- a/src/routes/getLockCategories.ts +++ b/src/routes/getLockCategories.ts @@ -13,11 +13,15 @@ export async function getLockCategories(req: Request, res: Response): Promise entry.category); + const row = await db.prepare("all", 'SELECT "category", "reason" from "lockCategories" where "videoID" = ?', [videoID]) as {category: Category, reason: string}[]; + // map categories to array in JS becaues of SQL incompatibilities + const categories = row.map(item => item.category); + if (categories.length === 0 || !categories[0]) return res.sendStatus(404); + // Get longest lock reason + const reason = row.map(item => item.reason) + .reduce((a,b) => (a.length > b.length) ? a : b); return res.send({ + reason, categories }); } catch (err) { diff --git a/src/routes/getLockCategoriesByHash.ts b/src/routes/getLockCategoriesByHash.ts index defc6ce..3376539 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 (obj.reason.length > destMatch.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] }); } diff --git a/src/routes/getSkipSegments.ts b/src/routes/getSkipSegments.ts index 87fbde6..79b0f79 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 6d01d5f..6b8f00c 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; diff --git a/src/routes/postWarning.ts b/src/routes/postWarning.ts index 6d033dd..e1b1f66 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/src/utils/redisKeys.ts b/src/utils/redisKeys.ts index 4bd1764..c93e5c1 100644 --- a/src/utils/redisKeys.ts +++ b/src/utils/redisKeys.ts @@ -10,9 +10,9 @@ export function skipSegmentsHashKey(hashedVideoIDPrefix: VideoIDHash, service: S hashedVideoIDPrefix = hashedVideoIDPrefix.substring(0, 4) as VideoIDHash; if (hashedVideoIDPrefix.length !== 4) Logger.warn(`Redis skip segment hash-prefix key is not length 4! ${hashedVideoIDPrefix}`); - return `segments.v2.${ service }.${ hashedVideoIDPrefix}`; + return `segments.v2.${service}.${hashedVideoIDPrefix}`; } export function reputationKey(userID: UserID): string { - return `reputation.user.${ userID}`; + return `reputation.user.${userID}`; } diff --git a/src/utils/reputation.ts b/src/utils/reputation.ts index 2e26f88..5d06517 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/getLockCategories.ts b/test/cases/getLockCategories.ts index fd068aa..3db2733 100644 --- a/test/cases/getLockCategories.ts +++ b/test/cases/getLockCategories.ts @@ -10,19 +10,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", "1-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) => { @@ -34,7 +34,8 @@ describe("getLockCategories", () => { categories: [ "sponsor", "interaction" - ] + ], + reason: "1-longer-reason" }; assert.deepStrictEqual(data, expected); done(); @@ -50,7 +51,8 @@ describe("getLockCategories", () => { const expected = { categories: [ "preview" - ] + ], + reason: "2-reason" }; assert.deepStrictEqual(data, expected); done(); diff --git a/test/cases/getLockCategoriesByHash.ts b/test/cases/getLockCategoriesByHash.ts index 70cc24f..710611e 100644 --- a/test/cases/getLockCategoriesByHash.ts +++ b/test/cases/getLockCategoriesByHash.ts @@ -4,29 +4,28 @@ import {getHash} from "../../src/utils/getHash"; import {db} from "../../src/databases/databases"; import assert from "assert"; - describe("getLockCategoriesByHash", () => { before(async () => { 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", "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-reason-longer", "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 () => { + 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 >= 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) => { @@ -40,7 +39,8 @@ describe("getLockCategoriesByHash", () => { categories: [ "sponsor", "interaction" - ] + ], + reason: "1-reason-longer" }]; assert.deepStrictEqual(data, expected); done(); @@ -58,7 +58,8 @@ describe("getLockCategoriesByHash", () => { hash: getHash("getLockHash-2", 1), categories: [ "preview" - ] + ], + reason: "2-reason" }]; assert.deepStrictEqual(data, expected); done(); @@ -76,7 +77,8 @@ describe("getLockCategoriesByHash", () => { hash: getHash("getLockHash-3", 1), categories: [ "nonmusic" - ] + ], + reason: "3-reason" }]; assert.deepStrictEqual(data, expected); done(); @@ -94,14 +96,16 @@ describe("getLockCategoriesByHash", () => { hash: "b05a20424f24a53dac1b059fb78d861ba9723645026be2174c93a94f9106bb35", categories: [ "outro" - ] + ], + reason: "fake1-reason" }, { videoID: "fakehash-2", hash: "b05acd1cd6ec7dffe5ffea64ada91ae7469d6db2ce21c7e30ad7fa62075d450", categories: [ "intro", "preview" - ] + ], + reason: "fake2-longer-reason" }]; assert.deepStrictEqual(data, expected); done(); @@ -144,4 +148,22 @@ describe("getLockCategoriesByHash", () => { }) .catch(err => done(err)); }); + + 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)); + }); }); diff --git a/test/cases/getSkipSegments.ts b/test/cases/getSkipSegments.ts index 8d6608b..28d6a2b 100644 --- a/test/cases/getSkipSegments.ts +++ b/test/cases/getSkipSegments.ts @@ -340,4 +340,13 @@ describe("getSkipSegments", () => { }) .catch(err => done(err)); }); + + 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)); + }); }); diff --git a/test/cases/getSkipSegmentsByHash.ts b/test/cases/getSkipSegmentsByHash.ts index 5c13c40..de74414 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"]); @@ -88,7 +88,7 @@ describe("getSegmentsByHash", () => { it("Should return 400 prefix too long", (done: Done) => { const prefix = "1".repeat(50); assert.ok(prefix.length > 33, "failed to generate long enough string"); - fetch(`${getbaseURL()}/api/skipSegments/${ prefix }?categories=["shilling"]`) + fetch(`${getbaseURL()}/api/skipSegments/${prefix}?categories=["shilling"]`) .then(res => { assert.strictEqual(res.status, 400); done(); diff --git a/test/cases/getUserID.ts b/test/cases/getUserID.ts index c7c9a7b..6a4ad30 100644 --- a/test/cases/getUserID.ts +++ b/test/cases/getUserID.ts @@ -313,4 +313,13 @@ describe("getUserID", () => { }) .catch(err => done(err)); }); + + 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/getUserInfo.ts b/test/cases/getUserInfo.ts index 1958e94..7b9d865 100644 --- a/test/cases/getUserInfo.ts +++ b/test/cases/getUserInfo.ts @@ -79,7 +79,7 @@ describe("getUserInfo", () => { }); it("Should get warning data with public ID", (done: Done) => { - fetch(`${getbaseURL()}/api/userInfo?publicUserID=${ getHash("getuserinfo_warning_0")}`) + fetch(`${getbaseURL()}/api/userInfo?publicUserID=${getHash("getuserinfo_warning_0")}`) .then(async res => { assert.strictEqual(res.status, 200); const data = await res.json(); diff --git a/test/cases/postPurgeAllSegments.ts b/test/cases/postPurgeAllSegments.ts index 3402f9e..65bccbb 100644 --- a/test/cases/postPurgeAllSegments.ts +++ b/test/cases/postPurgeAllSegments.ts @@ -81,4 +81,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/postSkipSegments.ts b/test/cases/postSkipSegments.ts index 3332657..0bcaea1 100644 --- a/test/cases/postSkipSegments.ts +++ b/test/cases/postSkipSegments.ts @@ -610,7 +610,7 @@ describe("postSkipSegments", () => { done(); // success } else { const body = await res.text(); - done(`Status code was ${ res.status } ${ body}`); + done(`Status code was ${res.status} ${body}`); } }) .catch(err => done(err)); @@ -636,7 +636,7 @@ describe("postSkipSegments", () => { done(); // success } else { const body = await res.text(); - done(`Status code was ${ res.status } ${ body}`); + done(`Status code was ${res.status} ${body}`); } }) .catch(err => done(err)); diff --git a/test/cases/postWarning.ts b/test/cases/postWarning.ts index b685eee..b3c15f6 100644 --- a/test/cases/postWarning.ts +++ b/test/cases/postWarning.ts @@ -98,4 +98,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)); + }); }); diff --git a/test/cases/reputation.ts b/test/cases/reputation.ts index bcb6192..8f09a41 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); }); }); diff --git a/test/cases/voteOnSponsorTime.ts b/test/cases/voteOnSponsorTime.ts index ce1a914..0447a94 100644 --- a/test/cases/voteOnSponsorTime.ts +++ b/test/cases/voteOnSponsorTime.ts @@ -235,7 +235,7 @@ describe("voteOnSponsorTime", () => { assert.strictEqual(sponsorVotes, 1); done(); } else { - done(`Status code was ${ res.status}`); + done(`Status code was ${res.status}`); } }) .catch(err => done(err)); @@ -245,7 +245,7 @@ describe("voteOnSponsorTime", () => { it("Should not be able to change your vote to an invalid category", (done: Done) => { const vote = (inputCat: string, assertCat: string, callback: Done) => { fetch(`${getbaseURL() - }/api/voteOnSponsorTime?userID=randomID2&UUID=incorrect-category-change&category=${ inputCat}`) + }/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"]); assert.strictEqual(row.category, assertCat);