diff --git a/src/types/innerTubeApi.model.ts b/src/types/innerTubeApi.model.ts index 28e46c8..04c1028 100644 --- a/src/types/innerTubeApi.model.ts +++ b/src/types/innerTubeApi.model.ts @@ -1,7 +1,7 @@ export interface innerTubeVideoDetails { "videoId": string, "title": string, - "lengthSeconds": string, // yes, don't ask. + "lengthSeconds"?: string, // yes, don't ask. "channelId": string, "isOwnerViewing": boolean, "shortDescription": string, diff --git a/src/utils/innerTubeAPI.ts b/src/utils/innerTubeAPI.ts index 475cda9..9361a8d 100644 --- a/src/utils/innerTubeAPI.ts +++ b/src/utils/innerTubeAPI.ts @@ -3,6 +3,30 @@ import { Logger } from "./logger"; import { innerTubeVideoDetails } from "../types/innerTubeApi.model"; import DiskCache from "./diskCache"; +const privateResponse = (videoId: string): innerTubeVideoDetails => ({ + videoId, + title: "", + channelId: "", + // exclude video duration + isOwnerViewing: false, + shortDescription: "", + isCrawlable: false, + thumbnail: { + thumbnails: [{ + url: "https://s.ytimg.com/yts/img/meh7-vflGevej7.png", + width: 140, + height: 100 + }] + }, + allowRatings: false, + viewCount: "0", // yes, don't ask + author: "", + isPrivate: true, + isUnpluggedCorpus: true, + isLiveContent: false, + publishDate: "" +}); + async function getFromITube (videoID: string): Promise { // start subrequest const url = "https://www.youtube.com/youtubei/v1/player"; @@ -20,9 +44,9 @@ async function getFromITube (videoID: string): Promise { }); /* istanbul ignore else */ if (result.status === 200) { - return result.data.videoDetails; + return result.data?.videoDetails ?? privateResponse(videoID); } else { - return Promise.reject(result.status); + return Promise.reject(`Innertube returned non-200 response: ${result.status}`); } } diff --git a/test/cases/innerTubeApi.ts b/test/cases/innerTubeApi.ts index 0c98642..d65b5cc 100644 --- a/test/cases/innerTubeApi.ts +++ b/test/cases/innerTubeApi.ts @@ -46,4 +46,9 @@ describe("innertube API test", function() { const videoDetail = await getVideoDetails(videoID); assert.ok(videoDetail); }); + it("Should not fail when getting data for private video", async function () { + const privateVideoId = "ZuibAax0VD8"; + const videoDetail = await getVideoDetails(privateVideoId); + assert.ok(videoDetail); + }); }); \ No newline at end of file diff --git a/test/cases/postSkipSegments.ts b/test/cases/postSkipSegments.ts index 57ebeb8..233f511 100644 --- a/test/cases/postSkipSegments.ts +++ b/test/cases/postSkipSegments.ts @@ -1292,4 +1292,20 @@ describe("postSkipSegments", () => { }) .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)); + }); }); diff --git a/test/mocks/youtubeMock.ts b/test/mocks/youtubeMock.ts index 95f3d20..c8f60c0 100644 --- a/test/mocks/youtubeMock.ts +++ b/test/mocks/youtubeMock.ts @@ -63,6 +63,11 @@ export class YouTubeApiMock { lengthSeconds: 100, } as APIVideoData }; + } else if (obj.id === "private-video") { + return { + err: false, + data: {} as APIVideoData + }; } else { return { err: false,