mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-07 03:57:06 +03:00
Improve self downvoting for dearrow
This commit is contained in:
@@ -88,7 +88,7 @@ export async function postBranding(req: Request, res: Response) {
|
|||||||
|
|
||||||
await handleExistingVotes(BrandingType.Title, videoID, hashedUserID, UUID, hashedIP, voteType);
|
await handleExistingVotes(BrandingType.Title, videoID, hashedUserID, UUID, hashedIP, voteType);
|
||||||
if (existingUUID) {
|
if (existingUUID) {
|
||||||
await updateVoteTotals(BrandingType.Title, UUID, shouldLock, !!downvote);
|
await updateVoteTotals(BrandingType.Title, UUID, hashedUserID, shouldLock, !!downvote);
|
||||||
} else {
|
} else {
|
||||||
if (downvote) {
|
if (downvote) {
|
||||||
throw new Error("Title submission doesn't exist");
|
throw new Error("Title submission doesn't exist");
|
||||||
@@ -134,7 +134,7 @@ export async function postBranding(req: Request, res: Response) {
|
|||||||
|
|
||||||
await handleExistingVotes(BrandingType.Thumbnail, videoID, hashedUserID, UUID, hashedIP, voteType);
|
await handleExistingVotes(BrandingType.Thumbnail, videoID, hashedUserID, UUID, hashedIP, voteType);
|
||||||
if (existingUUID) {
|
if (existingUUID) {
|
||||||
await updateVoteTotals(BrandingType.Thumbnail, UUID, shouldLock, !!downvote);
|
await updateVoteTotals(BrandingType.Thumbnail, UUID, hashedUserID, shouldLock, !!downvote);
|
||||||
} else {
|
} else {
|
||||||
if (downvote) {
|
if (downvote) {
|
||||||
throw new Error("Thumbnail submission doesn't exist");
|
throw new Error("Thumbnail submission doesn't exist");
|
||||||
@@ -185,7 +185,9 @@ export async function postBranding(req: Request, res: Response) {
|
|||||||
async function handleExistingVotes(type: BrandingType, videoID: VideoID,
|
async function handleExistingVotes(type: BrandingType, videoID: VideoID,
|
||||||
hashedUserID: HashedUserID, UUID: BrandingUUID, hashedIP: HashedIP, voteType: BrandingVoteType) {
|
hashedUserID: HashedUserID, UUID: BrandingUUID, hashedIP: HashedIP, voteType: BrandingVoteType) {
|
||||||
const table = type === BrandingType.Title ? `"titleVotes"` : `"thumbnailVotes"`;
|
const table = type === BrandingType.Title ? `"titleVotes"` : `"thumbnailVotes"`;
|
||||||
|
const table2 = type === BrandingType.Title ? `"titles"` : `"thumbnails"`;
|
||||||
|
|
||||||
|
const isUsersSubmission = (await db.prepare("get", `SELECT "userID" FROM ${table2} WHERE "UUID" = ?`, [UUID]))?.userID === hashedUserID;
|
||||||
const idsDealtWith: BrandingUUID[] = [];
|
const idsDealtWith: BrandingUUID[] = [];
|
||||||
|
|
||||||
// Either votes of the same type, or on the same submission (undo a downvote)
|
// Either votes of the same type, or on the same submission (undo a downvote)
|
||||||
@@ -204,15 +206,33 @@ async function handleExistingVotes(type: BrandingType, videoID: VideoID,
|
|||||||
|
|
||||||
await privateDB.prepare("run", `DELETE FROM ${table} WHERE "id" = ?`, [existingVote.id]);
|
await privateDB.prepare("run", `DELETE FROM ${table} WHERE "id" = ?`, [existingVote.id]);
|
||||||
break;
|
break;
|
||||||
case BrandingVoteType.Downvote:
|
case BrandingVoteType.Downvote: {
|
||||||
// Undoing a downvote now that it is being upvoted
|
// Undoing a downvote now that it is being upvoted
|
||||||
|
|
||||||
|
// Only undo downvote if it is not their submission
|
||||||
|
if (!isUsersSubmission) {
|
||||||
await db.prepare("run", `UPDATE ${table} SET "downvotes" = "downvotes" - 1 WHERE "UUID" = ?`, [existingVote.UUID]);
|
await db.prepare("run", `UPDATE ${table} SET "downvotes" = "downvotes" - 1 WHERE "UUID" = ?`, [existingVote.UUID]);
|
||||||
|
}
|
||||||
|
|
||||||
await privateDB.prepare("run", `DELETE FROM ${table} WHERE "id" = ?`, [existingVote.id]);
|
await privateDB.prepare("run", `DELETE FROM ${table} WHERE "id" = ?`, [existingVote.id]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (isUsersSubmission) {
|
||||||
|
// Treat like upvoting another submission (undoing upvote)
|
||||||
|
let dealtWith = false;
|
||||||
|
for (const existingVote of existingVotes) {
|
||||||
|
if (existingVote.type === BrandingVoteType.Upvote && existingVote.UUID === UUID) {
|
||||||
|
if (!dealtWith) {
|
||||||
|
dealtWith = true;
|
||||||
|
await db.prepare("run", `UPDATE ${table} SET "votes" = "votes" - 1 WHERE "UUID" = ?`, [UUID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
await privateDB.prepare("run", `DELETE FROM ${table} WHERE "id" = ?`, [existingVote.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await privateDB.prepare("run", `INSERT INTO ${table} ("videoID", "UUID", "userID", "hashedIP", "type") VALUES (?, ?, ?, ?, ?)`,
|
await privateDB.prepare("run", `INSERT INTO ${table} ("videoID", "UUID", "userID", "hashedIP", "type") VALUES (?, ?, ?, ?, ?)`,
|
||||||
@@ -223,11 +243,16 @@ async function handleExistingVotes(type: BrandingType, videoID: VideoID,
|
|||||||
* Only called if an existing vote exists.
|
* Only called if an existing vote exists.
|
||||||
* Will update public vote totals and locked status.
|
* Will update public vote totals and locked status.
|
||||||
*/
|
*/
|
||||||
async function updateVoteTotals(type: BrandingType, UUID: BrandingUUID, shouldLock: boolean, downvote: boolean): Promise<void> {
|
async function updateVoteTotals(type: BrandingType, UUID: BrandingUUID, userID: HashedUserID, shouldLock: boolean, downvote: boolean): Promise<void> {
|
||||||
const table = type === BrandingType.Title ? `"titleVotes"` : `"thumbnailVotes"`;
|
const table = type === BrandingType.Title ? `"titleVotes"` : `"thumbnailVotes"`;
|
||||||
|
const table2 = type === BrandingType.Title ? `"titles"` : `"thumbnails"`;
|
||||||
|
|
||||||
if (downvote) {
|
if (downvote) {
|
||||||
|
// Only downvote if it is not their submission
|
||||||
|
const isUsersSubmission = (await db.prepare("get", `SELECT "userID" FROM ${table2} WHERE "UUID" = ?`, [UUID]))?.userID === userID;
|
||||||
|
if (!isUsersSubmission) {
|
||||||
await db.prepare("run", `UPDATE ${table} SET "downvotes" = "downvotes" + 1 WHERE "UUID" = ?`, [UUID]);
|
await db.prepare("run", `UPDATE ${table} SET "downvotes" = "downvotes" + 1 WHERE "UUID" = ?`, [UUID]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
await db.prepare("run", `UPDATE ${table} SET "votes" = "votes" + 1 WHERE "UUID" = ?`, [UUID]);
|
await db.prepare("run", `UPDATE ${table} SET "votes" = "votes" + 1 WHERE "UUID" = ?`, [UUID]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,6 +317,51 @@ describe("postBranding", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Downvote your own title and thumbnail", async () => {
|
||||||
|
const videoID = "postBrand5";
|
||||||
|
const title = {
|
||||||
|
title: "Some other title",
|
||||||
|
original: false
|
||||||
|
};
|
||||||
|
const thumbnail = {
|
||||||
|
timestamp: 13.42,
|
||||||
|
original: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await postBranding({
|
||||||
|
title,
|
||||||
|
thumbnail,
|
||||||
|
userID: userID4,
|
||||||
|
service: Service.YouTube,
|
||||||
|
videoID,
|
||||||
|
downvote: true
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.strictEqual(res.status, 200);
|
||||||
|
const dbTitles = await queryTitleByVideo(videoID, true);
|
||||||
|
for (const dbTitle of dbTitles) {
|
||||||
|
if (dbTitle.title === title.title) {
|
||||||
|
const dbTitleVotes = await queryTitleVotesByUUID(dbTitle.UUID);
|
||||||
|
assert.strictEqual(dbTitleVotes.votes, -1);
|
||||||
|
assert.strictEqual(dbTitleVotes.downvotes, 1);
|
||||||
|
assert.strictEqual(dbTitleVotes.locked, 0);
|
||||||
|
assert.strictEqual(dbTitleVotes.shadowHidden, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dbThumbnails = await queryThumbnailByVideo(videoID, true);
|
||||||
|
for (const dbThumbnail of dbThumbnails) {
|
||||||
|
if (dbThumbnail.timestamp === thumbnail.timestamp) {
|
||||||
|
const dbThumbnailVotes = await queryThumbnailVotesByUUID(dbThumbnail.UUID);
|
||||||
|
|
||||||
|
assert.strictEqual(dbThumbnailVotes.votes, -1);
|
||||||
|
assert.strictEqual(dbThumbnailVotes.downvotes, 1);
|
||||||
|
assert.strictEqual(dbThumbnailVotes.locked, 0);
|
||||||
|
assert.strictEqual(dbThumbnailVotes.shadowHidden, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("Downvote another title and thumbnail", async () => {
|
it("Downvote another title and thumbnail", async () => {
|
||||||
const videoID = "postBrand5";
|
const videoID = "postBrand5";
|
||||||
const title = {
|
const title = {
|
||||||
@@ -340,22 +385,26 @@ describe("postBranding", () => {
|
|||||||
assert.strictEqual(res.status, 200);
|
assert.strictEqual(res.status, 200);
|
||||||
const dbTitles = await queryTitleByVideo(videoID, true);
|
const dbTitles = await queryTitleByVideo(videoID, true);
|
||||||
for (const dbTitle of dbTitles) {
|
for (const dbTitle of dbTitles) {
|
||||||
|
if (dbTitle.title === title.title) {
|
||||||
const dbTitleVotes = await queryTitleVotesByUUID(dbTitle.UUID);
|
const dbTitleVotes = await queryTitleVotesByUUID(dbTitle.UUID);
|
||||||
assert.strictEqual(dbTitleVotes.votes, 0);
|
assert.strictEqual(dbTitleVotes.votes, 0);
|
||||||
assert.strictEqual(dbTitleVotes.downvotes, 1);
|
assert.strictEqual(dbTitleVotes.downvotes, 1);
|
||||||
assert.strictEqual(dbTitleVotes.locked, 0);
|
assert.strictEqual(dbTitleVotes.locked, 0);
|
||||||
assert.strictEqual(dbTitleVotes.shadowHidden, 0);
|
assert.strictEqual(dbTitleVotes.shadowHidden, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const dbThumbnails = await queryThumbnailByVideo(videoID, true);
|
const dbThumbnails = await queryThumbnailByVideo(videoID, true);
|
||||||
for (const dbThumbnail of dbThumbnails) {
|
for (const dbThumbnail of dbThumbnails) {
|
||||||
const dbThumbnailVotes = await queryThumbnailVotesByUUID(dbThumbnail.UUID);
|
const dbThumbnailVotes = await queryThumbnailVotesByUUID(dbThumbnail.UUID);
|
||||||
|
|
||||||
|
if (dbThumbnail.timestamp === thumbnail.timestamp) {
|
||||||
assert.strictEqual(dbThumbnailVotes.votes, 0);
|
assert.strictEqual(dbThumbnailVotes.votes, 0);
|
||||||
assert.strictEqual(dbThumbnailVotes.downvotes, 1);
|
assert.strictEqual(dbThumbnailVotes.downvotes, 1);
|
||||||
assert.strictEqual(dbThumbnailVotes.locked, 0);
|
assert.strictEqual(dbThumbnailVotes.locked, 0);
|
||||||
assert.strictEqual(dbThumbnailVotes.shadowHidden, 0);
|
assert.strictEqual(dbThumbnailVotes.shadowHidden, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Fail to downvote locked title and thumbnail", async () => {
|
it("Fail to downvote locked title and thumbnail", async () => {
|
||||||
@@ -427,7 +476,7 @@ describe("postBranding", () => {
|
|||||||
for (const dbTitle of dbTitles) {
|
for (const dbTitle of dbTitles) {
|
||||||
if (dbTitle.title === title.title) {
|
if (dbTitle.title === title.title) {
|
||||||
const dbTitleVotes = await queryTitleVotesByUUID(dbTitle.UUID);
|
const dbTitleVotes = await queryTitleVotesByUUID(dbTitle.UUID);
|
||||||
assert.strictEqual(dbTitleVotes.votes, 1);
|
assert.strictEqual(dbTitleVotes.votes, 0);
|
||||||
assert.strictEqual(dbTitleVotes.downvotes, 0);
|
assert.strictEqual(dbTitleVotes.downvotes, 0);
|
||||||
assert.strictEqual(dbTitleVotes.locked, 0);
|
assert.strictEqual(dbTitleVotes.locked, 0);
|
||||||
assert.strictEqual(dbTitleVotes.shadowHidden, 0);
|
assert.strictEqual(dbTitleVotes.shadowHidden, 0);
|
||||||
@@ -439,7 +488,7 @@ describe("postBranding", () => {
|
|||||||
if (dbThumbnail.timestamp === thumbnail.timestamp) {
|
if (dbThumbnail.timestamp === thumbnail.timestamp) {
|
||||||
const dbThumbnailVotes = await queryThumbnailVotesByUUID(dbThumbnail.UUID);
|
const dbThumbnailVotes = await queryThumbnailVotesByUUID(dbThumbnail.UUID);
|
||||||
|
|
||||||
assert.strictEqual(dbThumbnailVotes.votes, 1);
|
assert.strictEqual(dbThumbnailVotes.votes, 0);
|
||||||
assert.strictEqual(dbThumbnailVotes.downvotes, 0);
|
assert.strictEqual(dbThumbnailVotes.downvotes, 0);
|
||||||
assert.strictEqual(dbThumbnailVotes.locked, 0);
|
assert.strictEqual(dbThumbnailVotes.locked, 0);
|
||||||
assert.strictEqual(dbThumbnailVotes.shadowHidden, 0);
|
assert.strictEqual(dbThumbnailVotes.shadowHidden, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user