mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2024-11-10 09:07:47 +01:00
Merge pull request #319 from HaiDang666/266_final
Update: most upvoted segments on locked videos as locked submissions
This commit is contained in:
commit
9aa0ff6de6
2 changed files with 133 additions and 31 deletions
|
@ -10,7 +10,8 @@ interface ReputationDBResult {
|
||||||
votedSum: number,
|
votedSum: number,
|
||||||
lockedSum: number,
|
lockedSum: number,
|
||||||
semiOldUpvotedSubmissions: number,
|
semiOldUpvotedSubmissions: number,
|
||||||
oldUpvotedSubmissions: number
|
oldUpvotedSubmissions: number,
|
||||||
|
mostUpvotedInLockedVideoSum: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getReputation(userID: UserID): Promise<number> {
|
export async function getReputation(userID: UserID): Promise<number> {
|
||||||
|
@ -28,43 +29,60 @@ export async function getReputation(userID: UserID): Promise<number> {
|
||||||
SUM(CASE WHEN "timeSubmitted" > 1596240000000 THEN "votes" ELSE 0 END) AS "votedSum",
|
SUM(CASE WHEN "timeSubmitted" > 1596240000000 THEN "votes" ELSE 0 END) AS "votedSum",
|
||||||
SUM(locked) AS "lockedSum",
|
SUM(locked) AS "lockedSum",
|
||||||
SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "semiOldUpvotedSubmissions",
|
SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "semiOldUpvotedSubmissions",
|
||||||
SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "oldUpvotedSubmissions"
|
SUM(CASE WHEN "timeSubmitted" < ? AND "timeSubmitted" > 1596240000000 AND "votes" > 0 THEN 1 ELSE 0 END) AS "oldUpvotedSubmissions",
|
||||||
|
SUM(CASE WHEN "votes" > 0
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT * FROM "sponsorTimes" as c
|
||||||
|
WHERE (c."votes" > "a"."votes" OR c."locked" > "a"."locked") AND
|
||||||
|
c."videoID" = "a"."videoID" AND
|
||||||
|
c."category" = "a"."category" LIMIT 1)
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT * FROM "lockCategories" as l
|
||||||
|
WHERE l."videoID" = "a"."videoID" AND l."category" = "a"."category" LIMIT 1)
|
||||||
|
THEN 1 ELSE 0 END) AS "mostUpvotedInLockedVideoSum"
|
||||||
FROM "sponsorTimes" as "a" WHERE "userID" = ?`, [userID, weekAgo, pastDate, userID]) as Promise<ReputationDBResult>;
|
FROM "sponsorTimes" as "a" WHERE "userID" = ?`, [userID, weekAgo, pastDate, userID]) as Promise<ReputationDBResult>;
|
||||||
|
|
||||||
const result = await QueryCacher.get(fetchFromDB, reputationKey(userID));
|
const result = await QueryCacher.get(fetchFromDB, reputationKey(userID));
|
||||||
|
|
||||||
// Grace period
|
return calculateReputationFromMetrics(result);
|
||||||
if (result.totalSubmissions < 5) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const downvoteRatio = result.downvotedSubmissions / result.totalSubmissions;
|
|
||||||
if (downvoteRatio > 0.3) {
|
|
||||||
return convertRange(Math.min(downvoteRatio, 0.7), 0.3, 0.7, -0.5, -2.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
const nonSelfDownvoteRatio = result.nonSelfDownvotedSubmissions / result.totalSubmissions;
|
|
||||||
if (nonSelfDownvoteRatio > 0.05) {
|
|
||||||
return convertRange(Math.min(nonSelfDownvoteRatio, 0.4), 0.05, 0.4, -0.5, -2.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.votedSum < 5) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.oldUpvotedSubmissions < 3) {
|
|
||||||
if (result.semiOldUpvotedSubmissions > 3) {
|
|
||||||
return convertRange(Math.min(result.votedSum, 150), 5, 150, 0, 2) + convertRange(Math.min(result.lockedSum ?? 0, 50), 0, 50, 0, 5);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return convertRange(Math.min(result.votedSum, 150), 5, 150, 0, 7) + convertRange(Math.min(result.lockedSum ?? 0, 50), 0, 50, 0, 20);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert a number from one range to another.
|
||||||
function convertRange(value: number, currentMin: number, currentMax: number, targetMin: number, targetMax: number): number {
|
function convertRange(value: number, currentMin: number, currentMax: number, targetMin: number, targetMax: number): number {
|
||||||
const currentRange = currentMax - currentMin;
|
const currentRange = currentMax - currentMin;
|
||||||
const targetRange = targetMax - targetMin;
|
const targetRange = targetMax - targetMin;
|
||||||
return ((value - currentMin) / currentRange) * targetRange + targetMin;
|
return ((value - currentMin) / currentRange) * targetRange + targetMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function calculateReputationFromMetrics(metrics: ReputationDBResult): number {
|
||||||
|
// Grace period
|
||||||
|
if (metrics.totalSubmissions < 5) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const downvoteRatio = metrics.downvotedSubmissions / metrics.totalSubmissions;
|
||||||
|
if (downvoteRatio > 0.3) {
|
||||||
|
return convertRange(Math.min(downvoteRatio, 0.7), 0.3, 0.7, -0.5, -2.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonSelfDownvoteRatio = metrics.nonSelfDownvotedSubmissions / metrics.totalSubmissions;
|
||||||
|
if (nonSelfDownvoteRatio > 0.05) {
|
||||||
|
return convertRange(Math.min(nonSelfDownvoteRatio, 0.4), 0.05, 0.4, -0.5, -2.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metrics.votedSum < 5) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metrics.oldUpvotedSubmissions < 3) {
|
||||||
|
if (metrics.semiOldUpvotedSubmissions > 3) {
|
||||||
|
return convertRange(Math.min(metrics.votedSum, 150), 5, 150, 0, 2) +
|
||||||
|
convertRange(Math.min((metrics.lockedSum ?? 0) + (metrics.mostUpvotedInLockedVideoSum ?? 0), 50), 0, 50, 0, 5);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertRange(Math.min(metrics.votedSum, 150), 5, 150, 0, 7) +
|
||||||
|
convertRange(Math.min((metrics.lockedSum ?? 0) + (metrics.mostUpvotedInLockedVideoSum ?? 0), 50), 0, 50, 0, 20);
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import assert from "assert";
|
||||||
import { db } from "../../src/databases/databases";
|
import { db } from "../../src/databases/databases";
|
||||||
import { UserID } from "../../src/types/user.model";
|
import { UserID } from "../../src/types/user.model";
|
||||||
import { getHash } from "../../src/utils/getHash";
|
import { getHash } from "../../src/utils/getHash";
|
||||||
import { getReputation } from "../../src/utils/reputation";
|
import { getReputation, calculateReputationFromMetrics } from "../../src/utils/reputation";
|
||||||
|
|
||||||
const userIDLowSubmissions = "reputation-lowsubmissions" as UserID;
|
const userIDLowSubmissions = "reputation-lowsubmissions" as UserID;
|
||||||
const userIDHighDownvotes = "reputation-highdownvotes" as UserID;
|
const userIDHighDownvotes = "reputation-highdownvotes" as UserID;
|
||||||
|
@ -12,11 +12,13 @@ const userIDLowSum = "reputation-lowsum" as UserID;
|
||||||
const userIDHighRepBeforeManualVote = "reputation-oldhighrep" as UserID;
|
const userIDHighRepBeforeManualVote = "reputation-oldhighrep" as UserID;
|
||||||
const userIDHighRep = "reputation-highrep" as UserID;
|
const userIDHighRep = "reputation-highrep" as UserID;
|
||||||
const userIDHighRepAndLocked = "reputation-highlockedrep" as UserID;
|
const userIDHighRepAndLocked = "reputation-highlockedrep" as UserID;
|
||||||
|
const userIDHaveMostUpvotedInLockedVideo = "reputation-mostupvotedaslocked" as UserID;
|
||||||
|
|
||||||
describe("reputation", () => {
|
describe("reputation", () => {
|
||||||
before(async function() {
|
before(async function() {
|
||||||
this.timeout(5000); // this preparation takes longer then usual
|
this.timeout(5000); // this preparation takes longer then usual
|
||||||
const videoID = "reputation-videoID";
|
const videoID = "reputation-videoID";
|
||||||
|
const videoID2 = "reputation-videoID-2";
|
||||||
|
|
||||||
const sponsorTimesInsertQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "service", "videoDuration", "hidden", "shadowHidden", "hashedVideoID") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
|
const sponsorTimesInsertQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "service", "videoDuration", "hidden", "shadowHidden", "hashedVideoID") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
|
||||||
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-0-uuid-0", getHash(userIDLowSubmissions), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-0-uuid-0", getHash(userIDLowSubmissions), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
@ -87,6 +89,28 @@ describe("reputation", () => {
|
||||||
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-6-uuid-5", getHash(userIDHighRepAndLocked), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-6-uuid-5", getHash(userIDHighRepAndLocked), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-6-uuid-6", getHash(userIDHighRepAndLocked), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-6-uuid-6", getHash(userIDHighRepAndLocked), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-6-uuid-7", getHash(userIDHighRepAndLocked), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-6-uuid-7", getHash(userIDHighRepAndLocked), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
|
||||||
|
//Record has most upvoted
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 5, 0, "reputation-7-uuid-0", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 101, 0, "reputation-7-uuid-1", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "intro", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID2, 1, 11, 5, 0, "reputation-7-uuid-8", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID2, 1)]);
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID2, 1, 11, 0, 0, "reputation-7-uuid-9", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID2, 1)]);
|
||||||
|
// other segments
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-7-uuid-2", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-7-uuid-3", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 2, 0, "reputation-7-uuid-4", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, -1, 0, "reputation-7-uuid-5", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-7-uuid-6", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
await db.prepare("run", sponsorTimesInsertQuery, [videoID, 1, 11, 0, 0, "reputation-7-uuid-7", getHash(userIDHaveMostUpvotedInLockedVideo), 1606240000000, 50, "sponsor", "YouTube", 100, 0, 0, getHash(videoID, 1)]);
|
||||||
|
|
||||||
|
// lock video
|
||||||
|
const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)';
|
||||||
|
await db.prepare("run", insertVipUserQuery, [getHash("VIPUser-getLockCategories")]);
|
||||||
|
|
||||||
|
const insertLockCategoryQuery = 'INSERT INTO "lockCategories" ("userID", "videoID", "category", "hashedVideoID") VALUES (?, ?, ?, ?)';
|
||||||
|
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), videoID, "sponsor", getHash(videoID, 1)]);
|
||||||
|
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), videoID, "intro", getHash(videoID, 1)]);
|
||||||
|
await db.prepare("run", insertLockCategoryQuery, [getHash("VIPUser-getLockCategories"), videoID2, "sponsor", getHash(videoID2, 1)]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("user in grace period", async () => {
|
it("user in grace period", async () => {
|
||||||
|
@ -94,10 +118,33 @@ describe("reputation", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("user with high downvote ratio", async () => {
|
it("user with high downvote ratio", async () => {
|
||||||
|
const metrics = {
|
||||||
|
totalSubmissions: 8,
|
||||||
|
downvotedSubmissions: 5,
|
||||||
|
nonSelfDownvotedSubmissions: 0,
|
||||||
|
votedSum: -7,
|
||||||
|
lockedSum: 0,
|
||||||
|
semiOldUpvotedSubmissions: 1,
|
||||||
|
oldUpvotedSubmissions: 1,
|
||||||
|
mostUpvotedInLockedVideoSum: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.strictEqual(await getReputation(getHash(userIDHighDownvotes)), calculateReputationFromMetrics(metrics));
|
||||||
assert.strictEqual(await getReputation(getHash(userIDHighDownvotes)), -2.125);
|
assert.strictEqual(await getReputation(getHash(userIDHighDownvotes)), -2.125);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("user with high non self downvote ratio", async () => {
|
it("user with high non self downvote ratio", async () => {
|
||||||
|
const metrics = {
|
||||||
|
totalSubmissions: 8,
|
||||||
|
downvotedSubmissions: 2,
|
||||||
|
nonSelfDownvotedSubmissions: 2,
|
||||||
|
votedSum: -1,
|
||||||
|
lockedSum: 0,
|
||||||
|
semiOldUpvotedSubmissions: 1,
|
||||||
|
oldUpvotedSubmissions: 1,
|
||||||
|
mostUpvotedInLockedVideoSum: 0
|
||||||
|
};
|
||||||
|
assert.strictEqual(await getReputation(getHash(userIDHighNonSelfDownvotes)), calculateReputationFromMetrics(metrics));
|
||||||
assert.strictEqual(await getReputation(getHash(userIDHighNonSelfDownvotes)), -1.6428571428571428);
|
assert.strictEqual(await getReputation(getHash(userIDHighNonSelfDownvotes)), -1.6428571428571428);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -114,11 +161,48 @@ describe("reputation", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("user with high reputation", async () => {
|
it("user with high reputation", async () => {
|
||||||
|
const metrics = {
|
||||||
|
totalSubmissions: 8,
|
||||||
|
downvotedSubmissions: 1,
|
||||||
|
nonSelfDownvotedSubmissions: 0,
|
||||||
|
votedSum: 9,
|
||||||
|
lockedSum: 0,
|
||||||
|
semiOldUpvotedSubmissions: 5,
|
||||||
|
oldUpvotedSubmissions: 5,
|
||||||
|
mostUpvotedInLockedVideoSum: 0
|
||||||
|
};
|
||||||
|
assert.strictEqual(await getReputation(getHash(userIDHighRep)), calculateReputationFromMetrics(metrics));
|
||||||
assert.strictEqual(await getReputation(getHash(userIDHighRep)), 0.19310344827586207);
|
assert.strictEqual(await getReputation(getHash(userIDHighRep)), 0.19310344827586207);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("user with high reputation and locked segments", async () => {
|
it("user with high reputation and locked segments", async () => {
|
||||||
|
const metrics = {
|
||||||
|
totalSubmissions: 8,
|
||||||
|
downvotedSubmissions: 1,
|
||||||
|
nonSelfDownvotedSubmissions: 0,
|
||||||
|
votedSum: 9,
|
||||||
|
lockedSum: 4,
|
||||||
|
semiOldUpvotedSubmissions: 5,
|
||||||
|
oldUpvotedSubmissions: 5,
|
||||||
|
mostUpvotedInLockedVideoSum: 0
|
||||||
|
};
|
||||||
|
assert.strictEqual(await getReputation(getHash(userIDHighRepAndLocked)), calculateReputationFromMetrics(metrics));
|
||||||
assert.strictEqual(await getReputation(getHash(userIDHighRepAndLocked)), 1.793103448275862);
|
assert.strictEqual(await getReputation(getHash(userIDHighRepAndLocked)), 1.793103448275862);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("user with most upvoted segments in locked video", async () => {
|
||||||
|
const metrics = {
|
||||||
|
totalSubmissions: 10,
|
||||||
|
downvotedSubmissions: 1,
|
||||||
|
nonSelfDownvotedSubmissions: 0,
|
||||||
|
votedSum: 116,
|
||||||
|
lockedSum: 0,
|
||||||
|
semiOldUpvotedSubmissions: 6,
|
||||||
|
oldUpvotedSubmissions: 6,
|
||||||
|
mostUpvotedInLockedVideoSum: 2
|
||||||
|
};
|
||||||
|
assert.strictEqual(await getReputation(getHash(userIDHaveMostUpvotedInLockedVideo)), calculateReputationFromMetrics(metrics));
|
||||||
|
assert.strictEqual(await getReputation(getHash(userIDHaveMostUpvotedInLockedVideo)), 6.158620689655172);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue