mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2024-11-10 01:02:30 +01:00
Allow auto banning ips
This commit is contained in:
parent
5426ae826e
commit
d5c544f1ee
2 changed files with 164 additions and 84 deletions
|
@ -17,6 +17,10 @@ export async function shadowBanUser(req: Request, res: Response): Promise<Respon
|
|||
const enabled = req.query.enabled === undefined
|
||||
? true
|
||||
: req.query.enabled === "true";
|
||||
const lookForIPs = req.query.lookForIPs === "true";
|
||||
const banUsers = req.query.banUsers === undefined
|
||||
? true
|
||||
: req.query.banUsers === "true";
|
||||
|
||||
//if enabled is false and the old submissions should be made visible again
|
||||
const unHideOldSubmissions = req.query.unHideOldSubmissions !== "false";
|
||||
|
@ -38,93 +42,118 @@ export async function shadowBanUser(req: Request, res: Response): Promise<Respon
|
|||
}
|
||||
|
||||
if (userID) {
|
||||
//check to see if this user is already shadowbanned
|
||||
const row = await db.prepare("get", `SELECT count(*) as "userCount" FROM "shadowBannedUsers" WHERE "userID" = ?`, [userID]);
|
||||
const result = await banUser(userID, enabled, unHideOldSubmissions, type, categories);
|
||||
if (result) {
|
||||
res.sendStatus(result);
|
||||
}
|
||||
|
||||
if (enabled && row.userCount == 0) {
|
||||
//add them to the shadow ban list
|
||||
if (enabled && lookForIPs) {
|
||||
const ipLoggingFixedTime = 1674590916069;
|
||||
const timeSubmitted = (await db.prepare("all", `SELECT "timeSubmitted" FROM "sponsorTimes" WHERE "timeSubmitted" > ? AND "userID" = ?`, [ipLoggingFixedTime, userID])) as { timeSubmitted: number }[];
|
||||
const ips = (await Promise.all(timeSubmitted.map((s) => {
|
||||
return privateDB.prepare("all", `SELECT "hashedIP" FROM "sponsorTimes" WHERE "timeSubmitted" = ?`, [s.timeSubmitted]) as Promise<{ hashedIP: HashedIP }[]>;
|
||||
}))).flat();
|
||||
|
||||
//add it to the table
|
||||
await db.prepare("run", `INSERT INTO "shadowBannedUsers" VALUES(?)`, [userID]);
|
||||
|
||||
//find all previous submissions and hide them
|
||||
if (unHideOldSubmissions) {
|
||||
await unHideSubmissionsByUser(categories, userID, type);
|
||||
}
|
||||
} else if (!enabled && row.userCount > 0) {
|
||||
//remove them from the shadow ban list
|
||||
await db.prepare("run", `DELETE FROM "shadowBannedUsers" WHERE "userID" = ?`, [userID]);
|
||||
|
||||
//find all previous submissions and unhide them
|
||||
if (unHideOldSubmissions) {
|
||||
const segmentsToIgnore = (await db.prepare("all", `SELECT "UUID" FROM "sponsorTimes" st
|
||||
JOIN "lockCategories" ns on "st"."videoID" = "ns"."videoID" AND st.category = ns.category AND "st"."service" = "ns"."service" WHERE "st"."userID" = ?`
|
||||
, [userID])).map((item: { UUID: string }) => item.UUID);
|
||||
const allSegments = (await db.prepare("all", `SELECT "UUID" FROM "sponsorTimes" st WHERE "st"."userID" = ?`, [userID]))
|
||||
.map((item: { UUID: string }) => item.UUID);
|
||||
|
||||
await Promise.all(allSegments.filter((item: { uuid: string }) => {
|
||||
return segmentsToIgnore.indexOf(item) === -1;
|
||||
}).map(async (UUID: string) => {
|
||||
// collect list for unshadowbanning
|
||||
(await db.prepare("all", `SELECT "videoID", "hashedVideoID", "service", "votes", "views", "userID" FROM "sponsorTimes" WHERE "UUID" = ? AND "shadowHidden" >= 1 AND "category" in (${categories.map((c) => `'${c}'`).join(",")})`, [UUID]))
|
||||
.forEach((videoInfo: { category: Category, videoID: VideoID, hashedVideoID: VideoIDHash, service: Service, userID: UserID }) => {
|
||||
QueryCacher.clearSegmentCache(videoInfo);
|
||||
}
|
||||
);
|
||||
|
||||
return db.prepare("run", `UPDATE "sponsorTimes" SET "shadowHidden" = 0 WHERE "UUID" = ? AND "category" in (${categories.map((c) => `'${c}'`).join(",")})`, [UUID]);
|
||||
}));
|
||||
}
|
||||
// already shadowbanned
|
||||
} else if (enabled && row.userCount > 0) {
|
||||
// apply unHideOldSubmissions if applicable
|
||||
if (unHideOldSubmissions) {
|
||||
await unHideSubmissionsByUser(categories, userID, type);
|
||||
return res.sendStatus(200);
|
||||
}
|
||||
|
||||
// otherwise ban already exists, send 409
|
||||
return res.sendStatus(409);
|
||||
await Promise.all(ips.map((ip) => {
|
||||
return banIP(ip.hashedIP, enabled, unHideOldSubmissions, type, categories, true);
|
||||
}));
|
||||
}
|
||||
} else if (hashedIP) {
|
||||
//check to see if this user is already shadowbanned
|
||||
const row = await db.prepare("get", `SELECT count(*) as "userCount" FROM "shadowBannedIPs" WHERE "hashedIP" = ?`, [hashedIP]);
|
||||
|
||||
if (enabled && row.userCount == 0) {
|
||||
//add them to the shadow ban list
|
||||
|
||||
//add it to the table
|
||||
await db.prepare("run", `INSERT INTO "shadowBannedIPs" VALUES(?)`, [hashedIP]);
|
||||
|
||||
//find all previous submissions and hide them
|
||||
if (unHideOldSubmissions) {
|
||||
await unHideSubmissionsByIP(categories, hashedIP, type);
|
||||
}
|
||||
} else if (!enabled) {
|
||||
if (row.userCount > 0) {
|
||||
//remove them from the shadow ban list
|
||||
await db.prepare("run", `DELETE FROM "shadowBannedIPs" WHERE "hashedIP" = ?`, [hashedIP]);
|
||||
}
|
||||
|
||||
//find all previous submissions and unhide them
|
||||
if (unHideOldSubmissions) {
|
||||
await unHideSubmissionsByIP(categories, hashedIP, "0");
|
||||
}
|
||||
} else if (enabled && row.userCount > 0) {
|
||||
// apply unHideOldSubmissions if applicable
|
||||
if (unHideOldSubmissions) {
|
||||
await unHideSubmissionsByIP(categories, hashedIP, type);
|
||||
return res.sendStatus(200);
|
||||
}
|
||||
|
||||
// otherwise ban already exists, send 409
|
||||
return res.sendStatus(409);
|
||||
const result = await banIP(hashedIP, enabled, unHideOldSubmissions, type, categories, banUsers);
|
||||
if (result) {
|
||||
res.sendStatus(result);
|
||||
}
|
||||
}
|
||||
return res.sendStatus(200);
|
||||
}
|
||||
|
||||
async function banUser(userID: UserID, enabled: boolean, unHideOldSubmissions: boolean, type: string, categories: Category[]): Promise<number> {
|
||||
//check to see if this user is already shadowbanned
|
||||
const row = await db.prepare("get", `SELECT count(*) as "userCount" FROM "shadowBannedUsers" WHERE "userID" = ?`, [userID]);
|
||||
|
||||
if (enabled && row.userCount == 0) {
|
||||
//add them to the shadow ban list
|
||||
|
||||
//add it to the table
|
||||
await db.prepare("run", `INSERT INTO "shadowBannedUsers" VALUES(?)`, [userID]);
|
||||
|
||||
//find all previous submissions and hide them
|
||||
if (unHideOldSubmissions) {
|
||||
await unHideSubmissionsByUser(categories, userID, type);
|
||||
}
|
||||
} else if (enabled && row.userCount > 0) {
|
||||
// apply unHideOldSubmissions if applicable
|
||||
if (unHideOldSubmissions) {
|
||||
await unHideSubmissionsByUser(categories, userID, type);
|
||||
} else {
|
||||
// otherwise ban already exists, send 409
|
||||
return 409;
|
||||
}
|
||||
} else if (!enabled && row.userCount > 0) {
|
||||
//remove them from the shadow ban list
|
||||
await db.prepare("run", `DELETE FROM "shadowBannedUsers" WHERE "userID" = ?`, [userID]);
|
||||
|
||||
//find all previous submissions and unhide them
|
||||
if (unHideOldSubmissions) {
|
||||
const segmentsToIgnore = (await db.prepare("all", `SELECT "UUID" FROM "sponsorTimes" st
|
||||
JOIN "lockCategories" ns on "st"."videoID" = "ns"."videoID" AND st.category = ns.category AND "st"."service" = "ns"."service" WHERE "st"."userID" = ?`
|
||||
, [userID])).map((item: { UUID: string }) => item.UUID);
|
||||
const allSegments = (await db.prepare("all", `SELECT "UUID" FROM "sponsorTimes" st WHERE "st"."userID" = ?`, [userID]))
|
||||
.map((item: { UUID: string }) => item.UUID);
|
||||
|
||||
await Promise.all(allSegments.filter((item: { uuid: string }) => {
|
||||
return segmentsToIgnore.indexOf(item) === -1;
|
||||
}).map(async (UUID: string) => {
|
||||
// collect list for unshadowbanning
|
||||
(await db.prepare("all", `SELECT "videoID", "hashedVideoID", "service", "votes", "views", "userID" FROM "sponsorTimes" WHERE "UUID" = ? AND "shadowHidden" >= 1 AND "category" in (${categories.map((c) => `'${c}'`).join(",")})`, [UUID]))
|
||||
.forEach((videoInfo: { category: Category, videoID: VideoID, hashedVideoID: VideoIDHash, service: Service, userID: UserID }) => {
|
||||
QueryCacher.clearSegmentCache(videoInfo);
|
||||
}
|
||||
);
|
||||
|
||||
return db.prepare("run", `UPDATE "sponsorTimes" SET "shadowHidden" = 0 WHERE "UUID" = ? AND "category" in (${categories.map((c) => `'${c}'`).join(",")})`, [UUID]);
|
||||
}));
|
||||
}
|
||||
// already shadowbanned
|
||||
}
|
||||
|
||||
return 200;
|
||||
}
|
||||
|
||||
async function banIP(hashedIP: HashedIP, enabled: boolean, unHideOldSubmissions: boolean, type: string, categories: Category[], banUsers: boolean): Promise<number> {
|
||||
//check to see if this user is already shadowbanned
|
||||
const row = await db.prepare("get", `SELECT count(*) as "userCount" FROM "shadowBannedIPs" WHERE "hashedIP" = ?`, [hashedIP]);
|
||||
|
||||
if (enabled) {
|
||||
if (row.userCount == 0) {
|
||||
await db.prepare("run", `INSERT INTO "shadowBannedIPs" VALUES(?)`, [hashedIP]);
|
||||
}
|
||||
|
||||
//find all previous submissions and hide them
|
||||
if (unHideOldSubmissions) {
|
||||
const users = await unHideSubmissionsByIP(categories, hashedIP, type);
|
||||
await Promise.all([...users].map((user) => {
|
||||
return banUser(user, enabled, unHideOldSubmissions, type, categories);
|
||||
}))
|
||||
} else if (row.userCount > 0) {
|
||||
// Nothing to do, and already added
|
||||
return 409;
|
||||
}
|
||||
} else if (!enabled) {
|
||||
if (row.userCount > 0) {
|
||||
//remove them from the shadow ban list
|
||||
await db.prepare("run", `DELETE FROM "shadowBannedIPs" WHERE "hashedIP" = ?`, [hashedIP]);
|
||||
}
|
||||
|
||||
//find all previous submissions and unhide them
|
||||
if (unHideOldSubmissions) {
|
||||
await unHideSubmissionsByIP(categories, hashedIP, "0");
|
||||
}
|
||||
}
|
||||
|
||||
return 200;
|
||||
}
|
||||
|
||||
async function unHideSubmissionsByUser(categories: string[], userID: UserID, type = "1") {
|
||||
if (!["1", "2"].includes(type)) return;
|
||||
|
||||
|
@ -139,15 +168,17 @@ async function unHideSubmissionsByUser(categories: string[], userID: UserID, typ
|
|||
});
|
||||
}
|
||||
|
||||
async function unHideSubmissionsByIP(categories: string[], hashedIP: HashedIP, type = "1") {
|
||||
async function unHideSubmissionsByIP(categories: string[], hashedIP: HashedIP, type = "1"): Promise<Set<UserID>> {
|
||||
if (!["0", "1", "2"].includes(type)) return;
|
||||
|
||||
const submissions = await privateDB.prepare("all", `SELECT "timeSubmitted" FROM "sponsorTimes" WHERE "hashedIP" = ?`, [hashedIP]) as { timeSubmitted: number }[];
|
||||
|
||||
const users: Set<UserID> = new Set();
|
||||
await Promise.all(submissions.map(async (submission) => {
|
||||
(await db.prepare("all", `SELECT "videoID", "hashedVideoID", "service", "votes", "views", "userID" FROM "sponsorTimes" WHERE "timeSubmitted" = ? AND "shadowHidden" >= 1 AND "category" in (${categories.map((c) => `'${c}'`).join(",")})`, [submission.timeSubmitted]))
|
||||
(await db.prepare("all", `SELECT "videoID", "hashedVideoID", "service", "votes", "views", "userID" FROM "sponsorTimes" WHERE "timeSubmitted" = ? AND "category" in (${categories.map((c) => `'${c}'`).join(",")})`, [submission.timeSubmitted]))
|
||||
.forEach((videoInfo: { category: Category, videoID: VideoID, hashedVideoID: VideoIDHash, service: Service, userID: UserID }) => {
|
||||
QueryCacher.clearSegmentCache(videoInfo);
|
||||
users.add(videoInfo.userID);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -155,4 +186,6 @@ async function unHideSubmissionsByIP(categories: string[], hashedIP: HashedIP, t
|
|||
AND NOT EXISTS ( SELECT "videoID", "category" FROM "lockCategories" WHERE
|
||||
"sponsorTimes"."videoID" = "lockCategories"."videoID" AND "sponsorTimes"."service" = "lockCategories"."service" AND "sponsorTimes"."category" = "lockCategories"."category")`, [submission.timeSubmitted]);
|
||||
}));
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
|
@ -41,6 +41,13 @@ describe("shadowBanUser", () => {
|
|||
await db.prepare("run", insertQuery, [video, 20, 10, 2, 0, "shadow-71", "shadowBanned7", 2332, 50, "intro", "YouTube", 0, videohash]);
|
||||
await db.prepare("run", insertQuery, [video, 20, 10, 2, 0, "shadow-72", "shadowBanned7", 4923, 50, "interaction", "YouTube", 0, videohash]);
|
||||
|
||||
await db.prepare("run", insertQuery, [video, 20, 10, 2, 0, "shadow-80", "shadowBanned8", 1674590916068933, 50, "sponsor", "YouTube", 0, videohash]);
|
||||
await db.prepare("run", insertQuery, [video, 20, 10, 2, 0, "shadow-81", "shadowBanned8", 1674590916062936, 50, "intro", "YouTube", 0, videohash]);
|
||||
await db.prepare("run", insertQuery, [video, 20, 10, 2, 0, "shadow-82", "shadowBanned8", 1674590916064324, 50, "interaction", "YouTube", 0, videohash]);
|
||||
await db.prepare("run", insertQuery, [video, 20, 10, 2, 0, "shadow-90", "shadowBanned9", 1674590916062443, 50, "sponsor", "YouTube", 0, videohash]);
|
||||
await db.prepare("run", insertQuery, [video, 20, 10, 2, 0, "shadow-91", "shadowBanned9", 1674590916062342, 50, "intro", "YouTube", 0, videohash]);
|
||||
await db.prepare("run", insertQuery, [video, 20, 10, 2, 0, "shadow-92", "shadowBanned9", 1674590916069491, 50, "interaction", "YouTube", 0, videohash]);
|
||||
|
||||
await db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, ["shadowBanned3"]);
|
||||
await db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, ["shadowBanned4"]);
|
||||
|
||||
|
@ -53,6 +60,13 @@ describe("shadowBanUser", () => {
|
|||
await privateDB.prepare("run", privateInsertQuery, [video, "shadowBannedIP7", 383848, "YouTube"]);
|
||||
await privateDB.prepare("run", privateInsertQuery, [video, "shadowBannedIP7", 2332, "YouTube"]);
|
||||
await privateDB.prepare("run", privateInsertQuery, [video, "shadowBannedIP7", 4923, "YouTube"]);
|
||||
|
||||
await privateDB.prepare("run", privateInsertQuery, [video, "shadowBannedIP8", 1674590916068933, "YouTube"]);
|
||||
await privateDB.prepare("run", privateInsertQuery, [video, "shadowBannedIP8", 1674590916062936, "YouTube"]);
|
||||
await privateDB.prepare("run", privateInsertQuery, [video, "shadowBannedIP8", 1674590916064324, "YouTube"]);
|
||||
await privateDB.prepare("run", privateInsertQuery, [video, "shadowBannedIP8", 1674590916062443, "YouTube"]);
|
||||
await privateDB.prepare("run", privateInsertQuery, [video, "shadowBannedIP8", 1674590916062342, "YouTube"]);
|
||||
await privateDB.prepare("run", privateInsertQuery, [video, "shadowBannedIP8", 1674590916069491, "YouTube"]);
|
||||
});
|
||||
|
||||
it("Should be able to ban user and hide submissions", (done) => {
|
||||
|
@ -336,7 +350,7 @@ describe("shadowBanUser", () => {
|
|||
const normalShadowRow = await getShadowBan(userID);
|
||||
const ipShadowRow = await getIPShadowBan(hashedIP);
|
||||
assert.ok(ipShadowRow);
|
||||
assert.ok(!normalShadowRow);
|
||||
assert.ok(normalShadowRow);
|
||||
assert.strictEqual(videoRow.length, 2);
|
||||
done();
|
||||
})
|
||||
|
@ -362,7 +376,7 @@ describe("shadowBanUser", () => {
|
|||
const normalShadowRow = await getShadowBan(userID);
|
||||
const ipShadowRow = await getIPShadowBan(hashedIP);
|
||||
assert.ok(!ipShadowRow);
|
||||
assert.ok(!normalShadowRow);
|
||||
assert.ok(normalShadowRow);
|
||||
assert.strictEqual(videoRow.length, 2);
|
||||
done();
|
||||
})
|
||||
|
@ -389,10 +403,43 @@ describe("shadowBanUser", () => {
|
|||
const normalShadowRow = await getShadowBan(userID);
|
||||
const ipShadowRow = await getIPShadowBan(hashedIP);
|
||||
assert.ok(!ipShadowRow);
|
||||
assert.ok(!normalShadowRow);
|
||||
assert.ok(normalShadowRow);
|
||||
assert.strictEqual(videoRow.length, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to ban user by userID and other users who used that IP and hide specific category", (done) => {
|
||||
const hashedIP = "shadowBannedIP8";
|
||||
const userID = "shadowBanned8";
|
||||
const userID2 = "shadowBanned9";
|
||||
client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
params: {
|
||||
userID,
|
||||
enabled: true,
|
||||
categories: `["sponsor", "intro"]`,
|
||||
unHideOldSubmissions: true,
|
||||
adminUserID: VIPuserID,
|
||||
lookForIPs: true
|
||||
}
|
||||
})
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const videoRow = await getShadowBanSegments(userID, 1);
|
||||
const videoRow2 = await getShadowBanSegments(userID2, 1);
|
||||
const normalShadowRow = await getShadowBan(userID);
|
||||
const normalShadowRow2 = await getShadowBan(userID2);
|
||||
const ipShadowRow = await getIPShadowBan(hashedIP);
|
||||
assert.ok(ipShadowRow);
|
||||
assert.ok(normalShadowRow);
|
||||
assert.ok(normalShadowRow2);
|
||||
assert.strictEqual(videoRow.length, 2);
|
||||
assert.strictEqual(videoRow2.length, 2);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue