From e6f54f11f02a0410a3d0e2c1efb713c3affb7556 Mon Sep 17 00:00:00 2001 From: Michael C Date: Tue, 21 Feb 2023 17:00:23 -0500 Subject: [PATCH] decompose postSkipSegments more --- test/cases/postSkipSegments.ts | 385 ------------------------ test/cases/postSkipSegmentsDuration.ts | 205 +++++++++++++ test/cases/postSkipSegmentsLocked.ts | 70 +++++ test/cases/postSkipSegmentsShadowban.ts | 68 +++++ test/cases/postSkipSegmentsUserAgent.ts | 104 +++++++ 5 files changed, 447 insertions(+), 385 deletions(-) create mode 100644 test/cases/postSkipSegmentsDuration.ts create mode 100644 test/cases/postSkipSegmentsLocked.ts create mode 100644 test/cases/postSkipSegmentsShadowban.ts create mode 100644 test/cases/postSkipSegmentsUserAgent.ts diff --git a/test/cases/postSkipSegments.ts b/test/cases/postSkipSegments.ts index 499a5bc..cf45bca 100644 --- a/test/cases/postSkipSegments.ts +++ b/test/cases/postSkipSegments.ts @@ -43,32 +43,19 @@ describe("postSkipSegments", () => { const submitUserOne = `PostSkipUser1${".".repeat(18)}`; const submitUserTwo = `PostSkipUser2${".".repeat(18)}`; const submitUserTwoHash = getHash(submitUserTwo); - const submitUserThree = `PostSkipUser3${".".repeat(18)}`; - - const banUser01 = "ban-user01-loremipsumdolorsitametconsectetur"; - const banUser01Hash = getHash(banUser01); const submitVIPuser = `VIPPostSkipUser${".".repeat(16)}`; - const shadowBanVideoID = "postSkipBan"; - const shadowBanVideoID2 = "postSkipBan2"; const queryDatabase = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "votes", "userID", "locked", "category", "actionType" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]); const queryDatabaseActionType = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "actionType" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]); - const queryDatabaseDuration = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]); const queryDatabaseVideoInfo = (videoID: string) => db.prepare("get", `SELECT * FROM "videoInfo" WHERE "videoID" = ?`, [videoID]); before(() => { const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "videoDuration", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; db.prepare("run", insertSponsorTimeQuery, ["full_video_segment", 0, 0, 0, "full-video-uuid-0", submitUserTwoHash, 0, 0, "sponsor", "full", 0, 0, "full_video_segment"]); - db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 0, 0, 0, "full-video-duration-uuid-0", submitUserTwoHash, 0, 0, "sponsor", "full", 123, 0, "full_video_duration_segment"]); - db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 25, 30, 0, "full-video-duration-uuid-1", submitUserTwoHash, 0, 0, "sponsor", "skip", 123, 0, "full_video_duration_segment"]); - const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)'; db.prepare("run", insertVipUserQuery, [getHash(submitVIPuser)]); - - // ban user - db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, [banUser01Hash]); }); it("Should be able to submit a single time (Params method)", (done) => { @@ -155,174 +142,6 @@ describe("postSkipSegments", () => { .catch(err => done(err)); }); - it("Should be able to submit a single time with a duration from the YouTube API (JSON method)", (done) => { - const videoID = "postSkip5"; - postSkipSegmentJSON({ - userID: submitUserOne, - videoID, - videoDuration: 100, - segments: [{ - segment: [0, 10], - category: "sponsor", - }], - }) - .then(async res => { - assert.strictEqual(res.status, 200); - const row = await queryDatabaseDuration(videoID); - const expected = { - startTime: 0, - endTime: 10, - category: "sponsor", - videoDuration: 4980, - }; - assert.ok(partialDeepEquals(row, expected)); - done(); - }) - .catch(err => done(err)); - }); - - it("Should be able to submit a single time with a precise duration close to the one from the YouTube API (JSON method)", (done) => { - const videoID = "postSkip6"; - postSkipSegmentJSON({ - userID: submitUserOne, - videoID, - videoDuration: 4980.20, - segments: [{ - segment: [1, 10], - category: "sponsor", - }], - }) - .then(async res => { - assert.strictEqual(res.status, 200); - const row = await queryDatabaseDuration(videoID); - const expected = { - startTime: 1, - endTime: 10, - locked: 0, - category: "sponsor", - videoDuration: 4980.20, - }; - assert.ok(partialDeepEquals(row, expected)); - done(); - }) - .catch(err => done(err)); - }); - - it("Should be able to submit a single time with a duration in the body (JSON method)", (done) => { - const videoID = "noDuration"; - postSkipSegmentJSON({ - userID: submitUserOne, - videoID, - videoDuration: 100, - segments: [{ - segment: [0, 10], - category: "sponsor", - }], - }) - .then(async res => { - assert.strictEqual(res.status, 200); - const row = await queryDatabaseDuration(videoID); - const expected = { - startTime: 0, - endTime: 10, - locked: 0, - category: "sponsor", - videoDuration: 100, - }; - assert.ok(partialDeepEquals(row, expected)); - done(); - }) - .catch(err => done(err)); - }); - - it("Should be able to submit with a new duration, and hide old submissions and remove segment locks", async () => { - const videoID = "noDuration"; - await db.prepare("run", `INSERT INTO "lockCategories" ("userID", "videoID", "category") - VALUES(?, ?, ?)`, [getHash("VIPUser-lockCategories"), videoID, "sponsor"]); - - try { - const res = await postSkipSegmentJSON({ - userID: submitUserOne, - videoID, - videoDuration: 100, - segments: [{ - segment: [1, 10], - category: "sponsor", - }], - }); - assert.strictEqual(res.status, 200); - const lockCategoriesRow = await db.prepare("get", `SELECT * from "lockCategories" WHERE videoID = ?`, [videoID]); - const videoRows = await db.prepare("all", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" - FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 0`, [videoID]); - const hiddenVideoRows = await db.prepare("all", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" - FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 1`, [videoID]); - assert.ok(!lockCategoriesRow); - const expected = { - startTime: 1, - endTime: 10, - locked: 0, - category: "sponsor", - videoDuration: 100, - }; - assert.ok(partialDeepEquals(videoRows[0], expected)); - assert.strictEqual(videoRows.length, 1); - assert.strictEqual(hiddenVideoRows.length, 1); - } catch (e) { - return e; - } - }); - - it("Should still not be allowed if youtube thinks duration is 0", (done) => { - const videoID= "noDuration"; - postSkipSegmentJSON({ - userID: submitUserThree, - videoID, - videoDuration: 100, - segments: [{ - segment: [30, 10000], - category: "sponsor", - }], - }) - .then(res => { - assert.strictEqual(res.status, 403); - done(); - }) - .catch(err => done(err)); - }); - - it("Should be able to submit with a new duration, and not hide full video segments", async () => { - const videoID = "full_video_duration_segment"; - const res = await postSkipSegmentJSON({ - userID: submitUserOne, - videoID, - videoDuration: 100, - segments: [{ - segment: [20, 30], - category: "sponsor", - }], - }); - assert.strictEqual(res.status, 200); - const videoRows = await db.prepare("all", `SELECT "startTime", "endTime", "locked", "category", "actionType", "videoDuration" - FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 0`, [videoID]); - const hiddenVideoRows = await db.prepare("all", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" - FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 1`, [videoID]); - assert.strictEqual(videoRows.length, 2); - const expected = { - startTime: 20, - endTime: 30, - locked: 0, - category: "sponsor", - videoDuration: 100 - }; - const fullExpected = { - category: "sponsor", - actionType: "full" - }; - assert.ok((partialDeepEquals(videoRows[0], fullExpected) && partialDeepEquals(videoRows[1], expected)) - || (partialDeepEquals(videoRows[1], fullExpected) && partialDeepEquals(videoRows[0], expected))); - assert.strictEqual(hiddenVideoRows.length, 1); - }); - it("Should be able to submit a single time under a different service (JSON method)", (done) => { const videoID = "postSkip7"; postSkipSegmentJSON({ @@ -438,151 +257,6 @@ describe("postSkipSegments", () => { .catch(err => done(err)); }); - it("Should return 403 and custom reason for submiting in lockedCategory", (done) => { - const videoID = "lockedVideo"; - db.prepare("run", `INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") - VALUES(?, ?, ?, ?)`, [getHash("VIPUser-lockCategories"), videoID, "sponsor", "Custom Reason"]) - .then(() => postSkipSegmentJSON({ - userID: submitUserOne, - videoID, - segments: [{ - segment: [1, 10], - category: "sponsor", - }], - })) - .then(res => { - assert.strictEqual(res.status, 403); - assert.match(res.data, /Reason: /); - assert.match(res.data, /Custom Reason/); - done(); - }) - .catch(err => done(err)); - }); - - it("Should return not be 403 when submitting with locked category but unlocked actionType", (done) => { - const videoID = "lockedVideo"; - db.prepare("run", `INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") - VALUES(?, ?, ?, ?)`, [getHash("VIPUser-lockCategories"), videoID, "sponsor", "Custom Reason"]) - .then(() => postSkipSegmentJSON({ - userID: submitUserOne, - videoID, - segments: [{ - segment: [1, 10], - category: "sponsor", - actionType: "mute" - }], - })) - .then(res => { - assert.strictEqual(res.status, 200); - done(); - }) - .catch(err => done(err)); - }); - - it("Should return 403 for submiting in lockedCategory", (done) => { - const videoID = "lockedVideo1"; - db.prepare("run", `INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") - VALUES(?, ?, ?, ?)`, [getHash("VIPUser-lockCategories"), videoID, "intro", ""]) - .then(() => postSkipSegmentJSON({ - userID: submitUserOne, - videoID, - segments: [{ - segment: [1, 10], - category: "intro", - }], - })) - .then(res => { - assert.strictEqual(res.status, 403); - assert.doesNotMatch(res.data, /Lock reason: /); - assert.doesNotMatch(res.data, /Custom Reason/); - done(); - }) - .catch(err => done(err)); - }); - - it("Should be able to submit with custom user-agent 1", (done) => { - client({ - url: endpoint, - method: "POST", - headers: { - "Content-Type": "application/json", - "User-Agent": "com.google.android.youtube/5.0" - }, - data: { - userID: submitUserOne, - videoID: "userAgent-1", - segments: [{ - segment: [0, 10], - category: "sponsor", - }], - } - }) - .then(async res => { - assert.strictEqual(res.status, 200); - const row = await db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "userAgent" FROM "sponsorTimes" WHERE "videoID" = ?`, ["userAgent-1"]); - const expected = { - startTime: 0, - endTime: 10, - userAgent: "Vanced/5.0", - }; - assert.ok(partialDeepEquals(row, expected)); - done(); - }) - .catch(err => done(err)); - }); - - it("Should be able to submit with empty user-agent", (done) => { - client({ - url: endpoint, - method: "POST", - data: { - userID: submitUserOne, - videoID: "userAgent-3", - segments: [{ - segment: [0, 10], - category: "sponsor", - }], - userAgent: "", - } - }) - .then(async res => { - assert.strictEqual(res.status, 200); - const row = await db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "userAgent" FROM "sponsorTimes" WHERE "videoID" = ?`, ["userAgent-3"]); - const expected = { - startTime: 0, - endTime: 10, - userAgent: "", - }; - assert.ok(partialDeepEquals(row, expected)); - done(); - }) - .catch(err => done(err)); - }); - - it("Should be able to submit with custom userAgent in body", (done) => { - postSkipSegmentJSON({ - userID: submitUserOne, - videoID: "userAgent-4", - segments: [{ - segment: [0, 10], - category: "sponsor", - }], - userAgent: "MeaBot/5.0" - }) - .then(async res => { - assert.strictEqual(res.status, 200); - const row = await db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "userAgent" FROM "sponsorTimes" WHERE "videoID" = ?`, ["userAgent-4"]); - const expected = { - startTime: 0, - endTime: 10, - userAgent: "MeaBot/5.0", - }; - assert.ok(partialDeepEquals(row, expected)); - done(); - }) - .catch(err => done(err)); - }); - it("Should be able to submit with commas in timestamps", (done) => { const videoID = "commas-1"; postSkipSegmentJSON({ @@ -677,65 +351,6 @@ describe("postSkipSegments", () => { .catch(err => done(err)); }); - it("Should automatically shadowban segments if user is banned", (done) => { - const videoID = shadowBanVideoID; - postSkipSegmentParam({ - videoID, - startTime: 0, - endTime: 10, - category: "sponsor", - userID: banUser01 - }) - .then(async res => { - assert.strictEqual(res.status, 200); - const row = await db.prepare("get", `SELECT "startTime", "endTime", "shadowHidden", "userID" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]); - const expected = { - startTime: 0, - endTime: 10, - shadowHidden: 1, - userID: banUser01Hash - }; - assert.deepStrictEqual(row, expected); - done(); - }) - .catch(err => done(err)); - }); - - it("Should not add full segments to database if user if shadowbanned", (done) => { - const videoID = shadowBanVideoID2; - postSkipSegmentParam({ - videoID, - startTime: 0, - endTime: 0, - category: "sponsor", - actionType: "full", - userID: banUser01 - }) - .then(async res => { - assert.strictEqual(res.status, 200); - const row = await db.prepare("get", `SELECT "startTime", "endTime", "shadowHidden", "userID" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]); - assert.strictEqual(row, undefined); - done(); - }) - .catch(err => done(err)); - }); - - it("Should successfully submit if video is private", (done) => { - const videoID = "private-video"; - postSkipSegmentParam({ - videoID, - startTime: 1, - endTime: 5, - category: "sponsor", - userID: submitUserTwo - }) - .then(res => { - assert.strictEqual(res.status, 200); - done(); - }) - .catch(err => done(err)); - }); - it("Should throw 409 on duplicate submission", (done) => { const videoID = "private-video"; postSkipSegmentParam({ diff --git a/test/cases/postSkipSegmentsDuration.ts b/test/cases/postSkipSegmentsDuration.ts new file mode 100644 index 0000000..7277192 --- /dev/null +++ b/test/cases/postSkipSegmentsDuration.ts @@ -0,0 +1,205 @@ +import assert from "assert"; +import { postSkipSegmentJSON, postSkipSegmentParam } from "./postSkipSegments"; +import { getHash } from "../../src/utils/getHash"; +import { partialDeepEquals } from "../utils/partialDeepEquals"; +import { db } from "../../src/databases/databases"; +import { ImportMock } from "ts-mock-imports"; +import * as YouTubeAPIModule from "../../src/utils/youtubeApi"; +import { YouTubeApiMock } from "../mocks/youtubeMock"; +import { convertSingleToDBFormat } from "./postSkipSegments"; + +const mockManager = ImportMock.mockStaticClass(YouTubeAPIModule, "YouTubeAPI"); +const sinonStub = mockManager.mock("listVideos"); +sinonStub.callsFake(YouTubeApiMock.listVideos); + +describe("postSkipSegments - duration", () => { + const userIDOne = "postSkip-DurationUserOne"; + const userIDTwo = "postSkip-DurationUserTwo"; + const videoID = "postSkip-DurationVideo"; + const noDurationVideoID = "noDuration"; + const userID = userIDOne; + + const queryDatabaseDuration = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]); + + before(() => { + const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "videoDuration", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 0, 0, 0, "full-video-duration-uuid-0", userIDTwo, 0, 0, "sponsor", "full", 123, 0, "full_video_duration_segment"]); + db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 25, 30, 0, "full-video-duration-uuid-1", userIDTwo, 0, 0, "sponsor", "skip", 123, 0, "full_video_duration_segment"]); + }); + + it("Should be able to submit a single time with a precise duration close to the one from the YouTube API (JSON method)", (done) => { + const segment = { + segment: [1, 10], + category: "sponsor", + }; + postSkipSegmentJSON({ + userID, + videoID, + videoDuration: 4980.20, + segments: [segment], + }) + .then(async res => { + assert.strictEqual(res.status, 200); + const row = await queryDatabaseDuration(videoID); + const expected = { + ...convertSingleToDBFormat(segment), + locked: 0, + videoDuration: 4980.20, + }; + assert.ok(partialDeepEquals(row, expected)); + done(); + }) + .catch(err => done(err)); + }); + + it("Should be able to submit a single time with a duration in the body (JSON method)", (done) => { + const videoID = "noDuration"; + const segment = { + segment: [0, 10], + category: "sponsor", + }; + postSkipSegmentJSON({ + userID, + videoID, + videoDuration: 100, + segments: [segment], + }) + .then(async res => { + assert.strictEqual(res.status, 200); + const row = await queryDatabaseDuration(videoID); + const expected = { + ...convertSingleToDBFormat(segment), + locked: 0, + videoDuration: 100, + }; + assert.ok(partialDeepEquals(row, expected)); + done(); + }) + .catch(err => done(err)); + }); + + it("Should be able to submit with a new duration, and hide old submissions and remove segment locks", async () => { + const videoID = "noDuration"; + const segment = { + segment: [1, 10], + category: "sponsor", + }; + await db.prepare("run", `INSERT INTO "lockCategories" ("userID", "videoID", "category") + VALUES(?, ?, ?)`, [getHash("generic-VIP"), videoID, "sponsor"]); + try { + const res = await postSkipSegmentJSON({ + userID, + videoID, + videoDuration: 100, + segments: [segment], + }); + assert.strictEqual(res.status, 200); + const lockCategoriesRow = await db.prepare("get", `SELECT * from "lockCategories" WHERE videoID = ?`, [videoID]); + const videoRows = await db.prepare("all", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" + FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 0`, [videoID]); + const hiddenVideoRows = await db.prepare("all", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" + FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 1`, [videoID]); + assert.ok(!lockCategoriesRow); + const expected = { + ...convertSingleToDBFormat(segment), + locked: 0, + videoDuration: 100, + }; + assert.ok(partialDeepEquals(videoRows[0], expected)); + assert.strictEqual(videoRows.length, 1); + assert.strictEqual(hiddenVideoRows.length, 1); + } catch (e) { + return e; + } + }); + + it("Should still not be allowed if youtube thinks duration is 0", (done) => { + postSkipSegmentJSON({ + userID, + videoID: noDurationVideoID, + videoDuration: 100, + segments: [{ + segment: [30, 10000], + category: "sponsor", + }], + }) + .then(res => { + assert.strictEqual(res.status, 403); + done(); + }) + .catch(err => done(err)); + }); + + it("Should be able to submit with a new duration, and not hide full video segments", async () => { + const videoID = "full_video_duration_segment"; + const segment = { + segment: [20, 30], + category: "sponsor", + }; + const res = await postSkipSegmentJSON({ + userID, + videoID, + videoDuration: 100, + segments: [segment], + }); + assert.strictEqual(res.status, 200); + const videoRows = await db.prepare("all", `SELECT "startTime", "endTime", "locked", "category", "actionType", "videoDuration" + FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 0`, [videoID]); + const hiddenVideoRows = await db.prepare("all", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" + FROM "sponsorTimes" WHERE "videoID" = ? AND hidden = 1`, [videoID]); + assert.strictEqual(videoRows.length, 2); + const expected = { + ...convertSingleToDBFormat(segment), + locked: 0, + videoDuration: 100 + }; + const fullExpected = { + category: "sponsor", + actionType: "full" + }; + assert.ok((partialDeepEquals(videoRows[0], fullExpected) && partialDeepEquals(videoRows[1], expected)) + || (partialDeepEquals(videoRows[1], fullExpected) && partialDeepEquals(videoRows[0], expected))); + assert.strictEqual(hiddenVideoRows.length, 1); + }); + + it("Should be able to submit a single time with a duration from the YouTube API (JSON method)", (done) => { + const segment = { + segment: [0, 10], + category: "sponsor", + }; + const videoID = "postDuration-ytjson"; + postSkipSegmentJSON({ + userID, + videoID, + videoDuration: 100, + segments: [segment], + }) + .then(async res => { + assert.strictEqual(res.status, 200); + const row = await queryDatabaseDuration(videoID); + const expected = { + ...convertSingleToDBFormat(segment), + videoDuration: 4980, + }; + assert.ok(partialDeepEquals(row, expected)); + done(); + }) + .catch(err => done(err)); + }); + + it("Should successfully submit if video is private", (done) => { + const videoID = "private-video"; + postSkipSegmentParam({ + videoID, + startTime: 1, + endTime: 5, + category: "sponsor", + userID + }) + .then(res => { + assert.strictEqual(res.status, 200); + done(); + }) + .catch(err => done(err)); + }); +}); \ No newline at end of file diff --git a/test/cases/postSkipSegmentsLocked.ts b/test/cases/postSkipSegmentsLocked.ts new file mode 100644 index 0000000..0fc0ab8 --- /dev/null +++ b/test/cases/postSkipSegmentsLocked.ts @@ -0,0 +1,70 @@ +import assert from "assert"; +import { postSkipSegmentJSON } from "./postSkipSegments"; +import { getHash } from "../../src/utils/getHash"; +import { db } from "../../src/databases/databases"; + +describe("postSkipSegments - LockedVideos", () => { + const userIDOne = "postSkip-DurationUserOne"; + const VIPLockUser = "VIPUser-lockCategories"; + const videoID = "lockedVideo"; + const userID = userIDOne; + + before(() => { + const insertLockCategoriesQuery = `INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") VALUES(?, ?, ?, ?)`; + db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]); + db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]); + }); + + it("Should return 403 and custom reason for submiting in lockedCategory", (done) => { + postSkipSegmentJSON({ + userID, + videoID, + segments: [{ + segment: [1, 10], + category: "sponsor", + }], + }) + .then(res => { + assert.strictEqual(res.status, 403); + assert.match(res.data, /Reason: /); + assert.match(res.data, /Custom Reason/); + done(); + }) + .catch(err => done(err)); + }); + + it("Should return not be 403 when submitting with locked category but unlocked actionType", (done) => { + postSkipSegmentJSON({ + userID, + videoID, + segments: [{ + segment: [1, 10], + category: "sponsor", + actionType: "mute" + }], + }) + .then(res => { + assert.strictEqual(res.status, 200); + done(); + }) + .catch(err => done(err)); + }); + + it("Should return 403 for submiting in lockedCategory", (done) => { + postSkipSegmentJSON({ + userID, + videoID, + segments: [{ + segment: [1, 10], + category: "intro", + }], + }) + .then(res => { + assert.strictEqual(res.status, 403); + assert.doesNotMatch(res.data, /Lock reason: /); + assert.doesNotMatch(res.data, /Custom Reason/); + done(); + }) + .catch(err => done(err)); + }); +}); \ No newline at end of file diff --git a/test/cases/postSkipSegmentsShadowban.ts b/test/cases/postSkipSegmentsShadowban.ts new file mode 100644 index 0000000..38a0f76 --- /dev/null +++ b/test/cases/postSkipSegmentsShadowban.ts @@ -0,0 +1,68 @@ +import assert from "assert"; +import { postSkipSegmentParam } from "./postSkipSegments"; +import { getHash } from "../../src/utils/getHash"; +import { db } from "../../src/databases/databases"; +import { ImportMock } from "ts-mock-imports"; +import * as YouTubeAPIModule from "../../src/utils/youtubeApi"; +import { YouTubeApiMock } from "../mocks/youtubeMock"; + +const mockManager = ImportMock.mockStaticClass(YouTubeAPIModule, "YouTubeAPI"); +const sinonStub = mockManager.mock("listVideos"); +sinonStub.callsFake(YouTubeApiMock.listVideos); + +describe("postSkipSegments - shadowban", () => { + const banUser01 = "postSkip-banUser01"; + const banUser01Hash = getHash(banUser01); + + const shadowBanVideoID1 = "postSkipBan1"; + const shadowBanVideoID2 = "postSkipBan2"; + + const queryDatabaseShadowhidden = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "shadowHidden", "userID" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]); + + before(() => { + db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, [banUser01Hash]); + }); + + it("Should automatically shadowban segments if user is banned", (done) => { + const videoID = shadowBanVideoID1; + postSkipSegmentParam({ + videoID, + startTime: 0, + endTime: 10, + category: "sponsor", + userID: banUser01 + }) + .then(async res => { + assert.strictEqual(res.status, 200); + const row = await queryDatabaseShadowhidden(videoID); + const expected = { + startTime: 0, + endTime: 10, + shadowHidden: 1, + userID: banUser01Hash + }; + assert.deepStrictEqual(row, expected); + done(); + }) + .catch(err => done(err)); + }); + + it("Should not add full segments to database if user if shadowbanned", (done) => { + const videoID = shadowBanVideoID2; + postSkipSegmentParam({ + videoID, + startTime: 0, + endTime: 0, + category: "sponsor", + actionType: "full", + userID: banUser01 + }) + .then(async res => { + assert.strictEqual(res.status, 200); + const row = await queryDatabaseShadowhidden(videoID); + assert.strictEqual(row, undefined); + done(); + }) + .catch(err => done(err)); + }); +}); \ No newline at end of file diff --git a/test/cases/postSkipSegmentsUserAgent.ts b/test/cases/postSkipSegmentsUserAgent.ts new file mode 100644 index 0000000..c5e68c9 --- /dev/null +++ b/test/cases/postSkipSegmentsUserAgent.ts @@ -0,0 +1,104 @@ +import assert from "assert"; +import { convertSingleToDBFormat } from "./postSkipSegments"; +import { getHash } from "../../src/utils/getHash"; +import { db } from "../../src/databases/databases"; +import { partialDeepEquals } from "../utils/partialDeepEquals"; +import { client } from "../utils/httpClient"; + +const endpoint = "/api/skipSegments"; + +const queryUseragent = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "userAgent" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]); + +describe("postSkipSegments - userAgent", () => { + const userIDOne = "postSkip-DurationUserOne"; + const VIPLockUser = "VIPUser-lockCategories"; + const videoID = "lockedVideo"; + const userID = userIDOne; + + const segment = { + segment: [0, 10], + category: "sponsor", + }; + const dbFormatSegment = convertSingleToDBFormat(segment); + + before(() => { + const insertLockCategoriesQuery = `INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") VALUES(?, ?, ?, ?)`; + db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]); + db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]); + }); + + it("Should be able to submit with empty user-agent", (done) => { + const videoID = "userAgent-3"; + client(endpoint, { + method: "POST", + data: { + userID, + videoID, + segments: [segment], + userAgent: "", + } + }) + .then(async res => { + assert.strictEqual(res.status, 200); + const row = await queryUseragent(videoID); + const expected = { + ...dbFormatSegment, + userAgent: "", + }; + assert.ok(partialDeepEquals(row, expected)); + done(); + }) + .catch(err => done(err)); + }); + + it("Should be able to submit with custom userAgent in body", (done) => { + const videoID = "userAgent-4"; + client(endpoint, { + method: "POST", + data: { + userID, + videoID, + segments: [segment], + userAgent: "MeaBot/5.0" + } + }) + .then(async res => { + assert.strictEqual(res.status, 200); + const row = await queryUseragent(videoID); + const expected = { + ...dbFormatSegment, + userAgent: "MeaBot/5.0", + }; + assert.ok(partialDeepEquals(row, expected)); + done(); + }) + .catch(err => done(err)); + }); + + it("Should be able to submit with custom user-agent 1", (done) => { + const videoID = "userAgent-1"; + client(endpoint, { + method: "POST", + headers: { + "Content-Type": "application/json", + "User-Agent": "com.google.android.youtube/5.0" + }, + data: { + userID, + videoID, + segments: [segment], + } + }) + .then(async res => { + assert.strictEqual(res.status, 200); + const row = await queryUseragent(videoID); + const expected = { + ...dbFormatSegment, + userAgent: "Vanced/5.0", + }; + assert.ok(partialDeepEquals(row, expected)); + done(); + }) + .catch(err => done(err)); + }); +}); \ No newline at end of file