Combine action type segments when sorting overlapping

This commit is contained in:
Ajay Ramachandran
2021-07-06 00:57:57 -04:00
parent 35e1cf5733
commit 48349070b3
3 changed files with 21 additions and 21 deletions

View File

@@ -12,7 +12,7 @@ import { QueryCacher } from '../utils/queryCacher';
import { getReputation } from '../utils/reputation'; import { getReputation } from '../utils/reputation';
async function prepareCategorySegments(req: Request, videoID: VideoID, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise<Segment[]> { async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[],cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise<Segment[]> {
const shouldFilter: boolean[] = await Promise.all(segments.map(async (segment) => { const shouldFilter: boolean[] = await Promise.all(segments.map(async (segment) => {
if (segment.votes < -1 && !segment.required) { if (segment.votes < -1 && !segment.required) {
return false; //too untrustworthy, just ignore it return false; //too untrustworthy, just ignore it
@@ -41,7 +41,7 @@ async function prepareCategorySegments(req: Request, videoID: VideoID, segments:
const filteredSegments = segments.filter((_, index) => shouldFilter[index]); const filteredSegments = segments.filter((_, index) => shouldFilter[index]);
const maxSegments = getCategoryActionType(segments[0]?.category) === CategoryActionType.Skippable ? 32 : 1; const maxSegments = getCategoryActionType(category) === CategoryActionType.Skippable ? 32 : 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,
@@ -60,20 +60,20 @@ async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories:
categories = categories.filter((category) => !/[^a-z|_|-]/.test(category)); categories = categories.filter((category) => !/[^a-z|_|-]/.test(category));
if (categories.length === 0) return null; if (categories.length === 0) return null;
const segmentsByType: SBRecord<string, DBSegment[]> = (await getSegmentsFromDBByVideoID(videoID, service)) const segmentsByCategory: SBRecord<Category, DBSegment[]> = (await getSegmentsFromDBByVideoID(videoID, service))
.filter((segment: DBSegment) => categories.includes(segment?.category) && actionTypes.includes(segment?.actionType)) .filter((segment: DBSegment) => categories.includes(segment?.category) && actionTypes.includes(segment?.actionType))
.reduce((acc: SBRecord<Category, DBSegment[]>, segment: DBSegment) => { .reduce((acc: SBRecord<Category, DBSegment[]>, segment: DBSegment) => {
if (requiredSegments.includes(segment.UUID)) segment.required = true; if (requiredSegments.includes(segment.UUID)) segment.required = true;
acc[segment.category + segment.actionType] ??= []; acc[segment.category] ??= [];
acc[segment.category + segment.actionType].push(segment); acc[segment.category].push(segment);
return acc; return acc;
}, {}); }, {});
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [_key, typeSegments] of Object.entries(segmentsByType)) { for (const [category, categorySegments] of Object.entries(segmentsByCategory)) {
segments.push(...(await prepareCategorySegments(req, videoID, typeSegments, cache))); segments.push(...(await prepareCategorySegments(req, videoID, category as Category, categorySegments, cache)));
} }
return segments; return segments;
@@ -91,7 +91,7 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash,
const segments: SBRecord<VideoID, VideoData> = {}; const segments: SBRecord<VideoID, VideoData> = {};
try { try {
type SegmentWithHashPerVideoID = SBRecord<VideoID, {hash: VideoIDHash, segmentPerType: SBRecord<string, DBSegment[]>}>; type SegmentWithHashPerVideoID = SBRecord<VideoID, {hash: VideoIDHash, segmentPerCategory: SBRecord<Category, DBSegment[]>}>;
categories = categories.filter((category) => !(/[^a-z|_|-]/.test(category))); categories = categories.filter((category) => !(/[^a-z|_|-]/.test(category)));
if (categories.length === 0) return null; if (categories.length === 0) return null;
@@ -101,12 +101,12 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash,
.reduce((acc: SegmentWithHashPerVideoID, segment: DBSegment) => { .reduce((acc: SegmentWithHashPerVideoID, segment: DBSegment) => {
acc[segment.videoID] = acc[segment.videoID] || { acc[segment.videoID] = acc[segment.videoID] || {
hash: segment.hashedVideoID, hash: segment.hashedVideoID,
segmentPerType: {} segmentPerCategory: {}
}; };
if (requiredSegments.includes(segment.UUID)) segment.required = true; if (requiredSegments.includes(segment.UUID)) segment.required = true;
acc[segment.videoID].segmentPerType[segment.category + segment.actionType] ??= []; acc[segment.videoID].segmentPerCategory[segment.category] ??= [];
acc[segment.videoID].segmentPerType[segment.category + segment.actionType].push(segment); acc[segment.videoID].segmentPerCategory[segment.category].push(segment);
return acc; return acc;
}, {}); }, {});
@@ -118,8 +118,8 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash,
}; };
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [_key, segmentPerType] of Object.entries(videoData.segmentPerType)) { for (const [category, segmentPerCategory] of Object.entries(videoData.segmentPerCategory)) {
segments[videoID].segments.push(...(await prepareCategorySegments(req, videoID as VideoID, segmentPerType, cache))); segments[videoID].segments.push(...(await prepareCategorySegments(req, videoID as VideoID, category as Category, segmentPerCategory, cache)));
} }
} }

View File

@@ -7,8 +7,8 @@ describe('getSkipSegments', () => {
before(async () => { before(async () => {
const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", views, category, "actionType", "service", "videoDuration", "hidden", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", views, category, "actionType", "service", "videoDuration", "hidden", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
await db.prepare("run", query, ['testtesttest', 1, 11, 2, 0, '1-uuid-0', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 100, 0, 0, getHash('testtesttest', 1)]); await db.prepare("run", query, ['testtesttest', 1, 11, 2, 0, '1-uuid-0', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 100, 0, 0, getHash('testtesttest', 1)]);
await db.prepare("run", query, ['testtesttest', 1, 11, 2, 0, '1-uuid-0-0-1', 'testman', 0, 50, 'sponsor', 'mute', 'YouTube', 100, 0, 0, getHash('testtesttest', 1)]);
await db.prepare("run", query, ['testtesttest2', 1, 11, 2, 0, '1-uuid-0-1', 'testman', 0, 50, 'sponsor', 'skip', 'PeerTube', 120, 0, 0, getHash('testtesttest2', 1)]); await db.prepare("run", query, ['testtesttest2', 1, 11, 2, 0, '1-uuid-0-1', 'testman', 0, 50, 'sponsor', 'skip', 'PeerTube', 120, 0, 0, getHash('testtesttest2', 1)]);
await db.prepare("run", query, ['testtesttest', 12, 14, 2, 0, '1-uuid-0-2', 'testman', 0, 50, 'sponsor', 'mute', 'YouTube', 100, 0, 0, getHash('testtesttest', 1)]);
await db.prepare("run", query, ['testtesttest', 20, 33, 2, 0, '1-uuid-2', 'testman', 0, 50, 'intro', 'skip', 'YouTube', 101, 0, 0, getHash('testtesttest', 1)]); await db.prepare("run", query, ['testtesttest', 20, 33, 2, 0, '1-uuid-2', 'testman', 0, 50, 'intro', 'skip', 'YouTube', 101, 0, 0, getHash('testtesttest', 1)]);
await db.prepare("run", query, ['testtesttest,test', 1, 11, 2, 0, '1-uuid-1', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 140, 0, 0, getHash('testtesttest,test', 1)]); await db.prepare("run", query, ['testtesttest,test', 1, 11, 2, 0, '1-uuid-1', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 140, 0, 0, getHash('testtesttest,test', 1)]);
await db.prepare("run", query, ['test3', 1, 11, 2, 0, '1-uuid-4', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 200, 0, 0, getHash('test3', 1)]); await db.prepare("run", query, ['test3', 1, 11, 2, 0, '1-uuid-4', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 200, 0, 0, getHash('test3', 1)]);
@@ -49,8 +49,8 @@ describe('getSkipSegments', () => {
if (res.status !== 200) done("Status code was: " + res.status); if (res.status !== 200) done("Status code was: " + res.status);
else { else {
const data = await res.json(); const data = await res.json();
if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 if (data.length === 1 && data[0].segment[0] === 12 && data[0].segment[1] === 14
&& data[0].category === "sponsor" && data[0].UUID === "1-uuid-0-0-1" && data[0].videoDuration === 100) { && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0-2" && data[0].videoDuration === 100) {
done(); done();
} else { } else {
done("Received incorrect body: " + (await res.text())); done("Received incorrect body: " + (await res.text()));
@@ -68,7 +68,7 @@ describe('getSkipSegments', () => {
const data = await res.json(); const data = await res.json();
if (data.length === 2 && data[0].segment[0] === 1 && data[0].segment[1] === 11 if (data.length === 2 && data[0].segment[0] === 1 && data[0].segment[1] === 11
&& data[0].category === "sponsor" && data[0].UUID === "1-uuid-0" && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0"
&& data[1].UUID === "1-uuid-0-0-1" && data[0].videoDuration === 100) { && data[1].UUID === "1-uuid-0-2" && data[0].videoDuration === 100) {
done(); done();
} else { } else {
done("Received incorrect body: " + (await res.text())); done("Received incorrect body: " + (await res.text()));
@@ -86,7 +86,7 @@ describe('getSkipSegments', () => {
const data = await res.json(); const data = await res.json();
if (data.length === 2 && data[0].segment[0] === 1 && data[0].segment[1] === 11 if (data.length === 2 && data[0].segment[0] === 1 && data[0].segment[1] === 11
&& data[0].category === "sponsor" && data[0].UUID === "1-uuid-0" && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0"
&& data[1].UUID === "1-uuid-0-0-1" && data[0].videoDuration === 100) { && data[1].UUID === "1-uuid-0-2" && data[0].videoDuration === 100) {
done(); done();
} else { } else {
done("Received incorrect body: " + (await res.text())); done("Received incorrect body: " + (await res.text()));

View File

@@ -14,9 +14,9 @@ describe('getSegmentsByHash', () => {
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") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
await db.prepare("run", query, ['getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']); await db.prepare("run", query, ['getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']);
await db.prepare("run", query, ['getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0-0-1', 'testman', 0, 50, 'sponsor', 'mute', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']);
await db.prepare("run", query, ['getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0-1', 'testman', 0, 50, 'sponsor', 'skip', 'PeerTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']); await db.prepare("run", query, ['getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0-1', 'testman', 0, 50, 'sponsor', 'skip', 'PeerTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']);
await db.prepare("run", query, ['getSegmentsByHash-0', 20, 30, 2, 'getSegmentsByHash-0-1', 'testman', 100, 150, 'intro', 'skip', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']); await db.prepare("run", query, ['getSegmentsByHash-0', 20, 30, 2, 'getSegmentsByHash-0-1', 'testman', 100, 150, 'intro', 'skip', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']);
await db.prepare("run", query, ['getSegmentsByHash-0', 40, 50, 2, 'getSegmentsByHash-0-2', 'testman', 0, 50, 'sponsor', 'mute', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']);
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']);
@@ -188,7 +188,7 @@ describe('getSegmentsByHash', () => {
else if (body[1].segments.length !== 1) done("expected 1 segments for second video, got " + body[1].segments.length); else if (body[1].segments.length !== 1) done("expected 1 segments for second video, got " + body[1].segments.length);
else if (body[0].segments[0].category !== 'sponsor' else if (body[0].segments[0].category !== 'sponsor'
|| body[0].segments[0].UUID !== 'getSegmentsByHash-0-0' || body[0].segments[0].UUID !== 'getSegmentsByHash-0-0'
|| body[0].segments[1].UUID !== 'getSegmentsByHash-0-0-0-1' || body[0].segments[1].UUID !== 'getSegmentsByHash-0-2'
|| body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor"); || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor");
else done(); else done();
} }
@@ -207,7 +207,7 @@ describe('getSegmentsByHash', () => {
else if (body[1].segments.length !== 1) done("expected 1 segments for second video, got " + body[1].segments.length); else if (body[1].segments.length !== 1) done("expected 1 segments for second video, got " + body[1].segments.length);
else if (body[0].segments[0].category !== 'sponsor' else if (body[0].segments[0].category !== 'sponsor'
|| body[0].segments[0].UUID !== 'getSegmentsByHash-0-0' || body[0].segments[0].UUID !== 'getSegmentsByHash-0-0'
|| body[0].segments[1].UUID !== 'getSegmentsByHash-0-0-0-1' || body[0].segments[1].UUID !== 'getSegmentsByHash-0-2'
|| body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor"); || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor");
else done(); else done();
} }