mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-06 11:36:58 +03:00
Merge pull request #610 from mini-bomba/warning-history
Keep a history of warnings in the public database
This commit is contained in:
@@ -31,15 +31,15 @@ module.exports = {
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["src/**/*.ts"],
|
||||
files: ["**/*.ts"],
|
||||
|
||||
parserOptions: {
|
||||
project: ["./tsconfig.json"],
|
||||
project: ["./tsconfig.eslint.json"],
|
||||
},
|
||||
|
||||
rules: {
|
||||
"@typescript-eslint/no-misused-promises": "warn",
|
||||
"@typescript-eslint/no-floating-promises" : "warn"
|
||||
"@typescript-eslint/no-misused-promises": "error",
|
||||
"@typescript-eslint/no-floating-promises" : "error"
|
||||
}
|
||||
},
|
||||
],
|
||||
|
||||
1
ci.json
1
ci.json
@@ -56,7 +56,6 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"hoursAfterWarningExpires": 24,
|
||||
"rateLimit": {
|
||||
"vote": {
|
||||
"windowMs": 900000,
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
"webhooks": [],
|
||||
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "preview", "music_offtopic", "poi_highlight"], // List of supported categories any other category will be rejected
|
||||
"getTopUsersCacheTimeMinutes": 5, // cacheTime for getTopUsers result in minutes
|
||||
"maxNumberOfActiveWarnings": 3, // Users with this number of warnings will be blocked until warnings expire
|
||||
"hoursAfterWarningExpire": 24,
|
||||
"rateLimit": {
|
||||
"vote": {
|
||||
"windowMs": 900000, // 15 minutes
|
||||
|
||||
7
databases/_upgrade_sponsorTimes_45.sql
Normal file
7
databases/_upgrade_sponsorTimes_45.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE "warnings" ADD "disableTime" INTEGER NULL;
|
||||
|
||||
UPDATE "config" SET value = 45 WHERE key = 'version';
|
||||
|
||||
COMMIT;
|
||||
@@ -37,8 +37,6 @@ addDefaults(config, {
|
||||
},
|
||||
deArrowTypes: ["title", "thumbnail"],
|
||||
maxTitleLength: 110,
|
||||
maxNumberOfActiveWarnings: 1,
|
||||
hoursAfterWarningExpires: 16300000,
|
||||
adminUserID: "",
|
||||
discordCompletelyIncorrectReportWebhookURL: null,
|
||||
discordFirstTimeSubmissionsWebhookURL: null,
|
||||
|
||||
@@ -3,7 +3,6 @@ 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;
|
||||
|
||||
@@ -25,7 +24,7 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number
|
||||
timeNow,
|
||||
threshold
|
||||
]
|
||||
) as DBSegment[];
|
||||
);
|
||||
|
||||
} catch (err) {
|
||||
Logger.error("Execption when insert segment in archivedSponsorTimes");
|
||||
@@ -43,7 +42,7 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number
|
||||
timeNow,
|
||||
threshold
|
||||
]
|
||||
) as DBSegment[];
|
||||
);
|
||||
|
||||
} catch (err) {
|
||||
Logger.error("Execption when deleting segment in sponsorTimes");
|
||||
|
||||
@@ -6,7 +6,10 @@ export interface QueryOption {
|
||||
export interface IDatabase {
|
||||
init(): Promise<void>;
|
||||
|
||||
prepare(type: QueryType, query: string, params?: any[], options?: QueryOption): Promise<any | any[] | void>;
|
||||
prepare(type: "run", query: string, params?: any[], options?: QueryOption): Promise<void>;
|
||||
prepare(type: "get", query: string, params?: any[], options?: QueryOption): Promise<any>;
|
||||
prepare(type: "all", query: string, params?: any[], options?: QueryOption): Promise<any[]>;
|
||||
prepare(type: QueryType, query: string, params?: any[], options?: QueryOption): Promise<any>;
|
||||
|
||||
highLoad(): boolean;
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ export class Postgres implements IDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
async prepare(type: QueryType, query: string, params?: any[], options: QueryOption = {}): Promise<any[]> {
|
||||
async prepare(type: QueryType, query: string, params?: any[], options: QueryOption = {}): Promise<any> {
|
||||
// Convert query to use numbered parameters
|
||||
let count = 1;
|
||||
for (let char = 0; char < query.length; char++) {
|
||||
|
||||
@@ -13,7 +13,7 @@ export class Sqlite implements IDatabase {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
async prepare(type: QueryType, query: string, params: any[] = []): Promise<any[]> {
|
||||
async prepare(type: QueryType, query: string, params: any[] = []): Promise<any> {
|
||||
// Logger.debug(`prepare (sqlite): type: ${type}, query: ${query}, params: ${params}`);
|
||||
const preparedQuery = this.db.prepare(Sqlite.processQuery(query));
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ function chooseSegment<T extends DBSegment>(choices: T[]): FullVideoSegmentVideo
|
||||
return {
|
||||
segments: transformDBSegments(choices),
|
||||
hasStartSegment
|
||||
}
|
||||
};
|
||||
}
|
||||
// if locked, only choose from locked
|
||||
const locked = choices.filter((segment) => segment.locked);
|
||||
|
||||
@@ -164,20 +164,15 @@ async function autoModerateSubmission(apiVideoDetails: videoDetails,
|
||||
}
|
||||
|
||||
async function checkUserActiveWarning(userID: HashedUserID): Promise<CheckResult> {
|
||||
const MILLISECONDS_IN_HOUR = 3600000;
|
||||
const now = Date.now();
|
||||
const warnings = (await db.prepare("all",
|
||||
const warning = await db.prepare("get",
|
||||
`SELECT "reason"
|
||||
FROM warnings
|
||||
WHERE "userID" = ? AND "issueTime" > ? AND enabled = 1 AND type = 0
|
||||
WHERE "userID" = ? AND enabled = 1 AND type = 0
|
||||
ORDER BY "issueTime" DESC`,
|
||||
[
|
||||
userID,
|
||||
Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))
|
||||
],
|
||||
) as {reason: string}[]).sort((a, b) => (b?.reason?.length ?? 0) - (a?.reason?.length ?? 0));
|
||||
[userID],
|
||||
) as {reason: string};
|
||||
|
||||
if (warnings?.length >= config.maxNumberOfActiveWarnings) {
|
||||
if (warning != null) {
|
||||
const defaultMessage = "Submission rejected due to a tip from a moderator. This means that we noticed you were making some common mistakes"
|
||||
+ " that are not malicious, and we just want to clarify the rules. "
|
||||
+ "Could you please send a message in discord.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
@@ -185,7 +180,7 @@ async function checkUserActiveWarning(userID: HashedUserID): Promise<CheckResult
|
||||
|
||||
return {
|
||||
pass: false,
|
||||
errorMessage: defaultMessage + (warnings[0]?.reason?.length > 0 ? `\n\nTip message: '${warnings[0].reason}'` : ""),
|
||||
errorMessage: defaultMessage + (warning.reason?.length > 0 ? `\n\nTip message: '${warning.reason}'` : ""),
|
||||
errorCode: 403
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { db } from "../databases/databases";
|
||||
import { isUserVIP } from "../utils/isUserVIP";
|
||||
import { getHashCache } from "../utils/getHashCache";
|
||||
import { HashedUserID, UserID } from "../types/user.model";
|
||||
import { config } from "../config";
|
||||
import { generateWarningDiscord, warningData, dispatchEvent } from "../utils/webhookUtils";
|
||||
import { WarningType } from "../types/warning.model";
|
||||
|
||||
@@ -16,12 +15,7 @@ type warningEntry = {
|
||||
reason: string
|
||||
}
|
||||
|
||||
function checkExpiredWarning(warning: warningEntry): boolean {
|
||||
const MILLISECONDS_IN_HOUR = 3600000;
|
||||
const now = Date.now();
|
||||
const expiry = Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR));
|
||||
return warning.issueTime > expiry && !warning.enabled;
|
||||
}
|
||||
const MAX_EDIT_DELAY = 900000; // 15 mins
|
||||
|
||||
const getUsername = (userID: HashedUserID) => db.prepare("get", `SELECT "userName" FROM "userNames" WHERE "userID" = ?`, [userID], { useReplica: true });
|
||||
|
||||
@@ -44,30 +38,30 @@ export async function postWarning(req: Request, res: Response): Promise<Response
|
||||
|
||||
try {
|
||||
if (enabled) {
|
||||
const previousWarning = await db.prepare("get", 'SELECT * FROM "warnings" WHERE "userID" = ? AND "issuerUserID" = ? AND "type" = ?', [userID, issuerUserID, type]) as warningEntry;
|
||||
|
||||
if (!previousWarning) {
|
||||
if (!reason) {
|
||||
return res.status(400).json({ "message": "Missing warning reason" });
|
||||
}
|
||||
const previousWarning = await db.prepare("get", 'SELECT * FROM "warnings" WHERE "userID" = ? AND "type" = ? AND "enabled" = 1', [userID, type]) as warningEntry;
|
||||
|
||||
if (!previousWarning) {
|
||||
await db.prepare(
|
||||
"run",
|
||||
'INSERT INTO "warnings" ("userID", "issueTime", "issuerUserID", "enabled", "reason", "type") VALUES (?, ?, ?, 1, ?, ?)',
|
||||
[userID, issueTime, issuerUserID, reason, type]
|
||||
);
|
||||
resultStatus = "issued to";
|
||||
// check if warning is still within issue time and warning is not enabled
|
||||
} else if (checkExpiredWarning(previousWarning) ) {
|
||||
// allow a warning to be edited by the same vip within 15 mins of issuing
|
||||
} else if (issuerUserID === previousWarning.issuerUserID && (Date.now() - MAX_EDIT_DELAY) < previousWarning.issueTime) {
|
||||
await db.prepare(
|
||||
"run", 'UPDATE "warnings" SET "enabled" = 1, "reason" = ? WHERE "userID" = ? AND "issueTime" = ?',
|
||||
"run", 'UPDATE "warnings" SET "reason" = ? WHERE "userID" = ? AND "issueTime" = ?',
|
||||
[reason, userID, previousWarning.issueTime]
|
||||
);
|
||||
resultStatus = "re-enabled for";
|
||||
resultStatus = "edited for";
|
||||
} else {
|
||||
return res.sendStatus(409);
|
||||
}
|
||||
} else {
|
||||
await db.prepare("run", 'UPDATE "warnings" SET "enabled" = 0 WHERE "userID" = ? AND "type" = ?', [userID, type]);
|
||||
await db.prepare("run", 'UPDATE "warnings" SET "enabled" = 0, "disableTime" = ? WHERE "userID" = ? AND "type" = ? AND "enabled" = 1', [issueTime, userID, type]);
|
||||
resultStatus = "removed from";
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { isUserBanned } from "../utils/checkBan";
|
||||
import { HashedUserID } from "../types/user.model";
|
||||
import { isRequestInvalid } from "../utils/requestValidator";
|
||||
|
||||
function logUserNameChange(userID: string, newUserName: string, oldUserName: string, updatedByAdmin: boolean): Promise<Response> {
|
||||
function logUserNameChange(userID: string, newUserName: string, oldUserName: string, updatedByAdmin: boolean): Promise<void> {
|
||||
return privateDB.prepare("run",
|
||||
`INSERT INTO "userNameLogs"("userID", "newUserName", "oldUserName", "updatedByAdmin", "updatedAt") VALUES(?, ?, ?, ?, ?)`,
|
||||
[userID, newUserName, oldUserName, + updatedByAdmin, new Date().getTime()]
|
||||
|
||||
@@ -379,14 +379,12 @@ export async function vote(ip: IPAddress, UUID: SegmentUUID, paramUserID: UserID
|
||||
return { status: 400 };
|
||||
}
|
||||
|
||||
const MILLISECONDS_IN_HOUR = 3600000;
|
||||
const now = Date.now();
|
||||
const warnings = (await db.prepare("all", `SELECT "reason" FROM warnings WHERE "userID" = ? AND "issueTime" > ? AND enabled = 1 AND type = 0`,
|
||||
[nonAnonUserID, Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))],
|
||||
const warning = (await db.prepare("get", `SELECT "reason" FROM warnings WHERE "userID" = ? AND enabled = 1 AND type = 0`,
|
||||
[nonAnonUserID],
|
||||
));
|
||||
|
||||
if (warnings.length >= config.maxNumberOfActiveWarnings) {
|
||||
const warningReason = warnings[0]?.reason;
|
||||
if (warning != null) {
|
||||
const warningReason = warning.reason;
|
||||
lock.unlock();
|
||||
return { status: 403, message: "Vote rejected due to a tip from a moderator. This means that we noticed you were making some common mistakes that are not malicious, and we just want to clarify the rules. " +
|
||||
"Could you please send a message in Discord or Matrix so we can further help you?" +
|
||||
|
||||
@@ -109,8 +109,6 @@ export interface SBSConfig {
|
||||
categorySupport: Record<string, string[]>;
|
||||
maxTitleLength: number;
|
||||
getTopUsersCacheTimeMinutes: number;
|
||||
maxNumberOfActiveWarnings: number;
|
||||
hoursAfterWarningExpires: number;
|
||||
rateLimit: {
|
||||
vote: RateLimitConfig;
|
||||
view: RateLimitConfig;
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"hoursAfterWarningExpires": 24,
|
||||
"rateLimit": {
|
||||
"vote": {
|
||||
"windowMs": 900000,
|
||||
|
||||
@@ -73,11 +73,11 @@ describe("getUserID", () => {
|
||||
)
|
||||
);
|
||||
|
||||
it("Should be able to get multiple fuzzy user info from middle", () => {
|
||||
it("Should be able to get multiple fuzzy user info from middle", () =>
|
||||
validateSearch("user",
|
||||
[users["fuzzy_1"], users["fuzzy_2"], users["specific_1"]]
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it("Should be able to get with fuzzy public ID", () => {
|
||||
const userID = users["public_1"].pubID.substring(0,60);
|
||||
|
||||
@@ -81,19 +81,19 @@ describe("getUserInfo", () => {
|
||||
|
||||
// warnings & bans
|
||||
// warn-0
|
||||
insertWarning(db, users["warn-0"].pubID, { reason: "warning0-0", issueTime: 10 });
|
||||
await insertWarning(db, users["warn-0"].pubID, { reason: "warning0-0", issueTime: 10 });
|
||||
// warn-1
|
||||
insertWarning(db, users["warn-1"].pubID, { reason: "warning1-0", issueTime: 20 });
|
||||
insertWarning(db, users["warn-1"].pubID, { reason: "warning1-1", issueTime: 30 });
|
||||
await insertWarning(db, users["warn-1"].pubID, { reason: "warning1-0", issueTime: 20 });
|
||||
await insertWarning(db, users["warn-1"].pubID, { reason: "warning1-1", issueTime: 30 });
|
||||
// warn -2
|
||||
insertWarning(db, users["warn-2"].pubID, { reason: "warning2-0", issueTime: 40, enabled: false });
|
||||
await insertWarning(db, users["warn-2"].pubID, { reason: "warning2-0", issueTime: 40, enabled: false });
|
||||
// warn-3
|
||||
insertWarning(db, users["warn-3"].pubID, { reason: "warning3-0", issueTime: 50 });
|
||||
insertWarning(db, users["warn-3"].pubID, { reason: "warning3-1", issueTime: 60, enabled: false });
|
||||
await insertWarning(db, users["warn-3"].pubID, { reason: "warning3-0", issueTime: 50 });
|
||||
await insertWarning(db, users["warn-3"].pubID, { reason: "warning3-1", issueTime: 60, enabled: false });
|
||||
|
||||
// ban-
|
||||
insertBan(db, users["ban-1"].pubID);
|
||||
insertBan(db, users["ban-2"].pubID);
|
||||
await insertBan(db, users["ban-1"].pubID);
|
||||
await insertBan(db, users["ban-2"].pubID);
|
||||
});
|
||||
|
||||
it("Should be able to get a 200", () => statusTest(200, { userID: users["n-1"].privID }));
|
||||
|
||||
@@ -33,11 +33,11 @@ const checkUserViews = (user: User) =>
|
||||
});
|
||||
|
||||
describe("getViewsForUser", function() {
|
||||
before(() => {
|
||||
before(async () => {
|
||||
// add views for users
|
||||
insertSegment(db, { userID: users["u-1"].pubID, views: users["u-1"].info.views1 });
|
||||
insertSegment(db, { userID: users["u-1"].pubID, views: users["u-1"].info.views2 });
|
||||
insertSegment(db, { userID: users["u-2"].pubID, views: users["u-2"].info.views });
|
||||
await insertSegment(db, { userID: users["u-1"].pubID, views: users["u-1"].info.views1 });
|
||||
await insertSegment(db, { userID: users["u-1"].pubID, views: users["u-1"].info.views2 });
|
||||
await insertSegment(db, { userID: users["u-2"].pubID, views: users["u-2"].info.views });
|
||||
});
|
||||
it("Should get back views for user one", () =>
|
||||
checkUserViews(users["u-1"])
|
||||
|
||||
@@ -15,7 +15,6 @@ describe("postBranding", () => {
|
||||
const userID5 = `PostBrandingUser5${".".repeat(16)}`;
|
||||
const userID6 = `PostBrandingUser6${".".repeat(16)}`;
|
||||
const userID7 = `PostBrandingUser7${".".repeat(16)}`;
|
||||
const userID8 = `PostBrandingUser8${".".repeat(16)}`;
|
||||
const bannedUser = `BannedPostBrandingUser${".".repeat(16)}`;
|
||||
|
||||
|
||||
|
||||
@@ -50,12 +50,12 @@ describe("postSkipSegments", () => {
|
||||
const queryDatabaseActionType = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "actionType" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]);
|
||||
const queryDatabaseVideoInfo = (videoID: string) => db.prepare("get", `SELECT * FROM "videoInfo" WHERE "videoID" = ?`, [videoID]);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "videoDuration", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
db.prepare("run", insertSponsorTimeQuery, ["full_video_segment", 0, 0, 0, "full-video-uuid-0", submitUserTwoHash, 0, 0, "sponsor", "full", 0, 0, "full_video_segment"]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, ["full_video_segment", 0, 0, 0, "full-video-uuid-0", submitUserTwoHash, 0, 0, "sponsor", "full", 0, 0, "full_video_segment"]);
|
||||
|
||||
const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)';
|
||||
db.prepare("run", insertVipUserQuery, [getHash(submitVIPuser)]);
|
||||
await db.prepare("run", insertVipUserQuery, [getHash(submitVIPuser)]);
|
||||
});
|
||||
|
||||
it("Should be able to submit a single time (Params method)", (done) => {
|
||||
|
||||
@@ -19,11 +19,11 @@ describe("postSkipSegments - Automod 80%", () => {
|
||||
|
||||
const queryDatabaseCategory = (videoID: string) => db.prepare("all", `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, [videoID]);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "videoDuration", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 0, 1000, 0, "80percent-uuid-0", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 1001, 1005, 0, "80percent-uuid-1", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 0, 5000, -2, "80percent-uuid-2", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 0, 1000, 0, "80percent-uuid-0", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 1001, 1005, 0, "80percent-uuid-1", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 0, 5000, -2, "80percent-uuid-2", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
});
|
||||
|
||||
it("Should allow multiple times if total is under 80% of video (JSON method)", (done) => {
|
||||
|
||||
@@ -21,10 +21,10 @@ describe("postSkipSegments - duration", () => {
|
||||
|
||||
const queryDatabaseDuration = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "videoDuration", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 0, 0, 0, "full-video-duration-uuid-0", userIDTwo, 0, 0, "sponsor", "full", 123, 0, "full_video_duration_segment"]);
|
||||
db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 25, 30, 0, "full-video-duration-uuid-1", userIDTwo, 0, 0, "sponsor", "skip", 123, 0, "full_video_duration_segment"]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 0, 0, 0, "full-video-duration-uuid-0", userIDTwo, 0, 0, "sponsor", "full", 123, 0, "full_video_duration_segment"]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 25, 30, 0, "full-video-duration-uuid-1", userIDTwo, 0, 0, "sponsor", "skip", 123, 0, "full_video_duration_segment"]);
|
||||
});
|
||||
|
||||
it("Should be able to submit a single time with a precise duration close to the one from the YouTube API (JSON method)", (done) => {
|
||||
|
||||
@@ -21,17 +21,17 @@ describe("postSkipSegments Features - Chapters", () => {
|
||||
};
|
||||
}
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const submitNumberOfTimes = 10;
|
||||
const submitUser_reputationHash = getHash(submitUser_reputation);
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", views, category, "actionType", "shadowHidden") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
for (let i = 0; i < submitNumberOfTimes; i++) {
|
||||
const uuid = `post_reputation_uuid-${i}`;
|
||||
const videoID = `post_reputation_video-${i}`;
|
||||
db.prepare("run", insertSponsorTimeQuery, [videoID, 1, 11, 5, 1, uuid, submitUser_reputationHash, 1597240000000, 50, "sponsor", "skip", 0]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, [videoID, 1, 11, 5, 1, uuid, submitUser_reputationHash, 1597240000000, 50, "sponsor", "skip", 0]);
|
||||
}
|
||||
// user feature
|
||||
db.prepare("run", `INSERT INTO "userFeatures" ("userID", "feature", "issuerUserID", "timeSubmitted") VALUES(?, ?, ?, ?)`, [getHash(submitUser_feature), Feature.ChapterSubmitter, "generic-VIP", 0]);
|
||||
await db.prepare("run", `INSERT INTO "userFeatures" ("userID", "feature", "issuerUserID", "timeSubmitted") VALUES(?, ?, ?, ?)`, [getHash(submitUser_feature), Feature.ChapterSubmitter, "generic-VIP", 0]);
|
||||
});
|
||||
|
||||
it("Should be able to submit a single chapter due to reputation (JSON method)", (done) => {
|
||||
|
||||
@@ -9,10 +9,10 @@ describe("postSkipSegments - LockedVideos", () => {
|
||||
const videoID = "lockedVideo";
|
||||
const userID = userIDOne;
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertLockCategoriesQuery = `INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") VALUES(?, ?, ?, ?)`;
|
||||
db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]);
|
||||
db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]);
|
||||
await db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]);
|
||||
await db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]);
|
||||
});
|
||||
|
||||
it("Should return 403 and custom reason for submiting in lockedCategory", (done) => {
|
||||
|
||||
@@ -19,8 +19,8 @@ describe("postSkipSegments - shadowban", () => {
|
||||
|
||||
const queryDatabaseShadowhidden = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "shadowHidden", "userID" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]);
|
||||
|
||||
before(() => {
|
||||
db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, [banUser01Hash]);
|
||||
before(async () => {
|
||||
await db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, [banUser01Hash]);
|
||||
});
|
||||
|
||||
it("Should automatically shadowban segments if user is banned", (done) => {
|
||||
|
||||
@@ -21,10 +21,10 @@ describe("postSkipSegments - userAgent", () => {
|
||||
};
|
||||
const dbFormatSegment = convertSingleToDBFormat(segment);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertLockCategoriesQuery = `INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") VALUES(?, ?, ?, ?)`;
|
||||
db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]);
|
||||
db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]);
|
||||
await db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]);
|
||||
await db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]);
|
||||
});
|
||||
|
||||
it("Should be able to submit with empty user-agent", (done) => {
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
import { config } from "../../src/config";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { db } from "../../src/databases/databases";
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { usersForSuite } from "../utils/randomUsers";
|
||||
|
||||
describe("postSkipSegments Warnings", () => {
|
||||
// Constant and helpers
|
||||
const warnUser01 = "warn-user01";
|
||||
const warnUser01Hash = getHash(warnUser01);
|
||||
const warnUser02 = "warn-user02";
|
||||
const warnUser02Hash = getHash(warnUser02);
|
||||
const warnUser03 = "warn-user03";
|
||||
const warnUser03Hash = getHash(warnUser03);
|
||||
const warnUser04 = "warn-user04";
|
||||
const warnUser04Hash = getHash(warnUser04);
|
||||
|
||||
const users = usersForSuite("postSkipSegmentsWarnings");
|
||||
const warnVideoID = "postSkipSegments-warn-video";
|
||||
|
||||
const endpoint = "/api/skipSegments";
|
||||
@@ -24,104 +15,92 @@ describe("postSkipSegments Warnings", () => {
|
||||
data
|
||||
});
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const now = Date.now();
|
||||
|
||||
const warnVip01Hash = getHash("postSkipSegmentsWarnVIP");
|
||||
|
||||
const reason01 = "Reason01";
|
||||
const reason02 = "";
|
||||
const reason03 = "Reason03";
|
||||
|
||||
const MILLISECONDS_IN_HOUR = 3600000;
|
||||
const WARNING_EXPIRATION_TIME = config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR;
|
||||
|
||||
const insertWarningQuery = 'INSERT INTO warnings ("userID", "issuerUserID", "enabled", "reason", "issueTime") VALUES(?, ?, ?, ?, ?)';
|
||||
// User 1 | 1 active | custom reason
|
||||
db.prepare("run", insertWarningQuery, [warnUser01Hash, warnVip01Hash, 1, reason01, now]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u01.public, users.vip01.public, 1, reason01, now]);
|
||||
// User 2 | 1 inactive | default reason
|
||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, warnVip01Hash, 0, reason02, now]);
|
||||
// User 3 | 1 expired, active | custom reason
|
||||
db.prepare("run", insertWarningQuery, [warnUser03Hash, warnVip01Hash, 1, reason03, (now - WARNING_EXPIRATION_TIME - 1000)]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u02.public, users.vip01.public, 0, reason02, now]);
|
||||
// User 3 | 1 inactive, 1 active | different reasons
|
||||
await db.prepare("run", insertWarningQuery, [users.u03.public, users.vip01.public, 0, reason01, now]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u03.public, users.vip01.public, 1, reason03, now+1]);
|
||||
// User 4 | 1 active | default reason
|
||||
db.prepare("run", insertWarningQuery, [warnUser04Hash, warnVip01Hash, 1, reason02, now]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u04.public, users.vip01.public, 1, reason02, now]);
|
||||
});
|
||||
|
||||
it("Should be rejected with custom message if user has active warnings", (done) => {
|
||||
postSkipSegmentJSON({
|
||||
userID: warnUser01,
|
||||
it("Should be rejected with custom message if user has active warnings", async () => {
|
||||
const res = await postSkipSegmentJSON({
|
||||
userID: users.u01.private,
|
||||
videoID: warnVideoID,
|
||||
segments: [{
|
||||
segment: [0, 10],
|
||||
category: "sponsor",
|
||||
}],
|
||||
})
|
||||
.then(res => {
|
||||
});
|
||||
assert.strictEqual(res.status, 403);
|
||||
const errorMessage = res.data;
|
||||
const reason = "Reason01";
|
||||
const expected = "Submission rejected due to a tip from a moderator. This means that we noticed you were making some common mistakes"
|
||||
+ " that are not malicious, and we just want to clarify the rules. "
|
||||
+ "Could you please send a message in discord.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
+ `Your userID is ${warnUser01Hash}.\n\nTip message: '${reason}'`;
|
||||
+ `Your userID is ${users.u01.public}.\n\nTip message: '${reason}'`;
|
||||
|
||||
assert.strictEqual(errorMessage, expected);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be accepted if user has inactive warning", (done) => {
|
||||
postSkipSegmentJSON({
|
||||
userID: warnUser02,
|
||||
it("Should be accepted if user has inactive warning", async () => {
|
||||
const res = await postSkipSegmentJSON({
|
||||
userID: users.u02.private,
|
||||
videoID: warnVideoID,
|
||||
segments: [{
|
||||
segment: [50, 60],
|
||||
category: "sponsor",
|
||||
}],
|
||||
})
|
||||
.then(res => {
|
||||
});
|
||||
assert.ok(res.status === 200, `Status code was ${res.status} ${res.data}`);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be accepted if user has expired warning", (done) => {
|
||||
postSkipSegmentJSON({
|
||||
userID: warnUser03,
|
||||
it("Should be rejected with custom message if user has active warnings, even if has one inactive warning, should use current message", async () => {
|
||||
const res = await postSkipSegmentJSON({
|
||||
userID: users.u03.private,
|
||||
videoID: warnVideoID,
|
||||
segments: [{
|
||||
segment: [53, 60],
|
||||
segment: [10, 20],
|
||||
category: "sponsor",
|
||||
}],
|
||||
})
|
||||
.then(res => {
|
||||
assert.ok(res.status === 200, `Status code was ${res.status} ${res.data}`);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
assert.strictEqual(res.status, 403);
|
||||
const errorMessage = res.data;
|
||||
const reason = "Reason03";
|
||||
const expected = "Submission rejected due to a tip from a moderator. This means that we noticed you were making some common mistakes"
|
||||
+ " that are not malicious, and we just want to clarify the rules. "
|
||||
+ "Could you please send a message in discord.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
+ `Your userID is ${users.u03.public}.\n\nTip message: '${reason}'`;
|
||||
|
||||
assert.strictEqual(errorMessage, expected);
|
||||
});
|
||||
|
||||
it("Should be rejected with default message if user has active warning", (done) => {
|
||||
postSkipSegmentJSON({
|
||||
userID: warnUser04,
|
||||
it("Should be rejected with default message if user has active warning", async () => {
|
||||
const res = await postSkipSegmentJSON({
|
||||
userID: users.u04.private,
|
||||
videoID: warnVideoID,
|
||||
segments: [{
|
||||
segment: [0, 10],
|
||||
category: "sponsor",
|
||||
}],
|
||||
})
|
||||
.then(res => {
|
||||
});
|
||||
assert.strictEqual(res.status, 403);
|
||||
const errorMessage = res.data;
|
||||
const expected = "Submission rejected due to a tip from a moderator. This means that we noticed you were making some common mistakes"
|
||||
+ " that are not malicious, and we just want to clarify the rules. "
|
||||
+ "Could you please send a message in discord.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
+ `Your userID is ${warnUser04Hash}.`;
|
||||
+ `Your userID is ${users.u04.public}.`;
|
||||
assert.strictEqual(errorMessage, expected);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,33 +3,44 @@ import { db } from "../../src/databases/databases";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { usersForSuite } from "../utils/randomUsers";
|
||||
|
||||
describe("postWarning", () => {
|
||||
// constants
|
||||
const endpoint = "/api/warnUser";
|
||||
const getWarning = (userID: string, type = 0) => db.prepare("get", `SELECT "userID", "issueTime", "issuerUserID", enabled, "reason" FROM warnings WHERE "userID" = ? AND "type" = ?`, [userID, type]);
|
||||
const getWarning = (userID: string, type = 0) => db.prepare("all", `SELECT * FROM warnings WHERE "userID" = ? AND "type" = ? ORDER BY "issueTime" ASC`, [userID, type]);
|
||||
|
||||
const warneduserOneID = "warning-0";
|
||||
const warnedUserTwoID = "warning-1";
|
||||
const warnedUserOnePublicID = getHash(warneduserOneID);
|
||||
const warnedUserTwoPublicID = getHash(warnedUserTwoID);
|
||||
const warningVipOne = "warning-vip-1";
|
||||
const warningVipTwo = "warning-vip-2";
|
||||
const nonVipUser = "warning-non-vip";
|
||||
const users = usersForSuite("postWarning");
|
||||
|
||||
before(async () => {
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES (?)`, [getHash(warningVipOne)]);
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES (?)`, [getHash(warningVipTwo)]);
|
||||
const insertWarningQuery = 'INSERT INTO warnings ("userID", "issuerUserID", "enabled", "reason", "issueTime") VALUES(?, ?, ?, ?, ?)';
|
||||
const insertWarningQueryWithDisableTime = 'INSERT INTO warnings ("userID", "issuerUserID", "enabled", "reason", "issueTime", "disableTime") VALUES(?, ?, ?, ?, ?, ?)';
|
||||
const HOUR = 60 * 60 * 1000;
|
||||
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES (?)`, [users.vip1.public]);
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES (?)`, [users.vip2.public]);
|
||||
|
||||
await db.prepare("run", insertWarningQuery, [users.u1.public, users.vip1.public, 1, "warn reason 1", (Date.now() - 24 * HOUR)]); // 24 hours is much past the edit deadline
|
||||
await db.prepare("run", insertWarningQuery, [users.u2.public, users.vip1.public, 1, "warn reason 2", (Date.now() - 24 * HOUR)]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u3.public, users.vip1.public, 1, "warn reason 3", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u4.public, users.vip1.public, 1, "warn reason 4", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u6.public, users.vip1.public, 1, "warn reason 6", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u9.public, users.vip1.public, 0, "warn reason 9", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u10.public, users.vip1.public, 1, "warn reason 10", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u11.public, users.vip1.public, 1, "warn reason 11", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u12.public, users.vip1.public, 0, "warn reason 12", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u13.public, users.vip1.public, 0, "warn reason 13", Date.now()]);
|
||||
await db.prepare("run", insertWarningQueryWithDisableTime, [users.u14.public, users.vip1.public, 0, "warn reason 14", 123, 12345]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u14.public, users.vip1.public, 1, "another reason 14", Date.now()]);
|
||||
});
|
||||
|
||||
it("Should be able to create warning if vip (exp 200)", (done) => {
|
||||
it("Should be able to create warning if vip (exp 200)", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u0.public,
|
||||
reason: "warning-reason-0"
|
||||
};
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
@@ -37,165 +48,284 @@ describe("postWarning", () => {
|
||||
issuerUserID: getHash(json.issuerUserID),
|
||||
reason: json.reason,
|
||||
};
|
||||
assert.ok(partialDeepEquals(row, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should be not be able to create a duplicate warning if vip", (done) => {
|
||||
it("Should be not be able to edit a warning if past deadline and same vip", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u1.public,
|
||||
reason: "edited reason 1",
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 409);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: getHash(json.issuerUserID),
|
||||
issuerUserID: users.vip1.public,
|
||||
};
|
||||
assert.ok(partialDeepEquals(row, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should be able to remove warning if vip", (done) => {
|
||||
it("Should be not be able to edit a warning if past deadline and different vip", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
enabled: false
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u2.public,
|
||||
reason: "edited reason 2",
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 409);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip1.public,
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should be able to remove warning if same vip as issuer", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u3.public,
|
||||
enabled: false
|
||||
};
|
||||
const beforeTime = Date.now();
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
const afterTime = Date.now();
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 0
|
||||
};
|
||||
assert.ok(partialDeepEquals(row, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
// check disableTime
|
||||
assert.ok(row[0].disableTime >= beforeTime && row[0].disableTime <= afterTime, "expected disableTime to be somewhere between execution start and end");
|
||||
});
|
||||
|
||||
it("Should not be able to create warning if not vip (exp 403)", (done) => {
|
||||
it("Should be able to remove warning if not the same vip as issuer", async () => {
|
||||
const json = {
|
||||
issuerUserID: nonVipUser,
|
||||
userID: warnedUserOnePublicID,
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if missing body", (done) => {
|
||||
client.post(endpoint, {})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should re-enable disabled warning", (done) => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
enabled: true
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1
|
||||
};
|
||||
assert.ok(partialDeepEquals(data, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to remove your own warning", (done) => {
|
||||
const json = {
|
||||
userID: warneduserOneID,
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u4.public,
|
||||
enabled: false
|
||||
};
|
||||
const beforeTime = Date.now();
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
const res = await client.post(endpoint, json);
|
||||
const afterTime = Date.now();
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = await getWarning(warnedUserOnePublicID);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 0
|
||||
};
|
||||
assert.ok(partialDeepEquals(data, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
// check disableTime
|
||||
assert.ok(row[0].disableTime >= beforeTime && row[0].disableTime <= afterTime, "expected disableTime to be somewhere between execution start and end");
|
||||
});
|
||||
|
||||
it("Should not be able to add your own warning", (done) => {
|
||||
it("Should not be able to create warning if not vip (exp 403)", async () => {
|
||||
const json = {
|
||||
userID: warneduserOneID,
|
||||
enabled: true
|
||||
issuerUserID: users.nonvip.private,
|
||||
userID: users.u5.public,
|
||||
reason: "warn reason 5",
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 403);
|
||||
const data = await getWarning(warnedUserOnePublicID);
|
||||
});
|
||||
|
||||
it("Should return 400 if missing body", async () => {
|
||||
const res = await client.post(endpoint, {});
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
it("Should be able to remove your own warning", async () => {
|
||||
const json = {
|
||||
userID: users.u6.private,
|
||||
enabled: false
|
||||
};
|
||||
const beforeTime = Date.now();
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
const afterTime = Date.now();
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(users.u6.public);
|
||||
const expected = {
|
||||
enabled: 0
|
||||
};
|
||||
assert.ok(partialDeepEquals(data, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
// check disableTime
|
||||
assert.ok(row[0].disableTime >= beforeTime && row[0].disableTime <= afterTime, "expected disableTime to be somewhere between execution start and end");
|
||||
});
|
||||
|
||||
it("Should not be able to warn a user without reason", (done) => {
|
||||
it("Should not be able to add your own warning", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserTwoPublicID,
|
||||
userID: users.u7.private,
|
||||
enabled: true,
|
||||
reason: "warn reason 7",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 403);
|
||||
const data = await getWarning(users.u7.public);
|
||||
assert.equal(data.length, 0);
|
||||
});
|
||||
|
||||
it("Should not be able to warn a user without reason", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u8.public,
|
||||
enabled: true
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to re-warn a user without reason", (done) => {
|
||||
it("Should not be able to re-warn a user without reason", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u9.public,
|
||||
enabled: true
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = await getWarning(warnedUserOnePublicID);
|
||||
const expected = {
|
||||
enabled: 1
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
it("Should be able to edit a warning if within deadline and same vip", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u10.public,
|
||||
enabled: true,
|
||||
reason: "edited reason 10",
|
||||
};
|
||||
assert.ok(partialDeepEquals(data, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: json.reason,
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should not be able to edit a warning if within deadline and different vip", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u11.public,
|
||||
enabled: true,
|
||||
reason: "edited reason 11",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 409);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "warn reason 11",
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should be able to warn a previously warned user again (same vip)", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u12.public,
|
||||
enabled: true,
|
||||
reason: "new reason 12",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = [
|
||||
{
|
||||
enabled: 0,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "warn reason 12",
|
||||
},
|
||||
{
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "new reason 12",
|
||||
}
|
||||
];
|
||||
assert.equal(row.length, 2);
|
||||
assert.ok(partialDeepEquals(row[0], expected[0]), "warning 1");
|
||||
assert.ok(partialDeepEquals(row[1], expected[1]), "warning 2");
|
||||
});
|
||||
|
||||
it("Should be able to warn a previously warned user again (different vip)", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u13.public,
|
||||
enabled: true,
|
||||
reason: "new reason 13",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = [
|
||||
{
|
||||
enabled: 0,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "warn reason 13",
|
||||
},
|
||||
{
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip2.public,
|
||||
reason: "new reason 13",
|
||||
}
|
||||
];
|
||||
assert.equal(row.length, 2);
|
||||
assert.ok(partialDeepEquals(row[0], expected[0]), "warning 1");
|
||||
assert.ok(partialDeepEquals(row[1], expected[1]), "warning 2");
|
||||
});
|
||||
|
||||
it("Disabling a warning should only set disableTime for the active warning", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u14.public,
|
||||
enabled: false,
|
||||
};
|
||||
const beforeTime = Date.now();
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
const afterTime = Date.now();
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = [
|
||||
{
|
||||
enabled: 0,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "warn reason 14",
|
||||
disableTime: 12345,
|
||||
},
|
||||
{
|
||||
enabled: 0,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "another reason 14",
|
||||
}
|
||||
];
|
||||
assert.equal(row.length, 2);
|
||||
assert.ok(partialDeepEquals(row[0], expected[0]), "warning 1");
|
||||
assert.ok(partialDeepEquals(row[1], expected[1]), "warning 2");
|
||||
// check disableTime
|
||||
assert.ok(row[1].disableTime >= beforeTime && row[1].disableTime <= afterTime, "expected disableTime to be somewhere between execution start and end");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,44 +9,32 @@ const randKey2 = genRandom(16);
|
||||
const randKey3 = genRandom();
|
||||
const randValue3 = genRandom();
|
||||
|
||||
const redisGetCheck = (key: string, expected: string | null, done: Mocha.Done): Promise<void> =>
|
||||
redis.get(key)
|
||||
.then(res => {
|
||||
assert.strictEqual(res, expected);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
|
||||
describe("redis test", function() {
|
||||
before(async function() {
|
||||
if (!config.redis?.enabled) this.skip();
|
||||
await redis.set(randKey1, randValue1);
|
||||
});
|
||||
it("Should get stored value", (done) => {
|
||||
redisGetCheck(randKey1, randValue1, done);
|
||||
it("Should get stored value", async () => {
|
||||
const res = await redis.get(randKey1);
|
||||
assert.strictEqual(res, randValue1);
|
||||
});
|
||||
it("Should not be able to get not stored value", (done) => {
|
||||
redis.get(randKey2)
|
||||
.then(res => {
|
||||
if (res) done("Value should not be found");
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
it("Should not be able to get not stored value", async () => {
|
||||
const res = await redis.get(randKey2);
|
||||
assert.strictEqual(res, null, "Value should not be found");
|
||||
});
|
||||
it("Should be able to delete stored value", (done) => {
|
||||
redis.del(randKey1)
|
||||
.catch(err => done(err))
|
||||
.then(() => redisGetCheck(randKey1, null, done));
|
||||
it("Should be able to delete stored value", async () => {
|
||||
await redis.del(randKey1);
|
||||
const res = await redis.get(randKey1);
|
||||
assert.strictEqual(res, null, "Deleted key should not be found");
|
||||
});
|
||||
it("Should be able to set expiring value", (done) => {
|
||||
redis.setEx(randKey3, 8400, randValue3)
|
||||
.catch(err => done(err))
|
||||
.then(() => redisGetCheck(randKey3, randValue3, done));
|
||||
it("Should be able to set expiring value", async () => {
|
||||
await redis.setEx(randKey3, 8400, randValue3);
|
||||
const res = await redis.get(randKey3);
|
||||
assert.strictEqual(res, randValue3);
|
||||
});
|
||||
it("Should continue when undefined value is fetched", (done) => {
|
||||
it("Should continue when undefined value is fetched", async () => {
|
||||
const undefkey = `undefined.${genRandom()}`;
|
||||
redis.get(undefkey)
|
||||
.then(result => {
|
||||
assert.ok(!result); // result should be falsy
|
||||
done();
|
||||
});
|
||||
const res = await redis.get(undefkey);
|
||||
assert.strictEqual(res, null);
|
||||
});
|
||||
});
|
||||
@@ -56,12 +56,11 @@ function wellFormatUserName(userName: string) {
|
||||
return userName.replace(/[\u0000-\u001F\u007F-\u009F]/g, "");
|
||||
}
|
||||
|
||||
async function testUserNameChangelog(userID: string, newUserName: string, oldUserName: string, byAdmin: boolean, done: Mocha.Done) {
|
||||
async function testUserNameChangelog(userID: string, newUserName: string, oldUserName: string, byAdmin: boolean) {
|
||||
const log = await getLastLogUserNameChange(userID);
|
||||
assert.strictEqual(newUserName, log.newUserName);
|
||||
assert.strictEqual(oldUserName, log.oldUserName);
|
||||
assert.strictEqual(byAdmin, Boolean(log.updatedByAdmin));
|
||||
return done();
|
||||
}
|
||||
|
||||
const endpoint = "/api/setUsername";
|
||||
@@ -111,147 +110,104 @@ describe("setUsername", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("Should be able to set username that has never been set", (done) => {
|
||||
postSetUserName(user00PrivateUserID, username00)
|
||||
.then(async res => {
|
||||
it("Should be able to set username that has never been set", async () => {
|
||||
const res = await postSetUserName(user00PrivateUserID, username00);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user00PrivateUserID));
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(usernameInfo.userName, username00);
|
||||
assert.notStrictEqual(usernameInfo.locked, 1, "username should not be locked");
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it("Should return 200", (done) => {
|
||||
it("Should return 200", async () => {
|
||||
const username = "Changed%20Username";
|
||||
postSetUserName(user01PrivateUserID, username)
|
||||
.then(res => {
|
||||
const res = await postSetUserName(user01PrivateUserID, username);
|
||||
assert.strictEqual(res.status, 200);
|
||||
testUserNameChangelog(user01PrivateUserID, username, username01, false, done);
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
await testUserNameChangelog(user01PrivateUserID, username, username01, false);
|
||||
});
|
||||
|
||||
it('Should return 400 for missing param "userID"', (done) => {
|
||||
client({
|
||||
it('Should return 400 for missing param "userID"', async () => {
|
||||
const res = await client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
data: {
|
||||
userName: "MyUsername"
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
});
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it('Should return 400 for missing param "username"', (done) => {
|
||||
client({
|
||||
it('Should return 400 for missing param "username"', async () => {
|
||||
const res = await client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
data: {
|
||||
userID: "test"
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
});
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it('Should return 400 for "username" longer then 64 characters', (done) => {
|
||||
it('Should return 400 for "username" longer then 64 characters', async () => {
|
||||
const username65 = "0000000000000000000000000000000000000000000000000000000000000000X";
|
||||
postSetUserName("test", username65)
|
||||
.then(res => {
|
||||
const res = await postSetUserName("test", username65);
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it('Should not change username if it contains "discord"', (done) => {
|
||||
it('Should not change username if it contains "discord"', async () => {
|
||||
const newUsername = "discord.me";
|
||||
postSetUserName(user02PrivateUserID, newUsername)
|
||||
.then(async res => {
|
||||
const res = await postSetUserName(user02PrivateUserID, newUsername);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const userNameInfo = await getUsernameInfo(getHash(user02PrivateUserID));
|
||||
assert.notStrictEqual(userNameInfo.userName, newUsername);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to change username", (done) => {
|
||||
it("Should be able to change username", async () => {
|
||||
const newUsername = "newUsername";
|
||||
postSetUserName(user03PrivateUserID, newUsername)
|
||||
.then(async () => {
|
||||
await postSetUserName(user03PrivateUserID, newUsername);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user03PrivateUserID));
|
||||
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((err) => done(err));
|
||||
await testUserNameChangelog(user03PrivateUserID, newUsername, username03, false);
|
||||
});
|
||||
|
||||
it("Should not be able to change locked username", (done) => {
|
||||
it("Should not be able to change locked username", async () => {
|
||||
const newUsername = "newUsername";
|
||||
postSetUserName(user04PrivateUserID, newUsername)
|
||||
.then(async () => {
|
||||
await postSetUserName(user04PrivateUserID, newUsername);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user04PrivateUserID));
|
||||
assert.notStrictEqual(usernameInfo.userName, newUsername, "Username should not be changed");
|
||||
assert.strictEqual(usernameInfo.locked, 1, "username should be locked");
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it("Should filter out unicode control characters", (done) => {
|
||||
it("Should filter out unicode control characters", async () => {
|
||||
const newUsername = "This\nUsername+has\tInvalid+Characters";
|
||||
postSetUserName(user05PrivateUserID, newUsername)
|
||||
.then(async () => {
|
||||
await postSetUserName(user05PrivateUserID, newUsername);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user05PrivateUserID));
|
||||
assert.notStrictEqual(usernameInfo.userName, newUsername, "Username should not contain control characters");
|
||||
testUserNameChangelog(user05PrivateUserID, wellFormatUserName(newUsername), username05, false, done);
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
await testUserNameChangelog(user05PrivateUserID, wellFormatUserName(newUsername), username05, false);
|
||||
});
|
||||
|
||||
it("Incorrect adminUserID should return 403", (done) => {
|
||||
it("Incorrect adminUserID should return 403", async () => {
|
||||
const newUsername = "New Username";
|
||||
postSetUserNameAdmin(getHash(user06PrivateUserID), newUsername,"invalidAdminID")
|
||||
.then(res => {
|
||||
const res = await postSetUserNameAdmin(getHash(user06PrivateUserID), newUsername,"invalidAdminID");
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it("Admin should be able to change username", (done) => {
|
||||
it("Admin should be able to change username", async () => {
|
||||
const newUsername = "New Username";
|
||||
postSetUserNameAdmin(getHash(user06PrivateUserID), newUsername, adminPrivateUserID)
|
||||
.then(async () => {
|
||||
await postSetUserNameAdmin(getHash(user06PrivateUserID), newUsername, adminPrivateUserID);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user06PrivateUserID));
|
||||
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((err) => done(err));
|
||||
await testUserNameChangelog(user06PrivateUserID, newUsername, username06, true);
|
||||
});
|
||||
|
||||
it("Admin should be able to change locked username", (done) => {
|
||||
it("Admin should be able to change locked username", async () => {
|
||||
const newUsername = "New Username";
|
||||
postSetUserNameAdmin(getHash(user07PrivateUserID), newUsername, adminPrivateUserID)
|
||||
.then(async () => {
|
||||
await postSetUserNameAdmin(getHash(user07PrivateUserID), newUsername, adminPrivateUserID);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user06PrivateUserID));
|
||||
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((err) => done(err));
|
||||
await testUserNameChangelog(user07PrivateUserID, newUsername, username07, true);
|
||||
});
|
||||
|
||||
it("Should delete existing username if new username is same as publicID", async () => {
|
||||
|
||||
@@ -59,71 +59,47 @@ describe("setUsernamePrivate tests", () => {
|
||||
before(() => sinon.stub(config, "minUserIDLength").value(USERID_LIMIT));
|
||||
after(() => sinon.restore());
|
||||
|
||||
it("Existing privateID = username under Limit should retreive successfully", (done) => {
|
||||
it("Existing privateID = username under Limit should retreive successfully", async () => {
|
||||
const privateID = preExisting_underLimit;
|
||||
hasSetUsername(getHash(privateID))
|
||||
.then((usernameInfo) => {
|
||||
assert.ok(usernameInfo);
|
||||
done();
|
||||
});
|
||||
assert.ok(await hasSetUsername(getHash(privateID)));
|
||||
});
|
||||
|
||||
it("Existing privateID = username over Limit should retreive successfully", (done) => {
|
||||
it("Existing privateID = username over Limit should retreive successfully", async () => {
|
||||
const privateID = preExisting_overLimit;
|
||||
hasSetUsername(getHash(privateID))
|
||||
.then((usernameInfo) => {
|
||||
assert.ok(usernameInfo);
|
||||
done();
|
||||
});
|
||||
assert.ok(await hasSetUsername(getHash(privateID)));
|
||||
});
|
||||
|
||||
it("Should return error if trying to set userID = username under limit", (done) => {
|
||||
it("Should return error if trying to set userID = username under limit", async () => {
|
||||
const privateID = newUser_underLimit;
|
||||
postSetUserName(privateID, privateID)
|
||||
.then(async (res) => {
|
||||
const res = await postSetUserName(privateID, privateID);
|
||||
assert.strictEqual(res.status, 400);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(!usernameInfo);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it("Should return error if trying to set username = other privateID over limit", (done) => {
|
||||
it("Should return error if trying to set username = other privateID over limit", async () => {
|
||||
const privateID = newUser_overLimit;
|
||||
postSetUserName(privateID, privateID)
|
||||
.then(async (res) => {
|
||||
const res = await postSetUserName(privateID, privateID);
|
||||
assert.strictEqual(res.status, 400);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(!usernameInfo);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it("Should return error if trying to set username = other privateID over limit", (done) => {
|
||||
it("Should return error if trying to set username = other privateID over limit", async () => {
|
||||
const privateID = otherUser;
|
||||
const otherUserPrivate = preExisting_overLimit;
|
||||
postSetUserName(privateID, otherUserPrivate)
|
||||
.then(async (res) => {
|
||||
const res = await postSetUserName(privateID, otherUserPrivate);
|
||||
assert.strictEqual(res.status, 400);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(!usernameInfo);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
|
||||
it("Should not return error if trying to set username = other privateID under limit", (done) => {
|
||||
it("Should not return error if trying to set username = other privateID under limit", async () => {
|
||||
const privateID = otherUser;
|
||||
const otherUserPrivate = preExisting_underLimit;
|
||||
postSetUserName(privateID, otherUserPrivate)
|
||||
.then(async (res) => {
|
||||
const res = await postSetUserName(privateID, otherUserPrivate);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(usernameInfo);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { db, privateDB } from "../../src/databases/databases";
|
||||
import { db } from "../../src/databases/databases";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import assert from "assert";
|
||||
import { Category, Service } from "../../src/types/segments.model";
|
||||
|
||||
@@ -68,37 +68,23 @@ describe("tempVIP test", function() {
|
||||
await redis.del(tempVIPKey(publicTempVIPOne));
|
||||
});
|
||||
|
||||
it("Should update db version when starting the application", () => {
|
||||
privateDB.prepare("get", "SELECT key, value FROM config where key = ?", ["version"])
|
||||
.then(row => {
|
||||
it("Should update db version when starting the application", async () => {
|
||||
const row = await privateDB.prepare("get", "SELECT key, value FROM config where key = ?", ["version"]);
|
||||
assert.ok(row.value >= 5, `Versions are not at least 5. private is ${row.value}`);
|
||||
});
|
||||
});
|
||||
it("User should not already be temp VIP", (done) => {
|
||||
checkUserVIP(publicTempVIPOne)
|
||||
.then(result => {
|
||||
assert.ok(!result);
|
||||
})
|
||||
.then(async () => {
|
||||
it("User should not already be temp VIP", async () => {
|
||||
assert.ok(!await checkUserVIP(publicTempVIPOne));
|
||||
const row = await privateDB.prepare("get", `SELECT * FROM "tempVipLog" WHERE "targetUserID" = ?`, [publicTempVIPOne]);
|
||||
assert.ok(!row?.enabled);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should be able to normal upvote as a user", (done) => {
|
||||
postVote(tempVIPOne, UUID0, 1)
|
||||
.then(async res => {
|
||||
it("Should be able to normal upvote as a user", async () => {
|
||||
const res = await postVote(tempVIPOne, UUID0, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.votes, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should be able to add tempVIP", (done) => {
|
||||
addTempVIP("true", permVIP1, publicTempVIPOne)
|
||||
.then(async res => {
|
||||
it("Should be able to add tempVIP", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 200);
|
||||
// check redis
|
||||
const vip = await checkUserVIP(publicTempVIPOne);
|
||||
@@ -107,152 +93,93 @@ describe("tempVIP test", function() {
|
||||
// check privateDB
|
||||
const row = await privateDB.prepare("get", `SELECT * FROM "tempVipLog" WHERE "targetUserID" = ?`, [publicTempVIPOne]);
|
||||
assert.ok(row.enabled);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should be able to VIP downvote", (done) => {
|
||||
postVote(tempVIPOne, UUID0, 0)
|
||||
.then(async res => {
|
||||
it("Should be able to VIP downvote", async () => {
|
||||
const res = await postVote(tempVIPOne, UUID0, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.votes, -2);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should not be able to lock segment", (done) => {
|
||||
postVote(tempVIPOne, UUID0, 1)
|
||||
.then(async res => {
|
||||
it("Should not be able to lock segment", async () => {
|
||||
const res = await postVote(tempVIPOne, UUID0, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.votes, 1);
|
||||
assert.strictEqual(row.locked, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should be able to change category but not lock", (done) => {
|
||||
postVoteCategory(tempVIPOne, UUID0, "filler")
|
||||
.then(async res => {
|
||||
it("Should be able to change category but not lock", async () => {
|
||||
const res = await postVoteCategory(tempVIPOne, UUID0, "filler");
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.category, "filler");
|
||||
assert.strictEqual(row.locked, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should be able to remove tempVIP prematurely", (done) => {
|
||||
addTempVIP("false", permVIP1, publicTempVIPOne)
|
||||
.then(async res => {
|
||||
it("Should be able to remove tempVIP prematurely", async () => {
|
||||
const res = await addTempVIP("false", permVIP1, publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const vip = await checkUserVIP(publicTempVIPOne);
|
||||
assert.strictEqual(res.data, "Temp VIP removed");
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should not be able to VIP downvote", (done) => {
|
||||
postVote(tempVIPOne, UUID1, 0)
|
||||
.then(async res => {
|
||||
it("Should not be able to VIP downvote", async () => {
|
||||
const res = await postVote(tempVIPOne, UUID1, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID1);
|
||||
assert.strictEqual(row.votes, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should not be able to VIP change category", (done) => {
|
||||
postVoteCategory(tempVIPOne, UUID1, "filler")
|
||||
.then(async res => {
|
||||
it("Should not be able to VIP change category", async () => {
|
||||
const res = await postVoteCategory(tempVIPOne, UUID1, "filler");
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID1);
|
||||
assert.strictEqual(row.category, "sponsor");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
// error code testing
|
||||
it("Should be able to add tempVIP after removal", (done) => {
|
||||
addTempVIP("true", permVIP1, publicTempVIPOne)
|
||||
.then(async res => {
|
||||
it("Should be able to add tempVIP after removal", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const vip = await checkUserVIP(publicTempVIPOne);
|
||||
assert.strictEqual(vip, "ChannelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should not be able to add VIP without existing VIP (403)", (done) => {
|
||||
it("Should not be able to add VIP without existing VIP (403)", async () => {
|
||||
const privateID = "non-vip-privateid";
|
||||
addTempVIP("true", privateID, publicTempVIPOne)
|
||||
.then(async res => {
|
||||
const res = await addTempVIP("true", privateID, publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 403);
|
||||
const vip = await checkUserVIP(getHash(privateID) as HashedUserID);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should not be able to add permanant VIP as temporary VIP (409)", (done) => {
|
||||
addTempVIP("true", permVIP1, publicPermVIP2)
|
||||
.then(async res => {
|
||||
it("Should not be able to add permanant VIP as temporary VIP (409)", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, publicPermVIP2);
|
||||
assert.strictEqual(res.status, 409);
|
||||
const vip = await checkUserVIP(publicPermVIP2);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Temp VIP should not be able to add another Temp VIP (403)", (done) => {
|
||||
it("Temp VIP should not be able to add another Temp VIP (403)", async () => {
|
||||
const privateID = "non-vip-privateid";
|
||||
const publicID = getHash(privateID) as HashedUserID;
|
||||
addTempVIP("true", tempVIPOne, publicID)
|
||||
.then(async res => {
|
||||
const res = await addTempVIP("true", tempVIPOne, publicID);
|
||||
assert.strictEqual(res.status, 403);
|
||||
const vip = await checkUserVIP(publicID);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
// error 40X testing
|
||||
it("Should return 404 with invalid videoID", (done) => {
|
||||
it("Should return 404 with invalid videoID", async () => {
|
||||
const privateID = "non-vip-privateid";
|
||||
const publicID = getHash(privateID) as HashedUserID;
|
||||
addTempVIP("true", permVIP1, publicID, "knownWrongID")
|
||||
.then(async res => {
|
||||
const res = await addTempVIP("true", permVIP1, publicID, "knownWrongID");
|
||||
assert.strictEqual(res.status, 404);
|
||||
const vip = await checkUserVIP(publicID);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should return 400 with invalid userID", (done) => {
|
||||
addTempVIP("true", permVIP1, "" as HashedUserID, "knownWrongID")
|
||||
.then(res => {
|
||||
it("Should return 400 with invalid userID", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, "" as HashedUserID, "knownWrongID");
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should return 400 with invalid adminUserID", (done) => {
|
||||
addTempVIP("true", "", publicTempVIPOne)
|
||||
.then(res => {
|
||||
it("Should return 400 with invalid adminUserID", async () => {
|
||||
const res = await addTempVIP("true", "", publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should return 400 with invalid channelID", (done) => {
|
||||
addTempVIP("true", permVIP1, publicTempVIPOne, "")
|
||||
.then(res => {
|
||||
it("Should return 400 with invalid channelID", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, publicTempVIPOne, "");
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
@@ -16,32 +16,24 @@ describe("tokenUtils test", function() {
|
||||
mock.onGet(/identity/).reply(200, patreon.activeIdentity);
|
||||
});
|
||||
|
||||
it("Should be able to create patreon token", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
tokenUtils.createAndSaveToken(tokenUtils.TokenType.patreon, "test_code").then((licenseKey) => {
|
||||
it("Should be able to create patreon token", async function () {
|
||||
if (!config?.patreon) return this.skip();
|
||||
const licenseKey = await tokenUtils.createAndSaveToken(tokenUtils.TokenType.patreon, "test_code");
|
||||
assert.ok(validateToken(licenseKey[0]));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to create local token", (done) => {
|
||||
tokenUtils.createAndSaveToken(tokenUtils.TokenType.local).then((licenseKey) => {
|
||||
it("Should be able to create local token", async () => {
|
||||
const licenseKey = await tokenUtils.createAndSaveToken(tokenUtils.TokenType.local);
|
||||
assert.ok(validateToken(licenseKey[0]));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to get patreon identity", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
tokenUtils.getPatreonIdentity("fake_access_token").then((result) => {
|
||||
it("Should be able to get patreon identity", async function () {
|
||||
if (!config?.patreon) return this.skip();
|
||||
const result = await tokenUtils.getPatreonIdentity("fake_access_token");
|
||||
assert.deepEqual(result, patreon.activeIdentity);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to refresh token", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
tokenUtils.refreshToken(tokenUtils.TokenType.patreon, "fake-licence-Key", "fake_refresh_token").then((result) => {
|
||||
it("Should be able to refresh token", async function () {
|
||||
if (!config?.patreon) return this.skip();
|
||||
const result = await tokenUtils.refreshToken(tokenUtils.TokenType.patreon, "fake-licence-Key", "fake_refresh_token");
|
||||
assert.strictEqual(result, true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
@@ -56,17 +48,13 @@ describe("tokenUtils failing tests", function() {
|
||||
mock.onGet(/identity/).reply(204, patreon.activeIdentity);
|
||||
});
|
||||
|
||||
it("Should fail if patreon is not correctly stubbed", function (done) {
|
||||
tokenUtils.createAndSaveToken(tokenUtils.TokenType.patreon, "test_code").then((licenseKey) => {
|
||||
it("Should fail if patreon is not correctly stubbed", async () => {
|
||||
const licenseKey = await tokenUtils.createAndSaveToken(tokenUtils.TokenType.patreon, "test_code");
|
||||
assert.strictEqual(licenseKey, null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail if token type is invalid", (done) => {
|
||||
tokenUtils.createAndSaveToken("invalidTokenType" as tokenUtils.TokenType).then((licenseKey) => {
|
||||
it("Should fail if token type is invalid", async () => {
|
||||
const licenseKey = await tokenUtils.createAndSaveToken("invalidTokenType" as tokenUtils.TokenType);
|
||||
assert.strictEqual(licenseKey, null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { config } from "../../src/config";
|
||||
import { db, privateDB } from "../../src/databases/databases";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { ImportMock } from "ts-mock-imports";
|
||||
@@ -26,8 +25,6 @@ describe("voteOnSponsorTime", () => {
|
||||
const warnUser01Hash = getHash("warn-voteuser01");
|
||||
const warnUser02Hash = getHash("warn-voteuser02");
|
||||
const categoryChangeUserHash = getHash(categoryChangeUser);
|
||||
const MILLISECONDS_IN_HOUR = 3600000;
|
||||
const warningExpireTime = MILLISECONDS_IN_HOUR * config.hoursAfterWarningExpires;
|
||||
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "actionType", "shadowHidden", "hidden") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
await db.prepare("run", insertSponsorTimeQuery, ["vote-testtesttest", 1, 11, 2, 0, "vote-uuid-0", "testman", 0, 50, "sponsor", "skip", 0, 0]);
|
||||
@@ -96,8 +93,6 @@ describe("voteOnSponsorTime", () => {
|
||||
await db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 2000), warnVip01Hash, 1]);
|
||||
await db.prepare("run", insertWarningQuery, [warnUser01Hash, (now - 3601000), warnVip01Hash, 1]);
|
||||
await db.prepare("run", insertWarningQuery, [warnUser02Hash, now, warnVip01Hash, 1]);
|
||||
await db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 1000)), warnVip01Hash, 1]);
|
||||
await db.prepare("run", insertWarningQuery, [warnUser02Hash, (now - (warningExpireTime + 2000)), warnVip01Hash, 1]);
|
||||
|
||||
|
||||
await db.prepare("run", 'INSERT INTO "vipUsers" ("userID") VALUES (?)', [getHash(vipUser)]);
|
||||
@@ -133,34 +128,25 @@ describe("voteOnSponsorTime", () => {
|
||||
const getSegmentCategory = (UUID: string) => db.prepare("get", `SELECT "category" FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]);
|
||||
const getPrivateVoteInfo = (UUID: string) => privateDB.prepare("all", `SELECT * FROM "votes" WHERE "UUID" = ?`, [UUID]);
|
||||
|
||||
it("Should be able to upvote a segment", (done) => {
|
||||
it("Should be able to upvote a segment", async () => {
|
||||
const UUID = "vote-uuid-0";
|
||||
postVote("randomID", UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote("randomID", UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 3);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to upvote a segment with a partial ID", (done) => {
|
||||
it("Should be able to upvote a segment with a partial ID", async () => {
|
||||
const UUID = "vote-u34113123";
|
||||
postVote("randomIDpartial", UUID.substring(0, 9), 1, "vote-testtesttest---sdaas")
|
||||
.then(async res => {
|
||||
const res = await postVote("randomIDpartial", UUID.substring(0, 9), 1, "vote-testtesttest---sdaas");
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 3);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to downvote a segment", (done) => {
|
||||
it("Should be able to downvote a segment", async () => {
|
||||
const UUID = "vote-uuid-2";
|
||||
postVote(randomID2, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(randomID2, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.ok(row.votes < 10);
|
||||
@@ -168,123 +154,83 @@ describe("voteOnSponsorTime", () => {
|
||||
assert.strictEqual(voteInfo.length, 1);
|
||||
assert.strictEqual(voteInfo[0].normalUserID, randomID2Hashed);
|
||||
assert.strictEqual(voteInfo[0].type, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to downvote the same segment when voting from a different user on the same IP", (done) => {
|
||||
it("Should not be able to downvote the same segment when voting from a different user on the same IP", async () => {
|
||||
const UUID = "vote-uuid-2";
|
||||
postVote("randomID3", UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote("randomID3", UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 9);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to downvote a segment if the user is shadow banned", (done) => {
|
||||
it("Should not be able to downvote a segment if the user is shadow banned", async () => {
|
||||
const UUID = "vote-uuid-1.6";
|
||||
postVote("randomID4", UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote("randomID4", UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 10);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to upvote a segment if the user hasn't submitted yet", (done) => {
|
||||
it("Should not be able to upvote a segment if the user hasn't submitted yet", async () => {
|
||||
const UUID = "vote-uuid-1";
|
||||
postVote("hasNotSubmittedID", UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote("hasNotSubmittedID", UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 2);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to downvote a segment if the user hasn't submitted yet", (done) => {
|
||||
it("Should not be able to downvote a segment if the user hasn't submitted yet", async () => {
|
||||
const UUID = "vote-uuid-1.5";
|
||||
postVote("hasNotSubmittedID", UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote("hasNotSubmittedID", UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 10);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("VIP should be able to completely downvote a segment", (done) => {
|
||||
it("VIP should be able to completely downvote a segment", async () => {
|
||||
const UUID = "vote-uuid-3";
|
||||
postVote(vipUser, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(vipUser, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.ok(row.votes <= -2);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("should be able to completely downvote your own segment (segment unlocked)", (done) => {
|
||||
it("should be able to completely downvote your own segment (segment unlocked)", async () => {
|
||||
const UUID = "own-submission-uuid";
|
||||
postVote("own-submission-id", UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote("own-submission-id", UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.ok(row.votes <= -2);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("should not be able to completely downvote somebody elses segment", (done) => {
|
||||
it("should not be able to completely downvote somebody elses segment", async () => {
|
||||
const UUID = "not-own-submission-uuid";
|
||||
postVote(randomID2, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(randomID2, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 499);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("should be able to completely downvote chapter using malicious", (done) => {
|
||||
it("should be able to completely downvote chapter using malicious", async () => {
|
||||
const UUID = "chapter-uuid-1";
|
||||
postVote(randomID2, UUID, 30)
|
||||
.then(async res => {
|
||||
const res = await postVote(randomID2, UUID, 30);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, -2);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("should not be able to completely downvote non-chapter using malicious", (done) => {
|
||||
it("should not be able to completely downvote non-chapter using malicious", async () => {
|
||||
const UUID = "non-chapter-uuid-2";
|
||||
postVote(randomID2, UUID, 30)
|
||||
.then(async res => {
|
||||
const res = await postVote(randomID2, UUID, 30);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to vote for a category and it should add your vote to the database", (done) => {
|
||||
it("Should be able to vote for a category and it should add your vote to the database", async () => {
|
||||
const UUID = "vote-uuid-4";
|
||||
postVoteCategory(randomID2, UUID, "intro")
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(randomID2, UUID, "intro");
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
const categoryRows = await db.prepare("all", `SELECT votes, category FROM "categoryVotes" WHERE "UUID" = ?`, [UUID]);
|
||||
@@ -294,51 +240,35 @@ describe("voteOnSponsorTime", () => {
|
||||
assert.strictEqual(categoryRows[0].category, "intro");
|
||||
assert.strictEqual(categoryRows[1].votes, 1);
|
||||
assert.strictEqual(categoryRows[1].category, "sponsor");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not able to change to an invalid category", (done) => {
|
||||
it("Should not able to change to an invalid category", async () => {
|
||||
const UUID = "incorrect-category";
|
||||
postVoteCategory(randomID2, UUID, "fakecategory")
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(randomID2, UUID, "fakecategory");
|
||||
assert.strictEqual(res.status, 400);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, "sponsor");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not able to change to highlight category", (done) => {
|
||||
it("Should not able to change to highlight category", async () => {
|
||||
const UUID = "incorrect-category";
|
||||
postVoteCategory(randomID2, UUID, "highlight")
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(randomID2, UUID, "highlight");
|
||||
assert.strictEqual(res.status, 400);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, "sponsor");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not able to change to chapter category", (done) => {
|
||||
it("Should not able to change to chapter category", async () => {
|
||||
const UUID = "incorrect-category";
|
||||
postVoteCategory(randomID2, UUID, "chapter")
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(randomID2, UUID, "chapter");
|
||||
assert.strictEqual(res.status, 400);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, "sponsor");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to change your vote for a category and it should add your vote to the database(segment unlocked, nextCatgeory unlocked)", (done) => {
|
||||
it("Should be able to change your vote for a category and it should add your vote to the database(segment unlocked, nextCatgeory unlocked)", async () => {
|
||||
const UUID = "vote-uuid-4";
|
||||
postVoteCategory(randomID2, UUID, "outro")
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(randomID2, UUID, "outro");
|
||||
assert.strictEqual(res.status, 200, "Status code should be 200");
|
||||
const submissionRow = await getSegmentCategory(UUID);
|
||||
const categoryRows = await db.prepare("all", `SELECT votes, category FROM "categoryVotes" WHERE "UUID" = ?`, [UUID]);
|
||||
@@ -355,352 +285,240 @@ describe("voteOnSponsorTime", () => {
|
||||
assert.strictEqual(introVotes, 0);
|
||||
assert.strictEqual(outroVotes, 1);
|
||||
assert.strictEqual(sponsorVotes, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
|
||||
it("Should not be able to change your vote to an invalid category", (done) => {
|
||||
it("Should not be able to change your vote to an invalid category", async () => {
|
||||
const UUID = "incorrect-category-change";
|
||||
const vote = (inputCat: string, assertCat: string, callback: Mocha.Done) => {
|
||||
postVoteCategory(randomID2, UUID, inputCat)
|
||||
.then(async () => {
|
||||
const vote = async (inputCat: string, assertCat: string) => {
|
||||
await postVoteCategory(randomID2, UUID, inputCat);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, assertCat);
|
||||
callback();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
};
|
||||
vote("sponsor", "sponsor", () => {
|
||||
vote("fakeCategory", "sponsor", done);
|
||||
});
|
||||
await vote("sponsor", "sponsor");
|
||||
await vote("fakeCategory", "sponsor");
|
||||
});
|
||||
|
||||
it("Submitter should be able to vote for a category and it should immediately change (segment unlocked, nextCatgeory unlocked, notVip)", (done) => {
|
||||
it("Submitter should be able to vote for a category and it should immediately change (segment unlocked, nextCatgeory unlocked, notVip)", async () => {
|
||||
const userID = categoryChangeUser;
|
||||
const UUID = "category-change-uuid-1";
|
||||
const category = "sponsor";
|
||||
postVoteCategory(userID, UUID, category)
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(userID, UUID, category);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, category);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Submitter's vote on the category should not work (segment locked, nextCatgeory unlocked, notVip)", (done) => {
|
||||
it("Submitter's vote on the category should not work (segment locked, nextCatgeory unlocked, notVip)", async () => {
|
||||
const userID = categoryChangeUser;
|
||||
const UUID = "category-change-uuid-2";
|
||||
const category = "sponsor";
|
||||
postVoteCategory(userID, UUID, category)
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(userID, UUID, category);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, "intro");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Submitter's vote on the category should not work (segment unlocked, nextCatgeory locked, notVip)", (done) => {
|
||||
it("Submitter's vote on the category should not work (segment unlocked, nextCatgeory locked, notVip)", async () => {
|
||||
const userID = categoryChangeUser;
|
||||
const UUID = "category-change-uuid-3";
|
||||
const category = "preview";
|
||||
postVoteCategory(userID, UUID, category)
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(userID, UUID, category);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, "intro");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Submitter's vote on the category should not work (segment locked, nextCatgeory locked, notVip)", (done) => {
|
||||
it("Submitter's vote on the category should not work (segment locked, nextCatgeory locked, notVip)", async () => {
|
||||
const userID = categoryChangeUser;
|
||||
const UUID = "category-change-uuid-4";
|
||||
const category = "preview";
|
||||
postVoteCategory(userID, UUID, category)
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(userID, UUID, category);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, "intro");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Vip should be able to vote for a category and it should immediately change (segment unlocked, nextCatgeory unlocked, Vip)", (done) => {
|
||||
it("Vip should be able to vote for a category and it should immediately change (segment unlocked, nextCatgeory unlocked, Vip)", async () => {
|
||||
const userID = vipUser;
|
||||
const UUID = "category-change-uuid-5";
|
||||
const category = "sponsor";
|
||||
postVoteCategory(userID, UUID, category)
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(userID, UUID, category);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, category);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Vip should be able to vote for a category and it should immediately change (segment locked, nextCatgeory unlocked, Vip)", (done) => {
|
||||
it("Vip should be able to vote for a category and it should immediately change (segment locked, nextCatgeory unlocked, Vip)", async () => {
|
||||
const userID = vipUser;
|
||||
const UUID = "category-change-uuid-6";
|
||||
const category = "sponsor";
|
||||
postVoteCategory(userID, UUID, category)
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(userID, UUID, category);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, category);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Vip should be able to vote for a category and it should immediately change (segment unlocked, nextCatgeory locked, Vip)", (done) => {
|
||||
it("Vip should be able to vote for a category and it should immediately change (segment unlocked, nextCatgeory locked, Vip)", async () => {
|
||||
const userID = vipUser;
|
||||
const UUID = "category-change-uuid-7";
|
||||
const category = "preview";
|
||||
postVoteCategory(userID, UUID, category)
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(userID, UUID, category);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, category);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Vip should be able to vote for a category and it should immediately change (segment locked, nextCatgeory locked, Vip)", (done) => {
|
||||
it("Vip should be able to vote for a category and it should immediately change (segment locked, nextCatgeory locked, Vip)", async () => {
|
||||
const userID = vipUser;
|
||||
const UUID = "category-change-uuid-8";
|
||||
const category = "preview";
|
||||
postVoteCategory(userID, UUID, category)
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory(userID, UUID, category);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, category);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to vote for a category of a segment (Too many warning)", (done) => {
|
||||
it("Should not be able to vote for a category of a segment (Too many warning)", async () => {
|
||||
const UUID = "category-warnvote-uuid-0";
|
||||
const category = "preview";
|
||||
postVoteCategory("warn-voteuser01", UUID, category)
|
||||
.then(res => {
|
||||
const res = await postVoteCategory("warn-voteuser01", UUID, category);
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to vote for a category as a shadowbanned user, but it shouldn't add your vote to the database", (done) => {
|
||||
it("Should be able to vote for a category as a shadowbanned user, but it shouldn't add your vote to the database", async () => {
|
||||
const UUID = "category-banvote-uuid-0";
|
||||
const category = "preview";
|
||||
postVoteCategory("randomID4", UUID, category)
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory("randomID4", UUID, category);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
const categoryRows = await db.prepare("all", `SELECT votes, category FROM "categoryVotes" WHERE "UUID" = ?`, [UUID]);
|
||||
assert.strictEqual(row.category, "intro");
|
||||
assert.strictEqual(categoryRows.length, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to category-vote on an invalid UUID submission", (done) => {
|
||||
it("Should not be able to category-vote on an invalid UUID submission", async () => {
|
||||
const UUID = "invalid-uuid";
|
||||
postVoteCategory("randomID3", UUID, "intro")
|
||||
.then(res => {
|
||||
const res = await postVoteCategory("randomID3", UUID, "intro");
|
||||
assert.strictEqual(res.status, 404);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to category-vote on a full video segment", (done) => {
|
||||
it("Should not be able to category-vote on a full video segment", async () => {
|
||||
const UUID = "full-video-uuid-1";
|
||||
postVoteCategory("randomID3", UUID, "selfpromo")
|
||||
.then(res => {
|
||||
const res = await postVoteCategory("randomID3", UUID, "selfpromo");
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('Non-VIP should not be able to upvote "dead" submission', (done) => {
|
||||
it('Non-VIP should not be able to upvote "dead" submission', async () => {
|
||||
const UUID = "vote-uuid-5";
|
||||
postVote(randomID2, UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote(randomID2, UUID, 1);
|
||||
assert.strictEqual(res.status, 403);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, -3);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('Non-VIP should not be able to downvote "dead" submission', (done) => {
|
||||
it('Non-VIP should not be able to downvote "dead" submission', async () => {
|
||||
const UUID = "vote-uuid-5";
|
||||
postVote(randomID2, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(randomID2, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, -3);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('VIP should be able to upvote "dead" submission', (done) => {
|
||||
it('VIP should be able to upvote "dead" submission', async () => {
|
||||
const UUID = "vote-uuid-5";
|
||||
postVote(vipUser, UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote(vipUser, UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.ok(row.votes > -3);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to upvote a segment (Too many warning)", (done) => {
|
||||
it("Should not be able to upvote a segment (Too many warning)", async () => {
|
||||
const UUID = "warnvote-uuid-0";
|
||||
postVote("warn-voteuser01", UUID, 1)
|
||||
.then(res => {
|
||||
const res = await postVote("warn-voteuser01", UUID, 1);
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Non-VIP should not be able to downvote on a segment with no-segments category", (done) => {
|
||||
it("Non-VIP should not be able to downvote on a segment with no-segments category", async () => {
|
||||
const UUID = "no-sponsor-segments-uuid-0";
|
||||
postVote("randomID", UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote("randomID", UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 2);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Non-VIP should be able to upvote on a segment with no-segments category", (done) => {
|
||||
it("Non-VIP should be able to upvote on a segment with no-segments category", async () => {
|
||||
const UUID = "no-sponsor-segments-uuid-0";
|
||||
postVote("randomID", UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote("randomID", UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 3);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Non-VIP should not be able to category vote on a segment with no-segments category", (done) => {
|
||||
it("Non-VIP should not be able to category vote on a segment with no-segments category", async () => {
|
||||
const UUID = "no-sponsor-segments-uuid-0";
|
||||
postVoteCategory("randomID", UUID, "outro")
|
||||
.then(async res => {
|
||||
const res = await postVoteCategory("randomID", UUID, "outro");
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentCategory(UUID);
|
||||
assert.strictEqual(row.category, "sponsor");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("VIP upvote should lock segment", (done) => {
|
||||
it("VIP upvote should lock segment", async () => {
|
||||
const UUID = "segment-locking-uuid-1";
|
||||
postVote(vipUser, UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote(vipUser, UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await db.prepare("get", `SELECT "locked" FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]);
|
||||
assert.strictEqual(row.locked, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("VIP downvote should unlock segment", (done) => {
|
||||
it("VIP downvote should unlock segment", async () => {
|
||||
const UUID = "segment-locking-uuid-1";
|
||||
postVote(vipUser, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(vipUser, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await db.prepare("get", `SELECT "locked" FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]);
|
||||
assert.strictEqual(row.locked, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("VIP upvote should unhide segment", (done) => {
|
||||
it("VIP upvote should unhide segment", async () => {
|
||||
const UUID = "segment-hidden-uuid-1";
|
||||
postVote(vipUser, UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote(vipUser, UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await db.prepare("get", `SELECT "hidden" FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]);
|
||||
assert.strictEqual(row.hidden, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to undo-vote a segment", (done) => {
|
||||
it("Should be able to undo-vote a segment", async () => {
|
||||
const UUID = "vote-uuid-2";
|
||||
postVote(randomID2, UUID, 20)
|
||||
.then(async res => {
|
||||
const res = await postVote(randomID2, UUID, 20);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 10);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to vote with type 10", (done) => {
|
||||
it("Should not be able to vote with type 10", async () => {
|
||||
const UUID = "segment-locking-uuid-1";
|
||||
postVote(vipUser, UUID, 10)
|
||||
.then(res => {
|
||||
const res = await postVote(vipUser, UUID, 10);
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to vote with type 11", (done) => {
|
||||
it("Should not be able to vote with type 11", async () => {
|
||||
const UUID = "segment-locking-uuid-1";
|
||||
postVote(vipUser, UUID, 11)
|
||||
.then(res => {
|
||||
const res = await postVote(vipUser, UUID, 11);
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to update stored videoDuration with VIP upvote", (done) => {
|
||||
it("Should be able to update stored videoDuration with VIP upvote", async () => {
|
||||
const UUID = "duration-update-uuid-1";
|
||||
postVote(vipUser, UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote(vipUser, UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const { videoDuration } = await db.prepare("get", `SELECT "videoDuration" FROM "sponsorTimes" WHERE "UUID" = ?`, [UUID]);
|
||||
assert.strictEqual(videoDuration, 500);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Should hide changed submission on any downvote", (done) => {
|
||||
it("Should hide changed submission on any downvote", async () => {
|
||||
const UUID = "duration-changed-uuid-3";
|
||||
const videoID = "duration-changed";
|
||||
postVote(randomID2, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(randomID2, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const hiddenSegments = await db.prepare("all", `SELECT "UUID" FROM "sponsorTimes" WHERE "videoID" = ? AND "hidden" = 1`, [videoID]);
|
||||
assert.strictEqual(hiddenSegments.length, 2);
|
||||
@@ -710,128 +528,86 @@ describe("voteOnSponsorTime", () => {
|
||||
"UUID": "duration-changed-uuid-2",
|
||||
}];
|
||||
arrayDeepEquals(hiddenSegments, expected);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Should be able to downvote segment with ajacent actionType lock", (done) => {
|
||||
it("Should be able to downvote segment with ajacent actionType lock", async () => {
|
||||
const UUID = "no-sponsor-segments-uuid-2";
|
||||
postVote(randomID2, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(randomID2, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Should not be able to revive full video segment as non-vip", (done) => {
|
||||
it("Should not be able to revive full video segment as non-vip", async () => {
|
||||
const UUID = "full-video-uuid-1";
|
||||
postVote("VIPUser", UUID, 0).then(() => {
|
||||
postVote("randomID3", UUID, 1)
|
||||
.then(async res => {
|
||||
await postVote("VIPUser", UUID, 0);
|
||||
const res = await postVote("randomID3", UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, -2);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
it("Should be able to upvote a segment if the user has submitted that in category", (done) => {
|
||||
it("Should be able to upvote a segment if the user has submitted that in category", async () => {
|
||||
const UUID = "testing-outro-skip-1";
|
||||
postVote(outroSubmitter, UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote(outroSubmitter, UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to downvote a segment if the user has submitted that in category", (done) => {
|
||||
it("Should be able to downvote a segment if the user has submitted that in category", async () => {
|
||||
const UUID = "testing-outro-skip-2";
|
||||
postVote(outroSubmitter, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(outroSubmitter, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, -1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to upvote a segment if the user has submitted that in category but different action", (done) => {
|
||||
it("Should be able to upvote a segment if the user has submitted that in category but different action", async () => {
|
||||
const UUID = "testing-outro-mute-1";
|
||||
postVote(outroSubmitter, UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote(outroSubmitter, UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to downvote a segment if the user has submitted that in category but different action", (done) => {
|
||||
it("Should be able to downvote a segment if the user has submitted that in category but different action", async () => {
|
||||
const UUID = "testing-outro-mute-2";
|
||||
postVote(outroSubmitter, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(outroSubmitter, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, -1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to upvote a segment if the user's only submission of that category was downvoted", (done) => {
|
||||
it("Should not be able to upvote a segment if the user's only submission of that category was downvoted", async () => {
|
||||
const UUID = "testing-intro-skip-1";
|
||||
postVote(badIntroSubmitter, UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote(badIntroSubmitter, UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to downvote a segment if the user's only submission of that category was downvoted", (done) => {
|
||||
it("Should not be able to downvote a segment if the user's only submission of that category was downvoted", async () => {
|
||||
const UUID = "testing-intro-skip-2";
|
||||
postVote(badIntroSubmitter, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(badIntroSubmitter, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to upvote a segment if the user's only submission of that category was hidden", (done) => {
|
||||
it("Should not be able to upvote a segment if the user's only submission of that category was hidden", async () => {
|
||||
const UUID = "testing-interaction-skip-1";
|
||||
postVote(hiddenInteractionSubmitter, UUID, 1)
|
||||
.then(async res => {
|
||||
const res = await postVote(hiddenInteractionSubmitter, UUID, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to downvote a segment if the user's only submission of that category was hidden", (done) => {
|
||||
it("Should not be able to downvote a segment if the user's only submission of that category was hidden", async () => {
|
||||
const UUID = "testing-interaction-skip-2";
|
||||
postVote(hiddenInteractionSubmitter, UUID, 0)
|
||||
.then(async res => {
|
||||
const res = await postVote(hiddenInteractionSubmitter, UUID, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegmentVotes(UUID);
|
||||
assert.strictEqual(row.votes, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -59,12 +59,13 @@ async function init() {
|
||||
mocha.run((failures) => {
|
||||
mockServer.close();
|
||||
server.close();
|
||||
redis.quit();
|
||||
redis.quit().finally(() => {
|
||||
process.exitCode = failures ? 1 : 0; // exit with non-zero status if there were failures
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
void init();
|
||||
|
||||
51
test/utils/randomUsers.ts
Normal file
51
test/utils/randomUsers.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { HashedUserID, UserID } from "../../src/types/user.model";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { genRandom } from "./getRandom";
|
||||
|
||||
export interface TestUser {
|
||||
private: UserID,
|
||||
public: HashedUserID,
|
||||
}
|
||||
|
||||
interface InternalTestUsers {
|
||||
map: Map<any, TestUser>,
|
||||
suiteName: string,
|
||||
}
|
||||
|
||||
const userMapHandler = {
|
||||
get(target: InternalTestUsers, property: string): TestUser {
|
||||
const suiteName = Reflect.get(target, "suiteName");
|
||||
const map = Reflect.get(target, "map");
|
||||
let user = map.get(property);
|
||||
if (user !== undefined) {
|
||||
return user;
|
||||
}
|
||||
|
||||
const priv = `${suiteName}-${property}-${genRandom}` as UserID;
|
||||
user = {
|
||||
private: priv,
|
||||
public: getHash(priv),
|
||||
};
|
||||
map.set(property, user);
|
||||
return user;
|
||||
},
|
||||
set: () => false, // nope
|
||||
deleteProperty: () => false, // nope
|
||||
has: () => true, // yep
|
||||
defineProperty: () => false, // nope
|
||||
preventExtensions: () => false, // nope
|
||||
setPrototypeOf: () => false, // nope
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an object that generates test private/public userID pairs on demand
|
||||
*
|
||||
* @param suiteName the suite name, used as a prefix for the private userID
|
||||
* @returns a proxy that generates & caches private/public userID pairs for each property access
|
||||
*/
|
||||
export function usersForSuite(suiteName: string): Record<any, TestUser> {
|
||||
return new Proxy({
|
||||
map: new Map<any, TestUser>(),
|
||||
suiteName,
|
||||
}, userMapHandler) as unknown as Record<any, TestUser>;
|
||||
}
|
||||
4
tsconfig.eslint.json
Normal file
4
tsconfig.eslint.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["**/*"],
|
||||
}
|
||||
Reference in New Issue
Block a user