Skip to content

Commit

Permalink
Don't allow multiple downvotes on one submission
Browse files Browse the repository at this point in the history
  • Loading branch information
ajayyy committed Nov 10, 2024
1 parent 405805f commit b2981fe
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 37 deletions.
4 changes: 3 additions & 1 deletion src/databases/Sqlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ export class Sqlite implements IDatabase {
}

private static processUpgradeQuery(query: string): string {
return query.replace(/^.*--!sqlite-ignore/gm, "");
return query
.replace(/SERIAL PRIMARY KEY/gi, "INTEGER PRIMARY KEY AUTOINCREMENT")
.replace(/^.*--!sqlite-ignore/gm, "");
}

highLoad() {
Expand Down
52 changes: 16 additions & 36 deletions src/routes/postBranding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,51 +183,31 @@ export async function postBranding(req: Request, res: Response) {
async function handleExistingVotes(type: BrandingType, videoID: VideoID,
hashedUserID: HashedUserID, UUID: BrandingUUID, hashedIP: HashedIP, voteType: BrandingVoteType) {
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[] = [];

// Either votes of the same type, or on the same submission (undo a downvote)
const existingVotes = await privateDB.prepare("all", `SELECT "id", "UUID", "type" from ${table} where "videoID" = ? AND "userID" = ? AND ("type" = ? OR "UUID" = ?)`, [videoID, hashedUserID, voteType, UUID]) as ExistingVote[];
if (existingVotes.length > 0) {
// Only one upvote per video
if (voteType === BrandingVoteType.Upvote) {
for (const existingVote of existingVotes) {
switch (existingVote.type) {
case BrandingVoteType.Upvote:
// Old case where there are duplicate rows in private db
if (!idsDealtWith.includes(existingVote.UUID)) {
idsDealtWith.push(existingVote.UUID);
await db.prepare("run", `UPDATE ${table} SET "votes" = "votes" - 1 WHERE "UUID" = ?`, [existingVote.UUID]);
}

await privateDB.prepare("run", `DELETE FROM ${table} WHERE "id" = ?`, [existingVote.id]);
break;
case BrandingVoteType.Downvote: {
// 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 privateDB.prepare("run", `DELETE FROM ${table} WHERE "id" = ?`, [existingVote.id]);
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]);
for (const existingVote of existingVotes) {
// For downvotes, only undo for this specific submission (multiple downvotes on one submission not allowed)
if (voteType === BrandingVoteType.Downvote && existingVote.UUID !== UUID) continue;

switch (existingVote.type) {
case BrandingVoteType.Upvote:
// Old case where there are duplicate rows in private db
if (!idsDealtWith.includes(existingVote.UUID)) {
idsDealtWith.push(existingVote.UUID);
await db.prepare("run", `UPDATE ${table} SET "votes" = "votes" - 1 WHERE "UUID" = ?`, [existingVote.UUID]);
}

await privateDB.prepare("run", `DELETE FROM ${table} WHERE "id" = ?`, [existingVote.id]);
break;
case BrandingVoteType.Downvote: {
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]);
break;
}
}
}
Expand Down
45 changes: 45 additions & 0 deletions test/cases/postBranding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,51 @@ describe("postBranding", () => {
}
});

it("Double downvote title and thumbnail should only count once", 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: userID6,
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, 0);
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, 0);
assert.strictEqual(dbThumbnailVotes.downvotes, 1);
assert.strictEqual(dbThumbnailVotes.locked, 0);
assert.strictEqual(dbThumbnailVotes.shadowHidden, 0);
}
}
});

it("Downvote your own title and thumbnail", async () => {
const videoID = "postBrand5";
const title = {
Expand Down

0 comments on commit b2981fe

Please sign in to comment.