From d20320e87e67ef890f5b986f1a72beea72c38842 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sun, 4 Jul 2021 18:35:15 -0400 Subject: [PATCH 1/7] Add post for actionType untested --- databases/_upgrade_sponsorTimes_18.sql | 32 ++++++++++++++++++++++++++ src/routes/postSkipSegments.ts | 19 ++++++++++----- src/types/segments.model.ts | 6 +++++ 3 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 databases/_upgrade_sponsorTimes_18.sql diff --git a/databases/_upgrade_sponsorTimes_18.sql b/databases/_upgrade_sponsorTimes_18.sql new file mode 100644 index 0000000..5b524ab --- /dev/null +++ b/databases/_upgrade_sponsorTimes_18.sql @@ -0,0 +1,32 @@ +BEGIN TRANSACTION; + +/* Add actionType field */ +CREATE TABLE "sqlb_temp_table_18" ( + "videoID" TEXT NOT NULL, + "startTime" REAL NOT NULL, + "endTime" REAL NOT NULL, + "votes" INTEGER NOT NULL, + "locked" INTEGER NOT NULL default '0', + "incorrectVotes" INTEGER NOT NULL default '1', + "UUID" TEXT NOT NULL UNIQUE, + "userID" TEXT NOT NULL, + "timeSubmitted" INTEGER NOT NULL, + "views" INTEGER NOT NULL, + "category" TEXT NOT NULL DEFAULT 'sponsor', + "actionType" TEXT NOT NULL DEFAULT 'skip', + "service" TEXT NOT NULL DEFAULT 'YouTube', + "videoDuration" REAL NOT NULL DEFAULT '0', + "hidden" INTEGER NOT NULL DEFAULT '0', + "reputation" REAL NOT NULL DEFAULT 0, + "shadowHidden" INTEGER NOT NULL, + "hashedVideoID" TEXT NOT NULL default '' +); + +INSERT INTO sqlb_temp_table_18 SELECT "videoID","startTime","endTime","votes","locked","incorrectVotes","UUID","userID","timeSubmitted","views","category",'skip',"service","videoDuration","hidden","reputation","shadowHidden","hashedVideoID" FROM "sponsorTimes"; + +DROP TABLE "sponsorTimes"; +ALTER TABLE sqlb_temp_table_18 RENAME TO "sponsorTimes"; + +UPDATE "config" SET value = 18 WHERE key = 'version'; + +COMMIT; \ No newline at end of file diff --git a/src/routes/postSkipSegments.ts b/src/routes/postSkipSegments.ts index 94c6a07..bf1e769 100644 --- a/src/routes/postSkipSegments.ts +++ b/src/routes/postSkipSegments.ts @@ -10,7 +10,7 @@ import {getFormattedTime} from '../utils/getFormattedTime'; import {isUserTrustworthy} from '../utils/isUserTrustworthy'; import {dispatchEvent} from '../utils/webhookUtils'; import {Request, Response} from 'express'; -import { Category, CategoryActionType, IncomingSegment, SegmentUUID, Service, VideoDuration, VideoID } from '../types/segments.model'; +import { ActionType, Category, CategoryActionType, IncomingSegment, SegmentUUID, Service, VideoDuration, VideoID } from '../types/segments.model'; import { deleteLockCategories } from './deleteLockCategories'; import { getCategoryActionType } from '../utils/categoryInfo'; import { QueryCacher } from '../utils/queryCacher'; @@ -315,7 +315,7 @@ export async function postSkipSegments(req: Request, res: Response): Promise val == service)) { + if (!Object.values(Service).some((val) => val === service)) { service = Service.YouTube; } let videoDuration: VideoDuration = (parseFloat(req.query.videoDuration || req.body.videoDuration) || 0) as VideoDuration; @@ -325,9 +325,16 @@ export async function postSkipSegments(req: Request, res: Response): Promise { + if (!Object.values(ActionType).some((val) => val === segment.actionType)){ + segment.actionType = ActionType.Skip; + } + }); const invalidFields = []; if (typeof videoID !== 'string') { @@ -518,9 +525,9 @@ export async function postSkipSegments(req: Request, res: Response): Promise Date: Mon, 5 Jul 2021 13:23:31 -0400 Subject: [PATCH 2/7] Add action type to getSkipSegments --- src/routes/getSkipSegments.ts | 64 ++++++++++++++++++----------- src/routes/getSkipSegmentsByHash.ts | 20 ++++++++- src/types/segments.model.ts | 2 + src/utils/redisKeys.ts | 4 +- 4 files changed, 62 insertions(+), 28 deletions(-) diff --git a/src/routes/getSkipSegments.ts b/src/routes/getSkipSegments.ts index 8f78b5d..d671b00 100644 --- a/src/routes/getSkipSegments.ts +++ b/src/routes/getSkipSegments.ts @@ -3,7 +3,7 @@ import { config } from '../config'; import { db, privateDB } from '../databases/databases'; import { skipSegmentsHashKey, skipSegmentsKey } from '../utils/redisKeys'; import { SBRecord } from '../types/lib.model'; -import { Category, CategoryActionType, DBSegment, HashedIP, IPAddress, OverlappingSegmentGroup, Segment, SegmentCache, SegmentUUID, Service, VideoData, VideoID, VideoIDHash, Visibility, VotableObject } from "../types/segments.model"; +import { ActionType, Category, CategoryActionType, DBSegment, HashedIP, IPAddress, OverlappingSegmentGroup, Segment, SegmentCache, SegmentUUID, Service, VideoData, VideoID, VideoIDHash, Visibility, VotableObject } from "../types/segments.model"; import { getCategoryActionType } from '../utils/categoryInfo'; import { getHash } from '../utils/getHash'; import { getIP } from '../utils/getIP'; @@ -12,7 +12,7 @@ import { QueryCacher } from '../utils/queryCacher'; import { getReputation } from '../utils/reputation'; -async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise { +async function prepareCategorySegments(req: Request, videoID: VideoID, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise { const shouldFilter: boolean[] = await Promise.all(segments.map(async (segment) => { if (segment.votes < -1 && !segment.required) { return false; //too untrustworthy, just ignore it @@ -41,16 +41,18 @@ async function prepareCategorySegments(req: Request, videoID: VideoID, category: const filteredSegments = segments.filter((_, index) => shouldFilter[index]); - const maxSegments = getCategoryActionType(category) === CategoryActionType.Skippable ? 32 : 1; + const maxSegments = getCategoryActionType(segments[0]?.category) === CategoryActionType.Skippable ? 32 : 1; return (await chooseSegments(filteredSegments, maxSegments)).map((chosenSegment) => ({ - category, + category: chosenSegment.category, + actionType: chosenSegment.actionType, segment: [chosenSegment.startTime, chosenSegment.endTime], UUID: chosenSegment.UUID, videoDuration: chosenSegment.videoDuration })); } -async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories: Category[], requiredSegments: SegmentUUID[], service: Service): Promise { +async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories: Category[], + actionTypes: ActionType[], requiredSegments: SegmentUUID[], service: Service): Promise { const cache: SegmentCache = {shadowHiddenSegmentIPs: {}}; const segments: Segment[] = []; @@ -58,19 +60,20 @@ async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories: categories = categories.filter((category) => !/[^a-z|_|-]/.test(category)); if (categories.length === 0) return null; - const segmentsByCategory: SBRecord = (await getSegmentsFromDBByVideoID(videoID, service)) - .filter((segment: DBSegment) => categories.includes(segment?.category)) + const segmentsByType: SBRecord = (await getSegmentsFromDBByVideoID(videoID, service)) + .filter((segment: DBSegment) => categories.includes(segment?.category) && actionTypes.includes(segment?.actionType)) .reduce((acc: SBRecord, segment: DBSegment) => { if (requiredSegments.includes(segment.UUID)) segment.required = true; - acc[segment.category] = acc[segment.category] || []; - acc[segment.category].push(segment); + acc[segment.category + segment.actionType] ??= []; + acc[segment.category + segment.actionType].push(segment); return acc; }, {}); - for (const [category, categorySegments] of Object.entries(segmentsByCategory)) { - segments.push(...(await prepareCategorySegments(req, videoID, category as Category, categorySegments, cache))); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const [_key, typeSegments] of Object.entries(segmentsByType)) { + segments.push(...(await prepareCategorySegments(req, videoID, typeSegments, cache))); } return segments; @@ -82,28 +85,28 @@ async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories: } } -async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categories: Category[], requiredSegments: SegmentUUID[], service: Service): Promise> { +async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, categories: Category[], + actionTypes: ActionType[], requiredSegments: SegmentUUID[], service: Service): Promise> { const cache: SegmentCache = {shadowHiddenSegmentIPs: {}}; const segments: SBRecord = {}; try { - type SegmentWithHashPerVideoID = SBRecord}>; + type SegmentWithHashPerVideoID = SBRecord}>; categories = categories.filter((category) => !(/[^a-z|_|-]/.test(category))); if (categories.length === 0) return null; const segmentPerVideoID: SegmentWithHashPerVideoID = (await getSegmentsFromDBByHash(hashedVideoIDPrefix, service)) - .filter((segment: DBSegment) => categories.includes(segment?.category)) + .filter((segment: DBSegment) => categories.includes(segment?.category) && actionTypes.includes(segment?.actionType)) .reduce((acc: SegmentWithHashPerVideoID, segment: DBSegment) => { acc[segment.videoID] = acc[segment.videoID] || { hash: segment.hashedVideoID, - segmentPerCategory: {}, + segmentPerType: {} }; if (requiredSegments.includes(segment.UUID)) segment.required = true; - const videoCategories = acc[segment.videoID].segmentPerCategory; - videoCategories[segment.category] = videoCategories[segment.category] || []; - videoCategories[segment.category].push(segment); + acc[segment.videoID].segmentPerType[segment.category + segment.actionType] ??= []; + acc[segment.videoID].segmentPerType[segment.category + segment.actionType].push(segment); return acc; }, {}); @@ -114,8 +117,9 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, segments: [], }; - for (const [category, segmentPerCategory] of Object.entries(videoData.segmentPerCategory)) { - segments[videoID].segments.push(...(await prepareCategorySegments(req, videoID as VideoID, category as Category, segmentPerCategory, cache))); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const [_key, segmentPerType] of Object.entries(videoData.segmentPerType)) { + segments[videoID].segments.push(...(await prepareCategorySegments(req, videoID as VideoID, segmentPerType, cache))); } } @@ -132,7 +136,7 @@ async function getSegmentsFromDBByHash(hashedVideoIDPrefix: VideoIDHash, service const fetchFromDB = () => db .prepare( 'all', - `SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "videoDuration", "reputation", "shadowHidden", "hashedVideoID" FROM "sponsorTimes" + `SELECT "videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "reputation", "shadowHidden", "hashedVideoID" FROM "sponsorTimes" WHERE "hashedVideoID" LIKE ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`, [hashedVideoIDPrefix + '%', service] ) as Promise; @@ -148,7 +152,7 @@ async function getSegmentsFromDBByVideoID(videoID: VideoID, service: Service): P const fetchFromDB = () => db .prepare( 'all', - `SELECT "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "videoDuration", "reputation", "shadowHidden" FROM "sponsorTimes" + `SELECT "startTime", "endTime", "votes", "locked", "UUID", "userID", "category", "actionType", "videoDuration", "reputation", "shadowHidden" FROM "sponsorTimes" WHERE "videoID" = ? AND "service" = ? AND "hidden" = 0 ORDER BY "startTime"`, [videoID, service] ) as Promise; @@ -275,7 +279,7 @@ async function handleGetSegments(req: Request, res: Response): Promise { let hashPrefix = req.params.prefix as VideoIDHash; @@ -26,6 +26,22 @@ export async function getSkipSegmentsByHash(req: Request, res: Response): Promis return res.status(400).send("Bad parameter: categories (invalid JSON)"); } + let actionTypes: ActionType[] = []; + try { + actionTypes = req.query.actionTypes + ? JSON.parse(req.query.actionTypes as string) + : req.query.actionType + ? Array.isArray(req.query.actionType) + ? req.query.actionType + : [req.query.actionType] + : [ActionType.Skip]; + if (!Array.isArray(actionTypes)) { + return res.status(400).send("actionTypes parameter does not match format requirements."); + } + } catch(error) { + return res.status(400).send("Bad parameter: actionTypes (invalid JSON)"); + } + let requiredSegments: SegmentUUID[] = []; try { requiredSegments = req.query.requiredSegments @@ -51,7 +67,7 @@ export async function getSkipSegmentsByHash(req: Request, res: Response): Promis categories = categories.filter((item: any) => typeof item === "string"); // Get all video id's that match hash prefix - const segments = await getSegmentsByHash(req, hashPrefix, categories, requiredSegments, service); + const segments = await getSegmentsByHash(req, hashPrefix, categories, actionTypes, requiredSegments, service); if (!segments) return res.status(404).json([]); diff --git a/src/types/segments.model.ts b/src/types/segments.model.ts index 98abf4b..9d72829 100644 --- a/src/types/segments.model.ts +++ b/src/types/segments.model.ts @@ -34,6 +34,7 @@ export interface IncomingSegment { export interface Segment { category: Category; + actionType: ActionType; segment: number[]; UUID: SegmentUUID; videoDuration: VideoDuration; @@ -46,6 +47,7 @@ export enum Visibility { export interface DBSegment { category: Category; + actionType: ActionType; startTime: number; endTime: number; UUID: SegmentUUID; diff --git a/src/utils/redisKeys.ts b/src/utils/redisKeys.ts index fde37f3..fe37691 100644 --- a/src/utils/redisKeys.ts +++ b/src/utils/redisKeys.ts @@ -3,14 +3,14 @@ import { UserID } from "../types/user.model"; import { Logger } from "./logger"; export function skipSegmentsKey(videoID: VideoID, service: Service): string { - return "segments." + service + ".videoID." + videoID; + return "segments.v2." + service + ".videoID." + videoID; } export function skipSegmentsHashKey(hashedVideoIDPrefix: VideoIDHash, service: Service): string { hashedVideoIDPrefix = hashedVideoIDPrefix.substring(0, 4) as VideoIDHash; if (hashedVideoIDPrefix.length !== 4) Logger.warn("Redis skip segment hash-prefix key is not length 4! " + hashedVideoIDPrefix); - return "segments." + service + "." + hashedVideoIDPrefix; + return "segments.v2." + service + "." + hashedVideoIDPrefix; } export function reputationKey(userID: UserID): string { From 28e7ec0ef939a9e5cbf8eb37fe392a0b68c61be4 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 5 Jul 2021 13:26:49 -0400 Subject: [PATCH 3/7] Change db upgrade to v19 --- ...e_sponsorTimes_18.sql => _upgrade_sponsorTimes_19.sql} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename databases/{_upgrade_sponsorTimes_18.sql => _upgrade_sponsorTimes_19.sql} (81%) diff --git a/databases/_upgrade_sponsorTimes_18.sql b/databases/_upgrade_sponsorTimes_19.sql similarity index 81% rename from databases/_upgrade_sponsorTimes_18.sql rename to databases/_upgrade_sponsorTimes_19.sql index 5b524ab..24a0e60 100644 --- a/databases/_upgrade_sponsorTimes_18.sql +++ b/databases/_upgrade_sponsorTimes_19.sql @@ -1,7 +1,7 @@ BEGIN TRANSACTION; /* Add actionType field */ -CREATE TABLE "sqlb_temp_table_18" ( +CREATE TABLE "sqlb_temp_table_19" ( "videoID" TEXT NOT NULL, "startTime" REAL NOT NULL, "endTime" REAL NOT NULL, @@ -22,11 +22,11 @@ CREATE TABLE "sqlb_temp_table_18" ( "hashedVideoID" TEXT NOT NULL default '' ); -INSERT INTO sqlb_temp_table_18 SELECT "videoID","startTime","endTime","votes","locked","incorrectVotes","UUID","userID","timeSubmitted","views","category",'skip',"service","videoDuration","hidden","reputation","shadowHidden","hashedVideoID" FROM "sponsorTimes"; +INSERT INTO sqlb_temp_table_19 SELECT "videoID","startTime","endTime","votes","locked","incorrectVotes","UUID","userID","timeSubmitted","views","category",'skip',"service","videoDuration","hidden","reputation","shadowHidden","hashedVideoID" FROM "sponsorTimes"; DROP TABLE "sponsorTimes"; -ALTER TABLE sqlb_temp_table_18 RENAME TO "sponsorTimes"; +ALTER TABLE sqlb_temp_table_19 RENAME TO "sponsorTimes"; -UPDATE "config" SET value = 18 WHERE key = 'version'; +UPDATE "config" SET value = 19 WHERE key = 'version'; COMMIT; \ No newline at end of file From be006403eda3cecb0dee1d293b78bb7384feb122 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 6 Jul 2021 00:11:04 -0400 Subject: [PATCH 4/7] Add tests for getting segment by hash --- test/cases/getSkipSegmentsByHash.ts | 84 ++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 13 deletions(-) diff --git a/test/cases/getSkipSegmentsByHash.ts b/test/cases/getSkipSegmentsByHash.ts index e2891ab..6796345 100644 --- a/test/cases/getSkipSegmentsByHash.ts +++ b/test/cases/getSkipSegmentsByHash.ts @@ -12,19 +12,20 @@ sinonStub.callsFake(YouTubeApiMock.listVideos); describe('getSegmentsByHash', () => { before(async () => { - const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "service", "hidden", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; - await db.prepare("run", query, ['getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']); - await db.prepare("run", query, ['getSegmentsByHash-0', 1, 10, 2, 'getSegmentsByHash-0-0-1', 'testman', 0, 50, 'sponsor', 'PeerTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']); - await db.prepare("run", query, ['getSegmentsByHash-0', 20, 30, 2, 'getSegmentsByHash-0-1', 'testman', 100, 150, 'intro', 'YouTube', 0, 0, 'fdaff4dee1043451faa7398324fb63d8618ebcd11bddfe0491c488db12c6c910']); - await db.prepare("run", query, ['getSegmentsByHash-noMatchHash', 40, 50, 2, 'getSegmentsByHash-noMatchHash', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'fdaffnoMatchHash']); - await db.prepare("run", query, ['getSegmentsByHash-1', 60, 70, 2, 'getSegmentsByHash-1', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, '3272fa85ee0927f6073ef6f07ad5f3146047c1abba794cfa364d65ab9921692b']); - await db.prepare("run", query, ['onlyHidden', 60, 70, 2, 'onlyHidden', 'testman', 0, 50, 'sponsor', 'YouTube', 1, 0, 'f3a199e1af001d716cdc6599360e2b062c2d2b3fa2885f6d9d2fd741166cbbd3']); - await db.prepare("run", query, ['highlightVid', 60, 60, 2, 'highlightVid-1', 'testman', 0, 50, 'highlight', 'YouTube', 0, 0, getHash('highlightVid', 1)]); - await db.prepare("run", query, ['highlightVid', 70, 70, 2, 'highlightVid-2', 'testman', 0, 50, 'highlight', 'YouTube', 0, 0, getHash('highlightVid', 1)]); - await db.prepare("run", query, ['requiredSegmentVid', 60, 70, 2, 'requiredSegmentVid-1', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']); - await db.prepare("run", query, ['requiredSegmentVid', 60, 70, -2, 'requiredSegmentVid-2', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']); - await db.prepare("run", query, ['requiredSegmentVid', 80, 90, -2, 'requiredSegmentVid-3', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']); - await db.prepare("run", query, ['requiredSegmentVid', 80, 90, 2, 'requiredSegmentVid-4', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']); + 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-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', 20, 30, 2, 'getSegmentsByHash-0-1', 'testman', 100, 150, 'intro', 'skip', '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-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, ['highlightVid', 60, 60, 2, 'highlightVid-1', 'testman', 0, 50, 'highlight', 'skip', 'YouTube', 0, 0, getHash('highlightVid', 1)]); + await db.prepare("run", query, ['highlightVid', 70, 70, 2, 'highlightVid-2', 'testman', 0, 50, '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, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']); + await db.prepare("run", query, ['requiredSegmentVid', 60, 70, -2, 'requiredSegmentVid-2', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']); + await db.prepare("run", query, ['requiredSegmentVid', 80, 90, -2, 'requiredSegmentVid-3', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']); + await db.prepare("run", query, ['requiredSegmentVid', 80, 90, 2, 'requiredSegmentVid-4', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 'd51822c3f681e07aef15a8855f52ad12db9eb9cf059e65b16b64c43359557f61']); }); it('Should be able to get a 200', (done: Done) => { @@ -158,6 +159,62 @@ describe('getSegmentsByHash', () => { .catch(() => done("Couldn't call endpoint")); }); + it('Should be able to get 200 for no categories (default sponsor) with action type', (done: Done) => { + fetch(getbaseURL() + '/api/skipSegments/fdaf?actionType=skip') + .then(async res => { + if (res.status !== 200) done("non 200 status code, was " + res.status); + else { + const body = await res.json(); + if (body.length !== 2) done("expected 2 videos, got " + body.length); + else if (body[0].segments.length !== 1) done("expected 1 segments for first video, got " + body[0].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' + || body[0].segments[0].UUID !== 'getSegmentsByHash-0-0' + || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor"); + else done(); + } + }) + .catch(() => done("Couldn't call endpoint")); + }); + + it('Should be able to get 200 for no categories (default sponsor) with multiple action types', (done: Done) => { + fetch(getbaseURL() + '/api/skipSegments/fdaf?actionType=skip&actionType=mute') + .then(async res => { + if (res.status !== 200) done("non 200 status code, was " + res.status); + else { + const body = await res.json(); + if (body.length !== 2) done("expected 2 videos, got " + body.length); + else if (body[0].segments.length !== 2) done("expected 2 segments for first video, got " + body[0].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' + || body[0].segments[0].UUID !== 'getSegmentsByHash-0-0' + || body[0].segments[1].UUID !== 'getSegmentsByHash-0-0-0-1' + || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor"); + else done(); + } + }) + .catch(() => done("Couldn't call endpoint")); + }); + + it('Should be able to get 200 for no categories (default sponsor) with multiple action types (JSON array)', (done: Done) => { + fetch(getbaseURL() + '/api/skipSegments/fdaf?actionTypes=["skip","mute"]') + .then(async res => { + if (res.status !== 200) done("non 200 status code, was " + res.status); + else { + const body = await res.json(); + if (body.length !== 2) done("expected 2 videos, got " + body.length); + else if (body[0].segments.length !== 2) done("expected 2 segments for first video, got " + body[0].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' + || body[0].segments[0].UUID !== 'getSegmentsByHash-0-0' + || body[0].segments[1].UUID !== 'getSegmentsByHash-0-0-0-1' + || body[1].segments[0].category !== 'sponsor') done("both segments are not sponsor"); + else done(); + } + }) + .catch(() => done("Couldn't call endpoint")); + }); + it('Should be able to get 200 for no categories (default sponsor) for a non YouTube service', (done: Done) => { fetch(getbaseURL() + '/api/skipSegments/fdaf?service=PeerTube') .then(async res => { @@ -287,3 +344,4 @@ describe('getSegmentsByHash', () => { .catch(() => done("Couldn't call endpoint")); }); }); + From 139dff97ef7c8b216ecefc80da82a4b2e86a5624 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 6 Jul 2021 00:19:16 -0400 Subject: [PATCH 5/7] Add tests for normal get segments --- test/cases/getSkipSegments.ts | 86 ++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/test/cases/getSkipSegments.ts b/test/cases/getSkipSegments.ts index 407ce3e..11196bd 100644 --- a/test/cases/getSkipSegments.ts +++ b/test/cases/getSkipSegments.ts @@ -5,22 +5,23 @@ import {getHash} from '../../src/utils/getHash'; describe('getSkipSegments', () => { before(async () => { - const query = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", views, category, "service", "videoDuration", "hidden", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; - await db.prepare("run", query, ['testtesttest', 1, 11, 2, 0, '1-uuid-0', 'testman', 0, 50, 'sponsor', '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', 'PeerTube', 120, 0, 0, getHash('testtesttest2', 1)]); - await db.prepare("run", query, ['testtesttest', 20, 33, 2, 0, '1-uuid-2', 'testman', 0, 50, 'intro', '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', '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', 'YouTube', 200, 0, 0, getHash('test3', 1)]); - await db.prepare("run", query, ['test3', 7, 22, -3, 0, '1-uuid-5', 'testman', 0, 50, 'sponsor', 'YouTube', 300, 0, 0, getHash('test3', 1)]); - await db.prepare("run", query, ['multiple', 1, 11, 2, 0, '1-uuid-6', 'testman', 0, 50, 'intro', 'YouTube', 400, 0, 0, getHash('multiple', 1)]); - await db.prepare("run", query, ['multiple', 20, 33, 2, 0, '1-uuid-7', 'testman', 0, 50, 'intro', 'YouTube', 500, 0, 0, getHash('multiple', 1)]); - await db.prepare("run", query, ['locked', 20, 33, 2, 1, '1-uuid-locked-8', 'testman', 0, 50, 'intro', 'YouTube', 230, 0, 0, getHash('locked', 1)]); - await db.prepare("run", query, ['locked', 20, 34, 100000, 0, '1-uuid-9', 'testman', 0, 50, 'intro', 'YouTube', 190, 0, 0, getHash('locked', 1)]); - await db.prepare("run", query, ['onlyHiddenSegments', 20, 34, 100000, 0, 'onlyHiddenSegments', 'testman', 0, 50, 'sponsor', 'YouTube', 190, 1, 0, getHash('onlyHiddenSegments', 1)]); - await db.prepare("run", query, ['requiredSegmentVid-raw', 60, 70, 2, 0, 'requiredSegmentVid-raw-1', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]); - await db.prepare("run", query, ['requiredSegmentVid-raw', 60, 70, -2, 0, 'requiredSegmentVid-raw-2', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]); - await db.prepare("run", query, ['requiredSegmentVid-raw', 80, 90, -2, 0, 'requiredSegmentVid-raw-3', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]); - await db.prepare("run", query, ['requiredSegmentVid-raw', 80, 90, 2, 0, 'requiredSegmentVid-raw-4', 'testman', 0, 50, 'sponsor', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]); + 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-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, ['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, ['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', 7, 22, -3, 0, '1-uuid-5', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 300, 0, 0, getHash('test3', 1)]); + await db.prepare("run", query, ['multiple', 1, 11, 2, 0, '1-uuid-6', 'testman', 0, 50, 'intro', 'skip', 'YouTube', 400, 0, 0, getHash('multiple', 1)]); + await db.prepare("run", query, ['multiple', 20, 33, 2, 0, '1-uuid-7', 'testman', 0, 50, 'intro', 'skip', 'YouTube', 500, 0, 0, getHash('multiple', 1)]); + await db.prepare("run", query, ['locked', 20, 33, 2, 1, '1-uuid-locked-8', 'testman', 0, 50, 'intro', 'skip', 'YouTube', 230, 0, 0, getHash('locked', 1)]); + await db.prepare("run", query, ['locked', 20, 34, 100000, 0, '1-uuid-9', 'testman', 0, 50, 'intro', 'skip', 'YouTube', 190, 0, 0, getHash('locked', 1)]); + await db.prepare("run", query, ['onlyHiddenSegments', 20, 34, 100000, 0, 'onlyHiddenSegments', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 190, 1, 0, getHash('onlyHiddenSegments', 1)]); + await db.prepare("run", query, ['requiredSegmentVid-raw', 60, 70, 2, 0, 'requiredSegmentVid-raw-1', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]); + await db.prepare("run", query, ['requiredSegmentVid-raw', 60, 70, -2, 0, 'requiredSegmentVid-raw-2', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]); + await db.prepare("run", query, ['requiredSegmentVid-raw', 80, 90, -2, 0, 'requiredSegmentVid-raw-3', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]); + await db.prepare("run", query, ['requiredSegmentVid-raw', 80, 90, 2, 0, 'requiredSegmentVid-raw-4', 'testman', 0, 50, 'sponsor', 'skip', 'YouTube', 0, 0, 0, getHash('requiredSegmentVid-raw', 1)]); return; }); @@ -42,6 +43,59 @@ describe('getSkipSegments', () => { .catch(() => "Couldn't call endpoint"); }); + it('Should be able to get a time by category and action type', (done: Done) => { + fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&category=sponsor&actionType=mute") + .then(async res => { + if (res.status !== 200) done("Status code was: " + res.status); + else { + const data = await res.json(); + if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 + && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0-0-1" && data[0].videoDuration === 100) { + done(); + } else { + done("Received incorrect body: " + (await res.text())); + } + } + }) + .catch(() => "Couldn't call endpoint"); + }); + + it('Should be able to get a time by category and multiple action types', (done: Done) => { + fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest&category=sponsor&actionType=mute&actionType=skip") + .then(async res => { + if (res.status !== 200) done("Status code was: " + res.status); + else { + const data = await res.json(); + 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[1].UUID === "1-uuid-0-0-1" && data[0].videoDuration === 100) { + done(); + } else { + done("Received incorrect body: " + (await res.text())); + } + } + }) + .catch(() => "Couldn't call endpoint"); + }); + + it('Should be able to get a time by category and multiple action types (JSON array)', (done: Done) => { + fetch(getbaseURL() + '/api/skipSegments?videoID=testtesttest&category=sponsor&actionTypes=["mute","skip"]') + .then(async res => { + if (res.status !== 200) done("Status code was: " + res.status); + else { + const data = await res.json(); + 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[1].UUID === "1-uuid-0-0-1" && data[0].videoDuration === 100) { + done(); + } else { + done("Received incorrect body: " + (await res.text())); + } + } + }) + .catch(() => "Couldn't call endpoint"); + }); + it('Should be able to get a time by category for a different service 1', (done: Done) => { fetch(getbaseURL() + "/api/skipSegments?videoID=testtesttest2&category=sponsor&service=PeerTube") .then(async res => { From 35e1cf573354133b65af30eddc6ac68405f48ac0 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 6 Jul 2021 00:22:01 -0400 Subject: [PATCH 6/7] Add test for submitting --- test/cases/postSkipSegments.ts | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/cases/postSkipSegments.ts b/test/cases/postSkipSegments.ts index a79317e..7ab0219 100644 --- a/test/cases/postSkipSegments.ts +++ b/test/cases/postSkipSegments.ts @@ -107,6 +107,38 @@ describe('postSkipSegments', () => { .catch(err => done(err)); }); + it('Should be able to submit a single time with an action type (JSON method)', (done: Done) => { + fetch(getbaseURL() + + "/api/postVideoSponsorTimes", { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + userID: "test", + videoID: "dQw4w9WgXcV", + segments: [{ + segment: [0, 10], + category: "sponsor", + actionType: "mute" + }], + }), + }) + .then(async res => { + if (res.status === 200) { + const row = await db.prepare('get', `SELECT "startTime", "endTime", "locked", "category", "actionType" FROM "sponsorTimes" WHERE "videoID" = ?`, ["dQw4w9WgXcV"]); + if (row.startTime === 0 && row.endTime === 10 && row.locked === 0 && row.category === "sponsor" && row.actionType === "mute") { + done(); + } else { + done("Submitted times were not saved. Actual submission: " + JSON.stringify(row)); + } + } else { + done("Status code was " + res.status); + } + }) + .catch(err => done(err)); + }); + it('Should be able to submit a single time with a duration from the YouTube API (JSON method)', (done: Done) => { fetch(getbaseURL() + "/api/postVideoSponsorTimes", { From 48349070b30f60b8dfe11935fbec0063bcd865a6 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 6 Jul 2021 00:57:57 -0400 Subject: [PATCH 7/7] Combine action type segments when sorting overlapping --- src/routes/getSkipSegments.ts | 26 +++++++++++++------------- test/cases/getSkipSegments.ts | 10 +++++----- test/cases/getSkipSegmentsByHash.ts | 6 +++--- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/routes/getSkipSegments.ts b/src/routes/getSkipSegments.ts index d671b00..42a9b38 100644 --- a/src/routes/getSkipSegments.ts +++ b/src/routes/getSkipSegments.ts @@ -12,7 +12,7 @@ import { QueryCacher } from '../utils/queryCacher'; import { getReputation } from '../utils/reputation'; -async function prepareCategorySegments(req: Request, videoID: VideoID, segments: DBSegment[], cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise { +async function prepareCategorySegments(req: Request, videoID: VideoID, category: Category, segments: DBSegment[],cache: SegmentCache = {shadowHiddenSegmentIPs: {}}): Promise { const shouldFilter: boolean[] = await Promise.all(segments.map(async (segment) => { if (segment.votes < -1 && !segment.required) { 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 maxSegments = getCategoryActionType(segments[0]?.category) === CategoryActionType.Skippable ? 32 : 1; + const maxSegments = getCategoryActionType(category) === CategoryActionType.Skippable ? 32 : 1; return (await chooseSegments(filteredSegments, maxSegments)).map((chosenSegment) => ({ category: chosenSegment.category, actionType: chosenSegment.actionType, @@ -60,20 +60,20 @@ async function getSegmentsByVideoID(req: Request, videoID: VideoID, categories: categories = categories.filter((category) => !/[^a-z|_|-]/.test(category)); if (categories.length === 0) return null; - const segmentsByType: SBRecord = (await getSegmentsFromDBByVideoID(videoID, service)) + const segmentsByCategory: SBRecord = (await getSegmentsFromDBByVideoID(videoID, service)) .filter((segment: DBSegment) => categories.includes(segment?.category) && actionTypes.includes(segment?.actionType)) .reduce((acc: SBRecord, segment: DBSegment) => { if (requiredSegments.includes(segment.UUID)) segment.required = true; - acc[segment.category + segment.actionType] ??= []; - acc[segment.category + segment.actionType].push(segment); + acc[segment.category] ??= []; + acc[segment.category].push(segment); return acc; }, {}); // eslint-disable-next-line @typescript-eslint/no-unused-vars - for (const [_key, typeSegments] of Object.entries(segmentsByType)) { - segments.push(...(await prepareCategorySegments(req, videoID, typeSegments, cache))); + for (const [category, categorySegments] of Object.entries(segmentsByCategory)) { + segments.push(...(await prepareCategorySegments(req, videoID, category as Category, categorySegments, cache))); } return segments; @@ -91,7 +91,7 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, const segments: SBRecord = {}; try { - type SegmentWithHashPerVideoID = SBRecord}>; + type SegmentWithHashPerVideoID = SBRecord}>; categories = categories.filter((category) => !(/[^a-z|_|-]/.test(category))); if (categories.length === 0) return null; @@ -101,12 +101,12 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, .reduce((acc: SegmentWithHashPerVideoID, segment: DBSegment) => { acc[segment.videoID] = acc[segment.videoID] || { hash: segment.hashedVideoID, - segmentPerType: {} + segmentPerCategory: {} }; if (requiredSegments.includes(segment.UUID)) segment.required = true; - acc[segment.videoID].segmentPerType[segment.category + segment.actionType] ??= []; - acc[segment.videoID].segmentPerType[segment.category + segment.actionType].push(segment); + acc[segment.videoID].segmentPerCategory[segment.category] ??= []; + acc[segment.videoID].segmentPerCategory[segment.category].push(segment); return acc; }, {}); @@ -118,8 +118,8 @@ async function getSegmentsByHash(req: Request, hashedVideoIDPrefix: VideoIDHash, }; // eslint-disable-next-line @typescript-eslint/no-unused-vars - for (const [_key, segmentPerType] of Object.entries(videoData.segmentPerType)) { - segments[videoID].segments.push(...(await prepareCategorySegments(req, videoID as VideoID, segmentPerType, cache))); + for (const [category, segmentPerCategory] of Object.entries(videoData.segmentPerCategory)) { + segments[videoID].segments.push(...(await prepareCategorySegments(req, videoID as VideoID, category as Category, segmentPerCategory, cache))); } } diff --git a/test/cases/getSkipSegments.ts b/test/cases/getSkipSegments.ts index 11196bd..06e64f2 100644 --- a/test/cases/getSkipSegments.ts +++ b/test/cases/getSkipSegments.ts @@ -7,8 +7,8 @@ describe('getSkipSegments', () => { before(async () => { 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-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, ['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,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)]); @@ -49,8 +49,8 @@ describe('getSkipSegments', () => { if (res.status !== 200) done("Status code was: " + res.status); else { const data = await res.json(); - if (data.length === 1 && data[0].segment[0] === 1 && data[0].segment[1] === 11 - && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0-0-1" && data[0].videoDuration === 100) { + if (data.length === 1 && data[0].segment[0] === 12 && data[0].segment[1] === 14 + && data[0].category === "sponsor" && data[0].UUID === "1-uuid-0-2" && data[0].videoDuration === 100) { done(); } else { done("Received incorrect body: " + (await res.text())); @@ -68,7 +68,7 @@ describe('getSkipSegments', () => { const data = await res.json(); 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[1].UUID === "1-uuid-0-0-1" && data[0].videoDuration === 100) { + && data[1].UUID === "1-uuid-0-2" && data[0].videoDuration === 100) { done(); } else { done("Received incorrect body: " + (await res.text())); @@ -86,7 +86,7 @@ describe('getSkipSegments', () => { const data = await res.json(); 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[1].UUID === "1-uuid-0-0-1" && data[0].videoDuration === 100) { + && data[1].UUID === "1-uuid-0-2" && data[0].videoDuration === 100) { done(); } else { done("Received incorrect body: " + (await res.text())); diff --git a/test/cases/getSkipSegmentsByHash.ts b/test/cases/getSkipSegmentsByHash.ts index 6796345..af7852d 100644 --- a/test/cases/getSkipSegmentsByHash.ts +++ b/test/cases/getSkipSegmentsByHash.ts @@ -14,9 +14,9 @@ describe('getSegmentsByHash', () => { before(async () => { 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-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', 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-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']); @@ -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[0].segments[0].category !== 'sponsor' || 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"); 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[0].segments[0].category !== 'sponsor' || 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"); else done(); }