mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2024-11-10 01:02:30 +01:00
Merge branch 'master' of https://github.com/ajayyy/SponsorBlockServer
This commit is contained in:
commit
d2df5cef98
5 changed files with 78 additions and 22 deletions
2
.github/workflows/test.yaml
vendored
2
.github/workflows/test.yaml
vendored
|
@ -64,7 +64,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
PG_USER: ci_db_user
|
PG_USER: ci_db_user
|
||||||
PG_PASS: ci_db_pass
|
PG_PASS: ci_db_pass
|
||||||
run: docker-compose -f docker/docker-compose-ci.yml up -d
|
run: docker compose -f docker/docker-compose-ci.yml up -d
|
||||||
- name: Check running containers
|
- name: Check running containers
|
||||||
run: docker ps
|
run: docker ps
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
|
|
|
@ -241,7 +241,7 @@
|
||||||
| title | TEXT | not null |
|
| title | TEXT | not null |
|
||||||
| original | INTEGER | default 0 |
|
| original | INTEGER | default 0 |
|
||||||
| userID | TEXT | not null
|
| userID | TEXT | not null
|
||||||
| service | TEXT not null |
|
| service | TEXT | not null |
|
||||||
| hashedVideoID | TEXT | not null |
|
| hashedVideoID | TEXT | not null |
|
||||||
| timeSubmitted | INTEGER | not null |
|
| timeSubmitted | INTEGER | not null |
|
||||||
| UUID | TEXT | not null, primary key
|
| UUID | TEXT | not null, primary key
|
||||||
|
@ -277,7 +277,6 @@
|
||||||
|
|
||||||
| Name | Type | |
|
| Name | Type | |
|
||||||
| -- | :--: | -- |
|
| -- | :--: | -- |
|
||||||
| UUID | TEXT | not null |
|
|
||||||
| original | INTEGER | default 0 |
|
| original | INTEGER | default 0 |
|
||||||
| userID | TEXT | not null |
|
| userID | TEXT | not null |
|
||||||
| service | TEXT | not null |
|
| service | TEXT | not null |
|
||||||
|
@ -305,8 +304,8 @@
|
||||||
|
|
||||||
### thumbnailVotes
|
### thumbnailVotes
|
||||||
|
|
||||||
| index | field |
|
| Name | Type | |
|
||||||
| -- | :--: |
|
| -- | :--: | -- |
|
||||||
| UUID | TEXT | not null, primary key |
|
| UUID | TEXT | not null, primary key |
|
||||||
| votes | INTEGER | not null, default 0 |
|
| votes | INTEGER | not null, default 0 |
|
||||||
| locked | INTEGER |not null, default 0 |
|
| locked | INTEGER |not null, default 0 |
|
||||||
|
|
|
@ -27,10 +27,11 @@ export async function getChapterNames(req: Request, res: Response): Promise<Resp
|
||||||
FROM "videoInfo"
|
FROM "videoInfo"
|
||||||
WHERE "channelID" = ?
|
WHERE "channelID" = ?
|
||||||
) AND "description" != ''
|
) AND "description" != ''
|
||||||
|
AND similarity("description", ?) >= 0.1
|
||||||
GROUP BY "description"
|
GROUP BY "description"
|
||||||
ORDER BY SUM("votes"), similarity("description", ?) DESC
|
ORDER BY SUM("votes"), similarity("description", ?) DESC
|
||||||
LIMIT 5;`
|
LIMIT 5;`
|
||||||
, [channelID, description]) as { description: string }[];
|
, [channelID, description, description]) as { description: string }[];
|
||||||
|
|
||||||
if (descriptions?.length > 0) {
|
if (descriptions?.length > 0) {
|
||||||
return res.status(200).json(descriptions.map(d => ({
|
return res.status(200).json(descriptions.map(d => ({
|
||||||
|
|
|
@ -85,6 +85,7 @@ export async function postBranding(req: Request, res: Response) {
|
||||||
const existingIsLocked = !!existingUUID && (await db.prepare("get", `SELECT "locked" from "titleVotes" where "UUID" = ?`, [existingUUID]))?.locked;
|
const existingIsLocked = !!existingUUID && (await db.prepare("get", `SELECT "locked" from "titleVotes" where "UUID" = ?`, [existingUUID]))?.locked;
|
||||||
if (existingUUID != undefined && isBanned) return; // ignore votes on existing details from banned users
|
if (existingUUID != undefined && isBanned) return; // ignore votes on existing details from banned users
|
||||||
if (downvote && existingIsLocked && !isVip) {
|
if (downvote && existingIsLocked && !isVip) {
|
||||||
|
sendWebhooks(videoID, existingUUID, voteType).catch((e) => Logger.error(e));
|
||||||
errorCode = 403;
|
errorCode = 403;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +114,7 @@ export async function postBranding(req: Request, res: Response) {
|
||||||
await db.prepare("run", `UPDATE "titleVotes" as tv SET "locked" = 0 FROM "titles" t WHERE tv."UUID" = t."UUID" AND tv."UUID" != ? AND t."videoID" = ?`, [UUID, videoID]);
|
await db.prepare("run", `UPDATE "titleVotes" as tv SET "locked" = 0 FROM "titles" t WHERE tv."UUID" = t."UUID" AND tv."UUID" != ? AND t."videoID" = ?`, [UUID, videoID]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendWebhooks(videoID, UUID).catch((e) => Logger.error(e));
|
sendWebhooks(videoID, UUID, voteType).catch((e) => Logger.error(e));
|
||||||
}
|
}
|
||||||
})(), (async () => {
|
})(), (async () => {
|
||||||
if (thumbnail) {
|
if (thumbnail) {
|
||||||
|
@ -290,14 +291,34 @@ export async function verifyOldSubmissions(hashedUserID: HashedUserID, verificat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendWebhooks(videoID: VideoID, UUID: BrandingUUID) {
|
async function sendWebhooks(videoID: VideoID, UUID: BrandingUUID, voteType: BrandingVoteType) {
|
||||||
const lockedSubmission = await db.prepare("get", `SELECT "titleVotes"."votes", "titles"."title", "titles"."userID" FROM "titles" JOIN "titleVotes" ON "titles"."UUID" = "titleVotes"."UUID" WHERE "titles"."videoID" = ? AND "titles"."UUID" != ? AND "titleVotes"."locked" = 1`, [videoID, UUID]);
|
const currentSubmission = await db.prepare(
|
||||||
|
"get",
|
||||||
|
`SELECT
|
||||||
|
"titles"."title",
|
||||||
|
"titleVotes"."locked",
|
||||||
|
"titles"."userID",
|
||||||
|
"titleVotes"."votes"-"titleVotes"."downvotes"+"titleVotes"."verification" AS "score"
|
||||||
|
FROM "titles" JOIN "titleVotes" ON "titles"."UUID" = "titleVotes"."UUID"
|
||||||
|
WHERE "titles"."UUID" = ?`,
|
||||||
|
[UUID]);
|
||||||
|
|
||||||
if (lockedSubmission) {
|
// Unlocked title getting more upvotes than the locked one
|
||||||
const currentSubmission = await db.prepare("get", `SELECT "titleVotes"."votes", "titles"."title" FROM "titles" JOIN "titleVotes" ON "titles"."UUID" = "titleVotes"."UUID" WHERE "titles"."UUID" = ?`, [UUID]);
|
if (voteType === BrandingVoteType.Upvote) {
|
||||||
|
const lockedSubmission = await db.prepare(
|
||||||
|
"get",
|
||||||
|
`SELECT
|
||||||
|
"titles"."title",
|
||||||
|
"titles"."userID",
|
||||||
|
"titleVotes"."votes"-"titleVotes"."downvotes"+"titleVotes"."verification" AS "score"
|
||||||
|
FROM "titles" JOIN "titleVotes" ON "titles"."UUID" = "titleVotes"."UUID"
|
||||||
|
WHERE "titles"."videoID" = ?
|
||||||
|
AND "titles"."UUID" != ?
|
||||||
|
AND "titleVotes"."locked" = 1`,
|
||||||
|
[videoID, UUID]);
|
||||||
|
|
||||||
// Time to warn that there may be an issue
|
// Time to warn that there may be an issue
|
||||||
if (currentSubmission.votes - lockedSubmission.votes > 2) {
|
if (lockedSubmission && currentSubmission.score - lockedSubmission.score > 2) {
|
||||||
const usernameRow = await db.prepare("get", `SELECT "userName" FROM "userNames" WHERE "userID" = ?`, [lockedSubmission.userID]);
|
const usernameRow = await db.prepare("get", `SELECT "userName" FROM "userNames" WHERE "userID" = ?`, [lockedSubmission.userID]);
|
||||||
|
|
||||||
const data = await getVideoDetails(videoID);
|
const data = await getVideoDetails(videoID);
|
||||||
|
@ -305,7 +326,7 @@ async function sendWebhooks(videoID: VideoID, UUID: BrandingUUID) {
|
||||||
"embeds": [{
|
"embeds": [{
|
||||||
"title": data?.title,
|
"title": data?.title,
|
||||||
"url": `https://www.youtube.com/watch?v=${videoID}`,
|
"url": `https://www.youtube.com/watch?v=${videoID}`,
|
||||||
"description": `**${lockedSubmission.votes}** Votes vs **${currentSubmission.votes}**\
|
"description": `**${lockedSubmission.score}** score vs **${currentSubmission.score}**\
|
||||||
\n\n**Locked title:** ${lockedSubmission.title}\
|
\n\n**Locked title:** ${lockedSubmission.title}\
|
||||||
\n**New title:** ${currentSubmission.title}\
|
\n**New title:** ${currentSubmission.title}\
|
||||||
\n\n**Submitted by:** ${usernameRow?.userName ?? ""}\n${lockedSubmission.userID}`,
|
\n\n**Submitted by:** ${usernameRow?.userName ?? ""}\n${lockedSubmission.userID}`,
|
||||||
|
@ -329,6 +350,38 @@ async function sendWebhooks(videoID: VideoID, UUID: BrandingUUID) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Downvotes on locked title
|
||||||
|
if (voteType === BrandingVoteType.Downvote && currentSubmission.locked === 1) {
|
||||||
|
const usernameRow = await db.prepare("get", `SELECT "userName" FROM "userNames" WHERE "userID" = ?`, [currentSubmission.userID]);
|
||||||
|
|
||||||
|
const data = await getVideoDetails(videoID);
|
||||||
|
axios.post(config.discordDeArrowLockedWebhookURL, {
|
||||||
|
"embeds": [{
|
||||||
|
"title": data?.title,
|
||||||
|
"url": `https://www.youtube.com/watch?v=${videoID}`,
|
||||||
|
"description": `Locked title with **${currentSubmission.score}** score received a downvote\
|
||||||
|
\n\n**Locked title:** ${currentSubmission.title}\
|
||||||
|
\n**Submitted by:** ${usernameRow?.userName ?? ""}\n${currentSubmission.userID}`,
|
||||||
|
"color": 10813440,
|
||||||
|
"thumbnail": {
|
||||||
|
"url": getMaxResThumbnail(videoID),
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.status >= 400) {
|
||||||
|
Logger.error("Error sending reported submission Discord hook");
|
||||||
|
Logger.error(JSON.stringify((res.data)));
|
||||||
|
Logger.error("\n");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
Logger.error("Failed to send reported submission Discord hook.");
|
||||||
|
Logger.error(JSON.stringify(err));
|
||||||
|
Logger.error("\n");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkForWrongVideoDuration(videoID: VideoID, duration: number): Promise<boolean> {
|
async function checkForWrongVideoDuration(videoID: VideoID, duration: number): Promise<boolean> {
|
||||||
|
|
|
@ -16,17 +16,18 @@ describe("getChapterNames", function () {
|
||||||
"Weird name",
|
"Weird name",
|
||||||
"A different one",
|
"A different one",
|
||||||
"Something else",
|
"Something else",
|
||||||
|
"Weirder name",
|
||||||
];
|
];
|
||||||
|
|
||||||
const nameSearch = (query: string, expected: string): Promise<void> => {
|
const nameSearch = (query: string, expected: string | null, expectedResults: number): Promise<void> => {
|
||||||
const expectedData = [{
|
const expectedData = [{
|
||||||
description: expected
|
description: expected
|
||||||
}];
|
}];
|
||||||
return client.get(`${endpoint}?description=${query}&channelID=${chapterChannelID}`)
|
return client.get(`${endpoint}?description=${query}&channelID=${chapterChannelID}`)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
assert.strictEqual(res.status, 200);
|
assert.strictEqual(res.status, expectedResults == 0 ? 404 : 200);
|
||||||
assert.strictEqual(res.data.length, chapterNames.length);
|
assert.strictEqual(res.data.length, expectedResults);
|
||||||
assert.ok(partialDeepEquals(res.data, expectedData));
|
if (expected != null) assert.ok(partialDeepEquals(res.data, expectedData));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,11 +36,13 @@ describe("getChapterNames", function () {
|
||||||
await insertChapter(db, chapterNames[0], { videoID: chapterNamesVid1, startTime: 60, endTime: 80 });
|
await insertChapter(db, chapterNames[0], { videoID: chapterNamesVid1, startTime: 60, endTime: 80 });
|
||||||
await insertChapter(db, chapterNames[1], { videoID: chapterNamesVid1, startTime: 70, endTime: 75 });
|
await insertChapter(db, chapterNames[1], { videoID: chapterNamesVid1, startTime: 70, endTime: 75 });
|
||||||
await insertChapter(db, chapterNames[2], { videoID: chapterNamesVid1, startTime: 71, endTime: 76 });
|
await insertChapter(db, chapterNames[2], { videoID: chapterNamesVid1, startTime: 71, endTime: 76 });
|
||||||
|
await insertChapter(db, chapterNames[3], { videoID: chapterNamesVid1, startTime: 72, endTime: 77 });
|
||||||
|
|
||||||
await insertVideoInfo(db, chapterNamesVid1, chapterChannelID);
|
await insertVideoInfo(db, chapterNamesVid1, chapterChannelID);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Search for 'weird'", () => nameSearch("weird", chapterNames[0]));
|
it("Search for 'weird' (2 results)", () => nameSearch("weird", chapterNames[0], 2));
|
||||||
it("Search for 'different'", () => nameSearch("different", chapterNames[1]));
|
it("Search for 'different' (1 result)", () => nameSearch("different", chapterNames[1], 1));
|
||||||
it("Search for 'something'", () => nameSearch("something", chapterNames[2]));
|
it("Search for 'something' (1 result)", () => nameSearch("something", chapterNames[2], 1));
|
||||||
|
it("Search for 'unrelated' (0 result)", () => nameSearch("unrelated", null, 0));
|
||||||
});
|
});
|
Loading…
Reference in a new issue