mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-12 06:27:10 +03:00
@@ -45,7 +45,7 @@ async function prepareCategorySegments(req: Request, videoID: VideoID, category:
|
|||||||
|
|
||||||
const filteredSegments = segments.filter((_, index) => shouldFilter[index]);
|
const filteredSegments = segments.filter((_, index) => shouldFilter[index]);
|
||||||
|
|
||||||
const maxSegments = getCategoryActionType(category) === CategoryActionType.Skippable ? 32 : 1;
|
const maxSegments = getCategoryActionType(category) === CategoryActionType.Skippable ? Infinity : 1;
|
||||||
return (await chooseSegments(filteredSegments, maxSegments)).map((chosenSegment) => ({
|
return (await chooseSegments(filteredSegments, maxSegments)).map((chosenSegment) => ({
|
||||||
category: chosenSegment.category,
|
category: chosenSegment.category,
|
||||||
actionType: chosenSegment.actionType,
|
actionType: chosenSegment.actionType,
|
||||||
@@ -55,6 +55,7 @@ async function prepareCategorySegments(req: Request, videoID: VideoID, category:
|
|||||||
votes: chosenSegment.votes,
|
votes: chosenSegment.votes,
|
||||||
videoDuration: chosenSegment.videoDuration,
|
videoDuration: chosenSegment.videoDuration,
|
||||||
userID: chosenSegment.userID,
|
userID: chosenSegment.userID,
|
||||||
|
description: chosenSegment.description
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +140,7 @@ async function getSegmentsFromDBByHash(hashedVideoIDPrefix: VideoIDHash, service
|
|||||||
const fetchFromDB = () => db
|
const fetchFromDB = () => db
|
||||||
.prepare(
|
.prepare(
|
||||||
"all",
|
"all",
|
||||||
`SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "reputation", "shadowHidden", "hashedVideoID", "timeSubmitted" FROM "sponsorTimes"
|
`SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "reputation", "shadowHidden", "hashedVideoID", "timeSubmitted", "description" FROM "sponsorTimes"
|
||||||
WHERE "hashedVideoID" LIKE ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`,
|
WHERE "hashedVideoID" LIKE ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`,
|
||||||
[`${hashedVideoIDPrefix}%`, service]
|
[`${hashedVideoIDPrefix}%`, service]
|
||||||
) as Promise<DBSegment[]>;
|
) as Promise<DBSegment[]>;
|
||||||
@@ -155,7 +156,7 @@ async function getSegmentsFromDBByVideoID(videoID: VideoID, service: Service): P
|
|||||||
const fetchFromDB = () => db
|
const fetchFromDB = () => db
|
||||||
.prepare(
|
.prepare(
|
||||||
"all",
|
"all",
|
||||||
`SELECT "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "reputation", "shadowHidden", "timeSubmitted" FROM "sponsorTimes"
|
`SELECT "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "reputation", "shadowHidden", "timeSubmitted", "description" FROM "sponsorTimes"
|
||||||
WHERE "videoID" = ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`,
|
WHERE "videoID" = ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`,
|
||||||
[videoID, service]
|
[videoID, service]
|
||||||
) as Promise<DBSegment[]>;
|
) as Promise<DBSegment[]>;
|
||||||
@@ -219,7 +220,7 @@ async function chooseSegments(segments: DBSegment[], max: number): Promise<DBSeg
|
|||||||
//1. As long as the segments' startTime fall inside the currentGroup, we keep adding them to that group
|
//1. As long as the segments' startTime fall inside the currentGroup, we keep adding them to that group
|
||||||
//2. If a segment starts after the end of the currentGroup (> cursor), no other segment will ever fall
|
//2. If a segment starts after the end of the currentGroup (> cursor), no other segment will ever fall
|
||||||
// inside that group (because they're sorted) so we can create a new one
|
// inside that group (because they're sorted) so we can create a new one
|
||||||
const overlappingSegmentsGroups: OverlappingSegmentGroup[] = [];
|
let overlappingSegmentsGroups: OverlappingSegmentGroup[] = [];
|
||||||
let currentGroup: OverlappingSegmentGroup;
|
let currentGroup: OverlappingSegmentGroup;
|
||||||
let cursor = -1; //-1 to make sure that, even if the 1st segment starts at 0, a new group is created
|
let cursor = -1; //-1 to make sure that, even if the 1st segment starts at 0, a new group is created
|
||||||
for (const segment of segments) {
|
for (const segment of segments) {
|
||||||
@@ -261,6 +262,8 @@ async function chooseSegments(segments: DBSegment[], max: number): Promise<DBSeg
|
|||||||
group.reputation = group.reputation / group.segments.length;
|
group.reputation = group.reputation / group.segments.length;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
overlappingSegmentsGroups = splitPercentOverlap(overlappingSegmentsGroups);
|
||||||
|
|
||||||
//if there are too many groups, find the best ones
|
//if there are too many groups, find the best ones
|
||||||
return getWeightedRandomChoice(overlappingSegmentsGroups, max).map(
|
return getWeightedRandomChoice(overlappingSegmentsGroups, max).map(
|
||||||
//randomly choose 1 good segment per group and return them
|
//randomly choose 1 good segment per group and return them
|
||||||
@@ -268,6 +271,74 @@ async function chooseSegments(segments: DBSegment[], max: number): Promise<DBSeg
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function splitPercentOverlap(groups: OverlappingSegmentGroup[], percent: number): OverlappingSegmentGroup[] {
|
||||||
|
const result: OverlappingSegmentGroup[] = [];
|
||||||
|
for (const group of groups) {
|
||||||
|
const segmentsLeftToCheck = [...group.segments];
|
||||||
|
while (segmentsLeftToCheck.length > 0) {
|
||||||
|
const currentGroup: OverlappingSegmentGroup = { segments: [], votes: 0, reputation: 0, locked: false, required: false };
|
||||||
|
|
||||||
|
const currentSegment = segmentsLeftToCheck.shift();
|
||||||
|
// TODO: extract out this part to be more generic
|
||||||
|
currentGroup.segments.push(currentSegment);
|
||||||
|
currentGroup.votes += currentSegment.votes;
|
||||||
|
currentGroup.reputation += currentSegment.reputation;
|
||||||
|
currentGroup.locked ||= currentSegment.locked;
|
||||||
|
currentGroup.required ||= currentSegment.required;
|
||||||
|
|
||||||
|
const currentDuration = currentSegment.endTime - currentSegment.startTime;
|
||||||
|
for (const [index, compareSegment] of segmentsLeftToCheck.entries()) {
|
||||||
|
const compareDuration = compareSegment.endTime - compareSegment.startTime;
|
||||||
|
const overlap = Math.min(currentSegment.endTime, compareSegment.endTime) - Math.max(currentSegment.startTime, compareSegment.startTime);
|
||||||
|
const overlapPercent = overlap / Math.max(currentDuration, compareDuration);
|
||||||
|
if (overlapPercent >= percent) {
|
||||||
|
currentGroup.segments.push(currentSegment);
|
||||||
|
currentGroup.votes += compareSegment.votes;
|
||||||
|
currentGroup.reputation += compareSegment.reputation;
|
||||||
|
currentGroup.locked ||= compareSegment.locked;
|
||||||
|
currentGroup.required ||= compareSegment.required;
|
||||||
|
segmentsLeftToCheck.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push(currentGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// function splitPercentOverlap(groups: OverlappingSegmentGroup[]): OverlappingSegmentGroup[] {
|
||||||
|
// return groups.flatMap((group) => {
|
||||||
|
// const result: OverlappingSegmentGroup[] = [];
|
||||||
|
// group.segments.forEach((segment) => {
|
||||||
|
// const bestGroup = result.find((group) => {
|
||||||
|
// // At least one segment in the group must have high % overlap or the same action type
|
||||||
|
// return group.segments.some((compareSegment) => {
|
||||||
|
// const overlap = Math.min(segment.endTime, compareSegment.endTime) - Math.max(segment.startTime, compareSegment.startTime);
|
||||||
|
// const overallDuration = Math.max(segment.endTime, compareSegment.endTime) - Math.min(segment.startTime, compareSegment.startTime);
|
||||||
|
// const overlapPercent = overlap / overallDuration;
|
||||||
|
// return (segment.actionType === compareSegment.actionType && segment.actionType !== ActionType.Chapter)
|
||||||
|
// || overlapPercent >= 0.6
|
||||||
|
// || (overlapPercent >= 0.8 && segment.actionType === ActionType.Chapter && compareSegment.actionType === ActionType.Chapter);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (bestGroup) {
|
||||||
|
// bestGroup.segments.push(segment);
|
||||||
|
// bestGroup.votes += segment.votes;
|
||||||
|
// bestGroup.reputation += segment.reputation;
|
||||||
|
// bestGroup.locked ||= segment.locked;
|
||||||
|
// bestGroup.required ||= segment.required;
|
||||||
|
// } else {
|
||||||
|
// result.push({ segments: [segment], votes: segment.votes, reputation: segment.reputation, locked: segment.locked, required: segment.required });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return result;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Returns what would be sent to the client.
|
* Returns what would be sent to the client.
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ export interface DBSegment {
|
|||||||
timeSubmitted: number;
|
timeSubmitted: number;
|
||||||
userAgent: string;
|
userAgent: string;
|
||||||
service: Service;
|
service: Service;
|
||||||
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OverlappingSegmentGroup {
|
export interface OverlappingSegmentGroup {
|
||||||
|
|||||||
@@ -6,23 +6,26 @@ import { client } from "../utils/httpClient";
|
|||||||
describe("getSkipSegments", () => {
|
describe("getSkipSegments", () => {
|
||||||
const endpoint = "/api/skipSegments";
|
const endpoint = "/api/skipSegments";
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "actionType", "service", "videoDuration", "hidden", "shadowHidden") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "actionType", "service", "videoDuration", "hidden", "shadowHidden", "description") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||||
await db.prepare("run", query, ["getSkipSegmentID0", 1, 11, 1, 0, "uuid01", "testman", 0, 50, "sponsor", "skip", "YouTube", 100, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentID0", 1, 11, 1, 0, "uuid01", "testman", 0, 50, "sponsor", "skip", "YouTube", 100, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentID0", 12, 14, 2, 0, "uuid02", "testman", 0, 50, "sponsor", "mute", "YouTube", 100, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentID0", 12, 14, 2, 0, "uuid02", "testman", 0, 50, "sponsor", "mute", "YouTube", 100, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentID0", 20, 33, 2, 0, "uuid03", "testman", 0, 50, "intro", "skip", "YouTube", 101, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentID0", 20, 33, 2, 0, "uuid03", "testman", 0, 50, "intro", "skip", "YouTube", 101, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentID1", 1, 11, 2, 0, "uuid10", "testman", 0, 50, "sponsor", "skip", "PeerTube", 120, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentID1", 1, 11, 2, 0, "uuid10", "testman", 0, 50, "sponsor", "skip", "PeerTube", 120, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentID2", 1, 11, 2, 1, "uuid20", "testman", 0, 50, "sponsor", "skip", "YouTube", 140, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentID2", 1, 11, 2, 1, "uuid20", "testman", 0, 50, "sponsor", "skip", "YouTube", 140, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentID3", 1, 11, 2, 0, "uuid30", "testman", 0, 50, "sponsor", "skip", "YouTube", 200, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentID3", 1, 11, 2, 0, "uuid30", "testman", 0, 50, "sponsor", "skip", "YouTube", 200, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentID3", 7, 22, -3, 0, "uuid31", "testman", 0, 50, "sponsor", "skip", "YouTube", 300, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentID3", 7, 22, -3, 0, "uuid31", "testman", 0, 50, "sponsor", "skip", "YouTube", 300, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentMultiple", 1, 11, 2, 0, "uuid40", "testman", 0, 50, "intro", "skip", "YouTube", 400, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentMultiple", 1, 11, 2, 0, "uuid40", "testman", 0, 50, "intro", "skip", "YouTube", 400, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentMultiple", 20, 33, 2, 0, "uuid41", "testman", 0, 50, "intro", "skip", "YouTube", 500, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentMultiple", 20, 33, 2, 0, "uuid41", "testman", 0, 50, "intro", "skip", "YouTube", 500, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentLocked", 20, 33, 2, 1, "uuid50", "testman", 0, 50, "intro", "skip", "YouTube", 230, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentLocked", 20, 33, 2, 1, "uuid50", "testman", 0, 50, "intro", "skip", "YouTube", 230, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentLocked", 20, 34, 100000, 0, "uuid51", "testman", 0, 50, "intro", "skip", "YouTube", 190, 0, 0]);
|
await db.prepare("run", query, ["getSkipSegmentLocked", 20, 34, 100000, 0, "uuid51", "testman", 0, 50, "intro", "skip", "YouTube", 190, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["getSkipSegmentID6", 20, 34, 100000, 0, "uuid60", "testman", 0, 50, "sponsor", "skip", "YouTube", 190, 1, 0]);
|
await db.prepare("run", query, ["getSkipSegmentID6", 20, 34, 100000, 0, "uuid60", "testman", 0, 50, "sponsor", "skip", "YouTube", 190, 1, 0, ""]);
|
||||||
await db.prepare("run", query, ["requiredSegmentVid", 60, 70, 2, 0, "requiredSegmentVid1", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, 0]);
|
await db.prepare("run", query, ["requiredSegmentVid", 60, 70, 2, 0, "requiredSegmentVid1", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["requiredSegmentVid", 60, 70, -2, 0, "requiredSegmentVid2", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, 0]);
|
await db.prepare("run", query, ["requiredSegmentVid", 60, 70, -2, 0, "requiredSegmentVid2", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["requiredSegmentVid", 80, 90, -2, 0, "requiredSegmentVid3", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, 0]);
|
await db.prepare("run", query, ["requiredSegmentVid", 80, 90, -2, 0, "requiredSegmentVid3", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, 0, ""]);
|
||||||
await db.prepare("run", query, ["requiredSegmentVid", 80, 90, 2, 0, "requiredSegmentVid4", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, 0]);
|
await db.prepare("run", query, ["requiredSegmentVid", 80, 90, 2, 0, "requiredSegmentVid4", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, 0, ""]);
|
||||||
|
await db.prepare("run", query, ["chapterVid", 60, 80, 2, 0, "chapterVid-1", "testman", 0, 50, "chapter", "chapter", "YouTube", 0, 0, 0, "Chapter 1"]);
|
||||||
|
await db.prepare("run", query, ["chapterVid", 70, 75, 2, 0, "chapterVid-2", "testman", 0, 50, "chapter", "chapter", "YouTube", 0, 0, 0, "Chapter 2"]);
|
||||||
|
await db.prepare("run", query, ["chapterVid", 71, 76, 2, 0, "chapterVid-3", "testman", 0, 50, "chapter", "chapter", "YouTube", 0, 0, 0, "Chapter 3"]);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -388,6 +391,33 @@ describe("getSkipSegments", () => {
|
|||||||
.catch(err => done(err));
|
.catch(err => done(err));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should be able to get overlapping chapter segments if very different", (done) => {
|
||||||
|
client.get(`${endpoint}?videoID=chapterVid&category=chapter&actionType=chapter`)
|
||||||
|
.then(res => {
|
||||||
|
assert.strictEqual(res.status, 200);
|
||||||
|
const data = res.data;
|
||||||
|
assert.strictEqual(data.length, 2);
|
||||||
|
const expected = [{
|
||||||
|
UUID: "chapterVid-1",
|
||||||
|
description: "Chapter 1"
|
||||||
|
}, {
|
||||||
|
UUID: "chapterVid-2",
|
||||||
|
description: "Chapter 2"
|
||||||
|
}];
|
||||||
|
const expected2 = [{
|
||||||
|
UUID: "chapterVid-1",
|
||||||
|
description: "Chapter 1"
|
||||||
|
}, {
|
||||||
|
UUID: "chapterVid-3",
|
||||||
|
description: "Chapter 3"
|
||||||
|
}];
|
||||||
|
|
||||||
|
assert.ok(partialDeepEquals(data, expected, false) || partialDeepEquals(data, expected2));
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(err => done(err));
|
||||||
|
});
|
||||||
|
|
||||||
it("Should get 400 if no videoID passed in", (done) => {
|
it("Should get 400 if no videoID passed in", (done) => {
|
||||||
client.get(endpoint)
|
client.get(endpoint)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
|||||||
@@ -16,20 +16,26 @@ describe("getSkipSegmentsByHash", () => {
|
|||||||
const getSegmentsByHash0Hash = "fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910";
|
const getSegmentsByHash0Hash = "fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910";
|
||||||
const requiredSegmentVidHash = "d51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61";
|
const requiredSegmentVidHash = "d51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61";
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "service", "hidden", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "service", "hidden", "shadowHidden", "hashedVideoID", "description") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||||
await db.prepare("run", query, ["getSegmentsByHash-0", 1, 10, 2, "getSegmentsByHash-01", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, getSegmentsByHash0Hash]);
|
await db.prepare("run", query, ["getSegmentsByHash-0", 1, 10, 2, "getSegmentsByHash-01", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, getSegmentsByHash0Hash, ""]);
|
||||||
await db.prepare("run", query, ["getSegmentsByHash-0", 1, 10, 2, "getSegmentsByHash-02", "testman", 0, 50, "sponsor", "skip", "PeerTube", 0, 0, getSegmentsByHash0Hash]);
|
await db.prepare("run", query, ["getSegmentsByHash-0", 1, 10, 2, "getSegmentsByHash-02", "testman", 0, 50, "sponsor", "skip", "PeerTube", 0, 0, getSegmentsByHash0Hash, ""]);
|
||||||
await db.prepare("run", query, ["getSegmentsByHash-0", 20, 30, 2, "getSegmentsByHash-03", "testman", 100, 150, "intro", "skip", "YouTube", 0, 0, getSegmentsByHash0Hash]);
|
await db.prepare("run", query, ["getSegmentsByHash-0", 20, 30, 2, "getSegmentsByHash-03", "testman", 100, 150, "intro", "skip", "YouTube", 0, 0, getSegmentsByHash0Hash, ""]);
|
||||||
await db.prepare("run", query, ["getSegmentsByHash-0", 40, 50, 2, "getSegmentsByHash-04", "testman", 0, 50, "sponsor", "mute", "YouTube", 0, 0, getSegmentsByHash0Hash]);
|
await db.prepare("run", query, ["getSegmentsByHash-0", 40, 50, 2, "getSegmentsByHash-04", "testman", 0, 50, "sponsor", "mute", "YouTube", 0, 0, getSegmentsByHash0Hash, ""]);
|
||||||
await db.prepare("run", query, ["getSegmentsByHash-noMatchHash", 40, 50, 2, "getSegmentsByHash-noMatchHash", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, "fdaffnoMatchHash"]);
|
await db.prepare("run", query, ["getSegmentsByHash-noMatchHash", 40, 50, 2, "getSegmentsByHash-noMatchHash", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, "fdaffnoMatchHash", ""]);
|
||||||
await db.prepare("run", query, ["getSegmentsByHash-1", 60, 70, 2, "getSegmentsByHash-1", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, "3272fa85ee0927f6073ef6f07ad5f3146047c1abba794cfa364d65ab9921692b"]);
|
await db.prepare("run", query, ["getSegmentsByHash-1", 60, 70, 2, "getSegmentsByHash-1", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, "3272fa85ee0927f6073ef6f07ad5f3146047c1abba794cfa364d65ab9921692b", ""]);
|
||||||
await db.prepare("run", query, ["onlyHidden", 60, 70, 2, "onlyHidden", "testman", 0, 50, "sponsor", "skip", "YouTube", 1, 0, "f3a199e1af001d716cdc6599360e2b062c2d2b3fa2885f6d9d2fd741166cbbd3"]);
|
await db.prepare("run", query, ["onlyHidden", 60, 70, 2, "onlyHidden", "testman", 0, 50, "sponsor", "skip", "YouTube", 1, 0, "f3a199e1af001d716cdc6599360e2b062c2d2b3fa2885f6d9d2fd741166cbbd3", ""]);
|
||||||
await db.prepare("run", query, ["highlightVid", 60, 60, 2, "highlightVid-1", "testman", 0, 50, "poi_highlight", "skip", "YouTube", 0, 0, getHash("highlightVid", 1)]);
|
await db.prepare("run", query, ["highlightVid", 60, 60, 2, "highlightVid-1", "testman", 0, 50, "poi_highlight", "skip", "YouTube", 0, 0, getHash("highlightVid", 1), ""]);
|
||||||
await db.prepare("run", query, ["highlightVid", 70, 70, 2, "highlightVid-2", "testman", 0, 50, "poi_highlight", "skip", "YouTube", 0, 0, getHash("highlightVid", 1)]);
|
await db.prepare("run", query, ["highlightVid", 70, 70, 2, "highlightVid-2", "testman", 0, 50, "poi_highlight", "skip", "YouTube", 0, 0, getHash("highlightVid", 1), ""]);
|
||||||
await db.prepare("run", query, ["requiredSegmentVid", 60, 70, 2, "requiredSegmentVid-1", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, requiredSegmentVidHash]);
|
await db.prepare("run", query, ["requiredSegmentVid", 60, 70, 2, "requiredSegmentVid-1", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, requiredSegmentVidHash, ""]);
|
||||||
await db.prepare("run", query, ["requiredSegmentVid", 60, 70, -2, "requiredSegmentVid-2", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, requiredSegmentVidHash]);
|
await db.prepare("run", query, ["requiredSegmentVid", 60, 70, -2, "requiredSegmentVid-2", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, requiredSegmentVidHash, ""]);
|
||||||
await db.prepare("run", query, ["requiredSegmentVid", 80, 90, -2, "requiredSegmentVid-3", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, requiredSegmentVidHash]);
|
await db.prepare("run", query, ["requiredSegmentVid", 80, 90, -2, "requiredSegmentVid-3", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, requiredSegmentVidHash, ""]);
|
||||||
await db.prepare("run", query, ["requiredSegmentVid", 80, 90, 2, "requiredSegmentVid-4", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, requiredSegmentVidHash]);
|
await db.prepare("run", query, ["requiredSegmentVid", 80, 90, 2, "requiredSegmentVid-4", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, requiredSegmentVidHash, ""]);
|
||||||
|
await db.prepare("run", query, ["chapterVid-hash", 60, 80, 2, "chapterVid-hash-1", "testman", 0, 50, "chapter", "chapter", "YouTube", 0, 0, getHash("chapterVid-hash", 1), "Chapter 1"]); //7258
|
||||||
|
await db.prepare("run", query, ["chapterVid-hash", 70, 75, 2, "chapterVid-hash-2", "testman", 0, 50, "chapter", "chapter", "YouTube", 0, 0, getHash("chapterVid-hash", 1), "Chapter 2"]); //7258
|
||||||
|
await db.prepare("run", query, ["chapterVid-hash", 71, 76, 2, "chapterVid-hash-3", "testman", 0, 50, "chapter", "chapter", "YouTube", 0, 0, getHash("chapterVid-hash", 1), "Chapter 3"]); //7258
|
||||||
|
await db.prepare("run", query, ["longMuteVid-hash", 40, 45, 2, "longMuteVid-hash-1", "testman", 0, 50, "sponsor", "skip", "YouTube", 0, 0, getHash("longMuteVid-hash", 1), ""]); //6613
|
||||||
|
await db.prepare("run", query, ["longMuteVid-hash", 2, 80, 2, "longMuteVid-hash-2", "testman", 0, 50, "sponsor", "mute", "YouTube", 0, 0, getHash("longMuteVid-hash", 1), ""]); //6613
|
||||||
|
await db.prepare("run", query, ["longMuteVid-hash", 3, 78, 2, "longMuteVid-hash-3", "testman", 0, 50, "sponsor", "mute", "YouTube", 0, 0, getHash("longMuteVid-hash", 1), ""]); //6613
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should be able to get a 200", (done) => {
|
it("Should be able to get a 200", (done) => {
|
||||||
@@ -356,4 +362,68 @@ describe("getSkipSegmentsByHash", () => {
|
|||||||
})
|
})
|
||||||
.catch(err => done(err));
|
.catch(err => done(err));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should be able to get overlapping chapter segments if very different", (done) => {
|
||||||
|
client.get(`${endpoint}/7258?category=chapter&actionType=chapter`)
|
||||||
|
.then(res => {
|
||||||
|
assert.strictEqual(res.status, 200);
|
||||||
|
const data = res.data;
|
||||||
|
assert.strictEqual(data.length, 1);
|
||||||
|
const expected = [{
|
||||||
|
segments: [{
|
||||||
|
UUID: "chapterVid-hash-1",
|
||||||
|
description: "Chapter 1"
|
||||||
|
}, {
|
||||||
|
UUID: "chapterVid-hash-2",
|
||||||
|
description: "Chapter 2"
|
||||||
|
}]
|
||||||
|
}];
|
||||||
|
const expected2 = [{
|
||||||
|
segments: [{
|
||||||
|
UUID: "chapterVid-hash-1",
|
||||||
|
description: "Chapter 1"
|
||||||
|
}, {
|
||||||
|
UUID: "chapterVid-hash-3",
|
||||||
|
description: "Chapter 3"
|
||||||
|
}]
|
||||||
|
}];
|
||||||
|
|
||||||
|
assert.ok(partialDeepEquals(data, expected, false) || partialDeepEquals(data, expected2));
|
||||||
|
assert.strictEqual(data[0].segments.length, 2);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(err => done(err));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should be able to get mute segment with small skip segment in middle", (done) => {
|
||||||
|
client.get(`${endpoint}/6613?actionType=skip&actionType=mute`)
|
||||||
|
.then(res => {
|
||||||
|
assert.strictEqual(res.status, 200);
|
||||||
|
const data = res.data;
|
||||||
|
assert.strictEqual(data.length, 1);
|
||||||
|
const expected = [{
|
||||||
|
segments: [{
|
||||||
|
UUID: "longMuteVid-hash-2",
|
||||||
|
actionType: "mute"
|
||||||
|
}, {
|
||||||
|
UUID: "longMuteVid-hash-1",
|
||||||
|
actionType: "skip"
|
||||||
|
}]
|
||||||
|
}];
|
||||||
|
const expected2 = [{
|
||||||
|
segments: [{
|
||||||
|
UUID: "longMuteVid-hash-3",
|
||||||
|
actionType: "mute"
|
||||||
|
}, {
|
||||||
|
UUID: "longMuteVid-hash-1",
|
||||||
|
actionType: "skip"
|
||||||
|
}]
|
||||||
|
}];
|
||||||
|
|
||||||
|
assert.ok(partialDeepEquals(data, expected, false) || partialDeepEquals(data, expected2));
|
||||||
|
assert.strictEqual(data[0].segments.length, 2);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(err => done(err));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ export const partialDeepEquals = (actual: Record<string, any>, expected: Record<
|
|||||||
if (print) printActualExpected(actual, expected);
|
if (print) printActualExpected(actual, expected);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else if (actual?.[key] !== value) {
|
||||||
else if (actual?.[key] !== value) {
|
|
||||||
if (print) printActualExpected(actual, expected);
|
if (print) printActualExpected(actual, expected);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user