Comparing version 0.0.16 to 0.0.17
@@ -62,1 +62,3 @@ export declare const DEBUG = false; | ||
export declare const ENDPOINT_COMMENT_ACTION = "https://www.youtube.com/youtubei/v1/comment/perform_comment_action"; | ||
export declare const ENDPOINT_PLAYER = "https://www.youtube.com/youtubei/v1/player"; | ||
export declare const ENDPOINT_COMMENT_CREATE = "https://www.youtube.com/youtubei/v1/comment/create_comment"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ENDPOINT_COMMENT_ACTION = exports.ENDPOINT_NEXT = exports.ENDPOINT_ADDTOPLAYLIST = exports.ENDPOINT_UNSUBSCRIBE = exports.ENDPOINT_SUBSCRIBE = exports.ENDPOINT_REMOVELIKE = exports.ENDPOINT_DISLIKE = exports.ENDPOINT_LIKE = exports.ENDPOINT_SEARCH = exports.ENDPOINT_BROWSE = exports.CONSOLE_COLORS = exports.DEFAULT_CONTEXT = exports.DEFAULT_USER_AGENT = exports.DEFAULT_CLIENT_NAME = exports.DEFAULT_CLIENT_VERSION = exports.DEFAULT_API_KEY = exports.DEBUG = void 0; | ||
exports.ENDPOINT_COMMENT_CREATE = exports.ENDPOINT_PLAYER = exports.ENDPOINT_COMMENT_ACTION = exports.ENDPOINT_NEXT = exports.ENDPOINT_ADDTOPLAYLIST = exports.ENDPOINT_UNSUBSCRIBE = exports.ENDPOINT_SUBSCRIBE = exports.ENDPOINT_REMOVELIKE = exports.ENDPOINT_DISLIKE = exports.ENDPOINT_LIKE = exports.ENDPOINT_SEARCH = exports.ENDPOINT_BROWSE = exports.CONSOLE_COLORS = exports.DEFAULT_CONTEXT = exports.DEFAULT_USER_AGENT = exports.DEFAULT_CLIENT_NAME = exports.DEFAULT_CLIENT_VERSION = exports.DEFAULT_API_KEY = exports.DEBUG = void 0; | ||
exports.DEBUG = false; | ||
@@ -65,1 +65,3 @@ exports.DEFAULT_API_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"; | ||
exports.ENDPOINT_COMMENT_ACTION = "https://www.youtube.com/youtubei/v1/comment/perform_comment_action"; | ||
exports.ENDPOINT_PLAYER = "https://www.youtube.com/youtubei/v1/player"; | ||
exports.ENDPOINT_COMMENT_CREATE = "https://www.youtube.com/youtubei/v1/comment/create_comment"; |
import { WrappedHTTPClient } from "../WrappedHTTPClient"; | ||
import { ContinuatedList } from "./ContinuatedList"; | ||
export declare class CommentSectionContinuatedList extends ContinuatedList { | ||
constructor(videoId: string, httpclient: WrappedHTTPClient); | ||
constructor(initialContinuationToken: string, httpclient: WrappedHTTPClient); | ||
} |
@@ -18,20 +18,8 @@ "use strict"; | ||
class CommentSectionContinuatedList extends ContinuatedList_1.ContinuatedList { | ||
constructor(videoId, httpclient) { | ||
constructor(initialContinuationToken, httpclient) { | ||
super({ | ||
url: constants_1.ENDPOINT_NEXT, | ||
method: HTTPClient_1.HTTPRequestMethod.POST, | ||
data: { | ||
autonavState: "STATE_ON", | ||
captionsRequested: true, | ||
contentCheckOK: false, | ||
params: "OALAAQHCAwtPUEhMX09MVzNkUQ%3D%3D", | ||
racyCheckOk: false, | ||
videoId: videoId, | ||
} | ||
}, function (resJSON) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const itemSectionRenderers = helpers_1.default.recursiveSearchForKey("itemSectionRenderer", resJSON); | ||
const commentSectionRenderer = itemSectionRenderers.find((a) => a.targetId == 'comments-section'); | ||
if (commentSectionRenderer) | ||
return []; | ||
const continuationItems = helpers_1.default.recursiveSearchForKey("continuationItems", resJSON)[1]; | ||
@@ -41,4 +29,5 @@ return continuationItems; | ||
}, httpclient, false); | ||
this.continuationToken = initialContinuationToken; | ||
} | ||
} | ||
exports.CommentSectionContinuatedList = CommentSectionContinuatedList; |
@@ -32,2 +32,3 @@ import { ContinuatedList, Thumbnail, ChannelBadge, WrappedHTTPClient } from "../main"; | ||
fromCommentRenderer(obj: any): void; | ||
fromPlayerMicroRenderer(obj: any): void; | ||
loadAll(): Promise<void>; | ||
@@ -34,0 +35,0 @@ loadDetailsFromAboutPage(): Promise<void>; |
@@ -126,2 +126,6 @@ "use strict"; | ||
} | ||
fromPlayerMicroRenderer(obj) { | ||
this.channelId = obj.externalChannelId; | ||
this.title = obj.ownerChannelName; | ||
} | ||
loadAll() { | ||
@@ -128,0 +132,0 @@ return __awaiter(this, void 0, void 0, function* () { |
@@ -1,2 +0,2 @@ | ||
import { ContinuatedList, WrappedHTTPClient, Channel, Thumbnail } from "../main"; | ||
import { CommentSectionContinuatedList, ContinuatedList, WrappedHTTPClient, Channel, Thumbnail, CaptionTrack, CommentThread } from "../main"; | ||
export declare class Video { | ||
@@ -6,2 +6,3 @@ videoId?: any; | ||
shortDescription?: string; | ||
description?: string; | ||
viewCount?: number; | ||
@@ -11,4 +12,15 @@ thumbnails?: Array<Thumbnail>; | ||
publishedText?: string; | ||
publishedDate?: Date; | ||
owner?: Channel; | ||
playable?: boolean; | ||
private?: boolean; | ||
listed?: boolean; | ||
live?: boolean; | ||
familySafe?: boolean; | ||
captionTracks?: Array<CaptionTrack>; | ||
keywords?: Array<String>; | ||
canLike?: boolean; | ||
hasLiked?: boolean; | ||
currentUserIsOwner?: boolean; | ||
commentThreadList?: CommentSectionContinuatedList; | ||
httpclient: WrappedHTTPClient; | ||
@@ -20,6 +32,8 @@ error: boolean; | ||
fromPlaylistVideoRenderer(obj: any): void; | ||
getCommentThreadList(): Promise<ContinuatedList>; | ||
loadAll(): Promise<void>; | ||
getCommentThreadList(): Promise<ContinuatedList | undefined>; | ||
like(): Promise<boolean>; | ||
dislike(): Promise<boolean>; | ||
removeLike(): Promise<boolean>; | ||
comment(text: string): Promise<CommentThread>; | ||
} |
@@ -70,7 +70,112 @@ "use strict"; | ||
} | ||
loadAll() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const playerResponse = yield this.httpclient.request({ | ||
method: HTTPClient_1.HTTPRequestMethod.POST, | ||
url: constants_1.ENDPOINT_PLAYER, | ||
data: { | ||
videoId: this.videoId, | ||
racyCheckOk: false, | ||
contentCheckOk: false, | ||
playbackContext: { | ||
contentPlaybackContent: { | ||
currentUrl: "/watch?v=6Dh-RL__uN4", | ||
autonavState: "STATE_OFF", | ||
autoCaptionsDefaultOn: false, | ||
html5Preference: "HTML5_PREF_WANTS", | ||
lactMilliseconds: "-1", | ||
referer: "https://www.youtube.com/", | ||
signatureTimestamp: 19095, | ||
splay: false, | ||
vis: 0 | ||
} | ||
} | ||
} | ||
}); | ||
const playerJSON = yield JSON.parse(playerResponse.data); | ||
const videoDetails = helpers_1.default.recursiveSearchForKey("videoDetails", playerJSON)[0]; | ||
if (videoDetails) { | ||
this.title = videoDetails.title; | ||
this.description = videoDetails.shortDescription; | ||
this.thumbnails = helpers_1.default.recursiveSearchForKey("thumbnails", videoDetails)[0]; | ||
this.viewCount = helpers_1.default.getNumberFromText(videoDetails.viewCount); | ||
this.private = videoDetails.isPrivate; | ||
this.live = videoDetails.isLiveContent; | ||
this.keywords = videoDetails.keywords; | ||
this.currentUserIsOwner = videoDetails.isOwnerViewing; | ||
this.canLike = videoDetails.allowRatings; | ||
} | ||
const playerMicroRenderer = helpers_1.default.recursiveSearchForKey("playerMicroformatRenderer", playerJSON)[0]; | ||
if (playerMicroRenderer) { | ||
this.publishedText = playerMicroRenderer.publishDate; | ||
this.listed = !playerMicroRenderer.isUnlisted; | ||
this.familySafe = playerMicroRenderer.isFamilySafe; | ||
this.owner = new main_1.Channel(this.httpclient); | ||
this.owner.fromPlayerMicroRenderer(playerMicroRenderer); | ||
} | ||
const captions = helpers_1.default.recursiveSearchForKey("captionTracks", playerJSON)[0]; | ||
if (captions) { | ||
this.captionTracks = captions.map((a) => { | ||
a.name = helpers_1.default.recursiveSearchForKey("simpleText", a.name).join(""); | ||
return a; | ||
}); | ||
} | ||
const nextResponse = yield this.httpclient.request({ | ||
method: HTTPClient_1.HTTPRequestMethod.POST, | ||
url: constants_1.ENDPOINT_NEXT, | ||
data: { | ||
autonavState: "STATE_ON", | ||
captionsRequested: true, | ||
contentCheckOK: false, | ||
params: "OALAAQHCAwtPUEhMX09MVzNkUQ%3D%3D", | ||
racyCheckOk: false, | ||
videoId: this.videoId, | ||
} | ||
}); | ||
const nextJSON = yield JSON.parse(nextResponse.data); | ||
const itemSectionRenderers = helpers_1.default.recursiveSearchForKey("itemSectionRenderer", nextJSON); | ||
const commentSectionRenderer = itemSectionRenderers.find((a) => a.targetId == 'comments-section'); | ||
if (commentSectionRenderer) | ||
this.commentThreadList = new main_1.CommentSectionContinuatedList(helpers_1.default.recursiveSearchForKey("token", commentSectionRenderer)[0], this.httpclient); | ||
const primaryInfoRenderer = helpers_1.default.recursiveSearchForKey("videoPrimaryInfoRenderer", nextJSON)[0]; | ||
if (primaryInfoRenderer) { | ||
const titleContainer = primaryInfoRenderer.title; | ||
if (titleContainer) | ||
this.title = helpers_1.default.recursiveSearchForKey("text", titleContainer).join(); | ||
const viewCountContainer = helpers_1.default.recursiveSearchForKey("viewCount", nextJSON)[0]; | ||
if (viewCountContainer) | ||
this.viewCount = helpers_1.default.getNumberFromText(helpers_1.default.recursiveSearchForKey("simpleText", viewCountContainer).join("")); | ||
const dateContainer = helpers_1.default.recursiveSearchForKey("dateText", nextJSON)[0]; | ||
if (dateContainer) | ||
this.publishedDate = new Date(helpers_1.default.recursiveSearchForKey("simpleText", dateContainer).join("")); | ||
const buttons = helpers_1.default.recursiveSearchForKey("topLevelButtons", nextJSON)[0]; | ||
if (buttons) { | ||
const likeButton = buttons[0].toggleButtonRenderer; | ||
const dislikeButton = buttons[1].toggleButtonRenderer; | ||
if (likeButton && dislikeButton) | ||
this.hasLiked = likeButton.isToggled && !dislikeButton.isToggled; | ||
} | ||
} | ||
const secondaryInfoRenderer = helpers_1.default.recursiveSearchForKey("videoSecondaryInfoRenderer", nextJSON)[0]; | ||
if (secondaryInfoRenderer) { | ||
const descriptionContainer = secondaryInfoRenderer.description; | ||
if (descriptionContainer) | ||
this.description = helpers_1.default.recursiveSearchForKey("text", descriptionContainer).join(""); | ||
const ownerContainer = secondaryInfoRenderer.owner; | ||
if (ownerContainer) { | ||
this.owner = new main_1.Channel(this.httpclient); | ||
this.owner.fromVideoOwnerRenderer(helpers_1.default.recursiveSearchForKey("videoOwnerRenderer", ownerContainer)); | ||
this.owner.subscribed = helpers_1.default.recursiveSearchForKey("subscribed", nextJSON)[0]; | ||
} | ||
} | ||
}); | ||
} | ||
getCommentThreadList() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
var list = new main_1.CommentSectionContinuatedList(this.videoId, this.httpclient); | ||
yield list.loadFurhter(); | ||
return list; | ||
if (!this.commentThreadList) { | ||
yield this.loadAll(); | ||
if (!this.commentThreadList) | ||
throw new Error("This Video seems to have no comment section"); | ||
} | ||
return this.commentThreadList; | ||
}); | ||
@@ -80,2 +185,4 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this.canLike === false) | ||
throw new Error("This Video has disabled Like-Actions"); | ||
const res = yield this.httpclient.request({ | ||
@@ -90,3 +197,3 @@ method: HTTPClient_1.HTTPRequestMethod.POST, | ||
}); | ||
const resJSON = yield JSON.parse(res.data); | ||
this.hasLiked = res.status == 200 ? true : this.hasLiked; | ||
return res.status == 200; | ||
@@ -97,2 +204,4 @@ }); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this.canLike === false) | ||
throw new Error("This Video has disabled Like-Actions"); | ||
const res = yield this.httpclient.request({ | ||
@@ -107,3 +216,3 @@ method: HTTPClient_1.HTTPRequestMethod.POST, | ||
}); | ||
const resJSON = yield JSON.parse(res.data); | ||
this.hasLiked = res.status == 200 ? false : this.hasLiked; | ||
return res.status == 200; | ||
@@ -114,2 +223,4 @@ }); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this.canLike === false) | ||
throw new Error("This Video has disabled Like-Actions"); | ||
const res = yield this.httpclient.request({ | ||
@@ -124,7 +235,32 @@ method: HTTPClient_1.HTTPRequestMethod.POST, | ||
}); | ||
const resJSON = yield JSON.parse(res.data); | ||
this.hasLiked = res.status == 200 ? undefined : this.hasLiked; | ||
return res.status == 200; | ||
}); | ||
} | ||
comment(text) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
var commentParams = atob(decodeURIComponent("EgtQSGdjOFE2cVRqYyoCCABQBw%3D%3D")); | ||
commentParams = commentParams.replace("PHgc8Q6qTjc", this.videoId); | ||
commentParams = encodeURIComponent(btoa(commentParams)); | ||
const res = yield this.httpclient.request({ | ||
method: HTTPClient_1.HTTPRequestMethod.POST, | ||
url: constants_1.ENDPOINT_COMMENT_CREATE, | ||
data: { | ||
commentText: text, | ||
createCommentParams: commentParams | ||
} | ||
}); | ||
const resJSON = JSON.parse(res.data); | ||
const commentThreadRenderer = helpers_1.default.recursiveSearchForKey("commentThreadRenderer", resJSON)[0]; | ||
if (commentThreadRenderer) { | ||
var cmd = new main_1.CommentThread(this.httpclient); | ||
cmd.fromCommentThreadRenderer(commentThreadRenderer); | ||
return cmd; | ||
} | ||
else { | ||
throw new Error("Failed to create Comment on Video"); | ||
} | ||
}); | ||
} | ||
} | ||
exports.Video = Video; |
@@ -10,3 +10,3 @@ import { Authenticator } from "./Authenticator"; | ||
import { Playlist } from "./interfaces/Playlist"; | ||
import { Channel } from "./main"; | ||
import { Channel, Video } from "./main"; | ||
export default class IYoutube { | ||
@@ -23,2 +23,3 @@ #private; | ||
getChannel(channelId: string): Promise<Channel>; | ||
getVideo(videoId: string): Promise<Video>; | ||
getExplorer(): Explorer; | ||
@@ -25,0 +26,0 @@ getUser(): User; |
@@ -76,2 +76,11 @@ "use strict"; | ||
} | ||
getVideo(videoId) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.throwErrorIfNotReady(); | ||
var v = new main_1.Video(this.wrappedHttpClient); | ||
v.videoId = videoId; | ||
yield v.loadAll(); | ||
return v; | ||
}); | ||
} | ||
getExplorer() { | ||
@@ -78,0 +87,0 @@ return __classPrivateFieldGet(this, _IYoutube_explorer, "f"); |
@@ -19,2 +19,3 @@ import { NodeFetchClientAdapter } from "./adapters/NodeFetchClientAdapter"; | ||
import { CommentThreadRepliesContinuatedList } from "./fetchers/CommentThreadRepliesContinuatedList"; | ||
import { CaptionTrack } from "./interfaces/CaptionTrack"; | ||
import { default as IYoutube } from "./Iyoutube"; | ||
@@ -40,2 +41,3 @@ export { IYoutube as IYoutube }; | ||
export { CommentThreadRepliesContinuatedList as CommentThreadRepliesContinuatedList }; | ||
export { CaptionTrack as CaptionTrack }; | ||
export declare const nodeInst: IYoutube; |
{ | ||
"name": "iyoutube", | ||
"version": "0.0.16", | ||
"version": "0.0.17", | ||
"description": "The ultimate unofficial YouTube API Client for Javascript", | ||
@@ -5,0 +5,0 @@ "main": "output/main.js", |
@@ -65,2 +65,4 @@ export const DEBUG = false; | ||
export const ENDPOINT_NEXT = "https://www.youtube.com/youtubei/v1/next"; | ||
export const ENDPOINT_COMMENT_ACTION = "https://www.youtube.com/youtubei/v1/comment/perform_comment_action"; | ||
export const ENDPOINT_COMMENT_ACTION = "https://www.youtube.com/youtubei/v1/comment/perform_comment_action"; | ||
export const ENDPOINT_PLAYER = "https://www.youtube.com/youtubei/v1/player"; | ||
export const ENDPOINT_COMMENT_CREATE = "https://www.youtube.com/youtubei/v1/comment/create_comment"; |
@@ -8,3 +8,3 @@ import { ENDPOINT_NEXT } from "../constants"; | ||
export class CommentSectionContinuatedList extends ContinuatedList { | ||
constructor(videoId: string, httpclient: WrappedHTTPClient) { | ||
constructor(initialContinuationToken : string, httpclient: WrappedHTTPClient) { | ||
super( | ||
@@ -15,10 +15,2 @@ /* Request Options */ | ||
method: HTTPRequestMethod.POST, | ||
data: { | ||
autonavState: "STATE_ON", | ||
captionsRequested: true, | ||
contentCheckOK: false, | ||
params: "OALAAQHCAwtPUEhMX09MVzNkUQ%3D%3D", | ||
racyCheckOk: false, | ||
videoId: videoId, | ||
} | ||
}, | ||
@@ -28,7 +20,2 @@ | ||
async function(resJSON:any) { | ||
const itemSectionRenderers = helpers.recursiveSearchForKey("itemSectionRenderer", resJSON); | ||
const commentSectionRenderer = itemSectionRenderers.find((a:any) => a.targetId == 'comments-section'); | ||
if(commentSectionRenderer) return []; | ||
const continuationItems = helpers.recursiveSearchForKey("continuationItems", resJSON)[1]; | ||
@@ -40,3 +27,4 @@ return continuationItems; | ||
httpclient, false); | ||
this.continuationToken = initialContinuationToken; | ||
} | ||
} |
@@ -158,2 +158,7 @@ import { ENDPOINT_BROWSE, ENDPOINT_SUBSCRIBE, ENDPOINT_UNSUBSCRIBE } from "../constants"; | ||
fromPlayerMicroRenderer(obj: any) { | ||
this.channelId = obj.externalChannelId; | ||
this.title = obj.ownerChannelName; | ||
} | ||
async loadAll() { | ||
@@ -160,0 +165,0 @@ await this.loadDetailsFromAboutPage(); |
@@ -1,4 +0,4 @@ | ||
import { ENDPOINT_DISLIKE, ENDPOINT_LIKE, ENDPOINT_REMOVELIKE } from "../constants"; | ||
import { ENDPOINT_COMMENT_CREATE, ENDPOINT_DISLIKE, ENDPOINT_LIKE, ENDPOINT_NEXT, ENDPOINT_PLAYER, ENDPOINT_REMOVELIKE } from "../constants"; | ||
import helpers from "../fetchers/helpers"; | ||
import { CommentSectionContinuatedList, ContinuatedList, WrappedHTTPClient, Channel, Thumbnail } from "../main"; | ||
import { CommentSectionContinuatedList, ContinuatedList, WrappedHTTPClient, Channel, Thumbnail, CaptionTrack, CommentThread } from "../main"; | ||
import { HTTPRequestMethod } from "./HTTPClient"; | ||
@@ -11,2 +11,3 @@ | ||
shortDescription?: string; | ||
description?: string; | ||
viewCount?: number; | ||
@@ -16,4 +17,15 @@ thumbnails?: Array<Thumbnail>; | ||
publishedText?: string; | ||
publishedDate?: Date; | ||
owner?: Channel; | ||
playable?: boolean; | ||
private?: boolean; | ||
listed?: boolean; | ||
live?: boolean; | ||
familySafe?: boolean; | ||
captionTracks?: Array<CaptionTrack>; | ||
keywords?: Array<String>; | ||
canLike?: boolean; | ||
hasLiked?: boolean; | ||
currentUserIsOwner?: boolean; | ||
commentThreadList?: CommentSectionContinuatedList; | ||
@@ -28,3 +40,3 @@ httpclient: WrappedHTTPClient; | ||
fromVideoRenderer(obj: any) { | ||
// VIDEOID | ||
//VIDEOID | ||
this.videoId = helpers.recursiveSearchForKey("videoId", obj)[0]; | ||
@@ -98,9 +110,126 @@ | ||
async getCommentThreadList():Promise<ContinuatedList> { | ||
var list = new CommentSectionContinuatedList(this.videoId, this.httpclient); | ||
await list.loadFurhter(); | ||
return list; | ||
async loadAll() { | ||
const playerResponse = await this.httpclient.request({ | ||
method: HTTPRequestMethod.POST, | ||
url: ENDPOINT_PLAYER, | ||
data: { | ||
videoId: this.videoId, | ||
racyCheckOk: false, | ||
contentCheckOk: false, | ||
playbackContext: { | ||
contentPlaybackContent: { | ||
currentUrl: "/watch?v=6Dh-RL__uN4", | ||
autonavState: "STATE_OFF", | ||
autoCaptionsDefaultOn: false, | ||
html5Preference: "HTML5_PREF_WANTS", | ||
lactMilliseconds: "-1", | ||
referer: "https://www.youtube.com/", | ||
signatureTimestamp: 19095, | ||
splay: false, | ||
vis: 0 | ||
} | ||
} | ||
} | ||
}); | ||
const playerJSON = await JSON.parse(playerResponse.data); | ||
const videoDetails = helpers.recursiveSearchForKey("videoDetails", playerJSON)[0]; | ||
if(videoDetails) { | ||
this.title = videoDetails.title; | ||
this.description = videoDetails.shortDescription; | ||
this.thumbnails = helpers.recursiveSearchForKey("thumbnails", videoDetails)[0]; | ||
this.viewCount = helpers.getNumberFromText(videoDetails.viewCount); | ||
this.private = videoDetails.isPrivate; | ||
this.live = videoDetails.isLiveContent; | ||
this.keywords = videoDetails.keywords; | ||
this.currentUserIsOwner = videoDetails.isOwnerViewing; | ||
this.canLike = videoDetails.allowRatings; | ||
} | ||
const playerMicroRenderer = helpers.recursiveSearchForKey("playerMicroformatRenderer", playerJSON)[0]; | ||
if(playerMicroRenderer) { | ||
this.publishedText = playerMicroRenderer.publishDate; | ||
this.listed = !playerMicroRenderer.isUnlisted; | ||
this.familySafe = playerMicroRenderer.isFamilySafe; | ||
this.owner = new Channel(this.httpclient); | ||
this.owner.fromPlayerMicroRenderer(playerMicroRenderer); | ||
} | ||
const captions = helpers.recursiveSearchForKey("captionTracks", playerJSON)[0]; | ||
if(captions) { | ||
this.captionTracks = captions.map((a:any) => { | ||
a.name = helpers.recursiveSearchForKey("simpleText", a.name).join(""); | ||
return a; | ||
}); | ||
} | ||
const nextResponse = await this.httpclient.request({ | ||
method: HTTPRequestMethod.POST, | ||
url: ENDPOINT_NEXT, | ||
data: { | ||
autonavState: "STATE_ON", | ||
captionsRequested: true, | ||
contentCheckOK: false, | ||
params: "OALAAQHCAwtPUEhMX09MVzNkUQ%3D%3D", | ||
racyCheckOk: false, | ||
videoId: this.videoId, | ||
} | ||
}); | ||
const nextJSON = await JSON.parse(nextResponse.data); | ||
const itemSectionRenderers = helpers.recursiveSearchForKey("itemSectionRenderer", nextJSON); | ||
const commentSectionRenderer = itemSectionRenderers.find((a:any) => a.targetId == 'comments-section'); | ||
if(commentSectionRenderer) this.commentThreadList = new CommentSectionContinuatedList(helpers.recursiveSearchForKey("token", commentSectionRenderer)[0], this.httpclient); | ||
const primaryInfoRenderer = helpers.recursiveSearchForKey("videoPrimaryInfoRenderer", nextJSON)[0]; | ||
if(primaryInfoRenderer) { | ||
const titleContainer = primaryInfoRenderer.title; | ||
if(titleContainer) | ||
this.title = helpers.recursiveSearchForKey("text", titleContainer).join(); | ||
const viewCountContainer = helpers.recursiveSearchForKey("viewCount", nextJSON)[0]; | ||
if(viewCountContainer) | ||
this.viewCount = helpers.getNumberFromText(helpers.recursiveSearchForKey("simpleText", viewCountContainer).join("")); | ||
const dateContainer = helpers.recursiveSearchForKey("dateText", nextJSON)[0]; | ||
if(dateContainer) | ||
this.publishedDate = new Date(helpers.recursiveSearchForKey("simpleText", dateContainer).join("")); | ||
//In theory, it would be possible to get the exact like count using the Accessability Text | ||
const buttons = helpers.recursiveSearchForKey("topLevelButtons", nextJSON)[0]; | ||
if(buttons) { | ||
const likeButton = buttons[0].toggleButtonRenderer; | ||
const dislikeButton = buttons[1].toggleButtonRenderer; | ||
if(likeButton && dislikeButton) | ||
this.hasLiked = likeButton.isToggled && !dislikeButton.isToggled; | ||
} | ||
} | ||
const secondaryInfoRenderer = helpers.recursiveSearchForKey("videoSecondaryInfoRenderer", nextJSON)[0]; | ||
if(secondaryInfoRenderer) { | ||
const descriptionContainer = secondaryInfoRenderer.description; | ||
if(descriptionContainer) | ||
this.description = helpers.recursiveSearchForKey("text", descriptionContainer).join(""); | ||
const ownerContainer = secondaryInfoRenderer.owner; | ||
if(ownerContainer) { | ||
this.owner = new Channel(this.httpclient); | ||
this.owner.fromVideoOwnerRenderer(helpers.recursiveSearchForKey("videoOwnerRenderer", ownerContainer)); | ||
this.owner.subscribed = helpers.recursiveSearchForKey("subscribed", nextJSON)[0]; | ||
} | ||
} | ||
//TODO: Video Formats | ||
} | ||
async getCommentThreadList():Promise<ContinuatedList | undefined> { | ||
if(!this.commentThreadList) { | ||
await this.loadAll(); | ||
if(!this.commentThreadList) throw new Error("This Video seems to have no comment section"); | ||
} | ||
return this.commentThreadList; | ||
} | ||
async like() { | ||
if(this.canLike === false) throw new Error("This Video has disabled Like-Actions"); | ||
const res = await this.httpclient.request({ | ||
@@ -115,4 +244,3 @@ method: HTTPRequestMethod.POST, | ||
}); | ||
const resJSON = await JSON.parse(res.data); | ||
this.hasLiked = res.status == 200 ? true : this.hasLiked; | ||
return res.status == 200; | ||
@@ -122,2 +250,3 @@ } | ||
async dislike() { | ||
if(this.canLike === false) throw new Error("This Video has disabled Like-Actions"); | ||
const res = await this.httpclient.request({ | ||
@@ -132,4 +261,3 @@ method: HTTPRequestMethod.POST, | ||
}); | ||
const resJSON = await JSON.parse(res.data); | ||
this.hasLiked = res.status == 200 ? false : this.hasLiked; | ||
return res.status == 200; | ||
@@ -139,2 +267,3 @@ } | ||
async removeLike() { | ||
if(this.canLike === false) throw new Error("This Video has disabled Like-Actions"); | ||
const res = await this.httpclient.request({ | ||
@@ -149,6 +278,29 @@ method: HTTPRequestMethod.POST, | ||
}); | ||
const resJSON = await JSON.parse(res.data); | ||
this.hasLiked = res.status == 200 ? undefined : this.hasLiked; | ||
return res.status == 200; | ||
} | ||
async comment(text: string):Promise<CommentThread> { | ||
var commentParams = atob(decodeURIComponent("EgtQSGdjOFE2cVRqYyoCCABQBw%3D%3D")); | ||
commentParams = commentParams.replace("PHgc8Q6qTjc", this.videoId); | ||
commentParams = encodeURIComponent(btoa(commentParams)); | ||
const res = await this.httpclient.request({ | ||
method: HTTPRequestMethod.POST, | ||
url: ENDPOINT_COMMENT_CREATE, | ||
data: { | ||
commentText: text, | ||
createCommentParams: commentParams | ||
} | ||
}); | ||
const resJSON = JSON.parse(res.data); | ||
const commentThreadRenderer = helpers.recursiveSearchForKey("commentThreadRenderer", resJSON)[0]; | ||
if(commentThreadRenderer) { | ||
var cmd = new CommentThread(this.httpclient); | ||
cmd.fromCommentThreadRenderer(commentThreadRenderer); | ||
return cmd; | ||
} else { | ||
throw new Error("Failed to create Comment on Video"); | ||
} | ||
} | ||
} |
@@ -12,3 +12,3 @@ import { Authenticator } from "./Authenticator"; | ||
import { DEBUG } from "./constants"; | ||
import { Channel } from "./main"; | ||
import { Channel, Video } from "./main"; | ||
@@ -65,2 +65,10 @@ export default class IYoutube { | ||
async getVideo(videoId: string):Promise<Video> { | ||
this.throwErrorIfNotReady(); | ||
var v = new Video(this.wrappedHttpClient); | ||
v.videoId = videoId; | ||
await v.loadAll(); | ||
return v; | ||
} | ||
getExplorer():Explorer { | ||
@@ -67,0 +75,0 @@ return this.#explorer; |
@@ -19,2 +19,3 @@ import { NodeFetchClientAdapter } from "./adapters/NodeFetchClientAdapter"; | ||
import { CommentThreadRepliesContinuatedList } from "./fetchers/CommentThreadRepliesContinuatedList"; | ||
import { CaptionTrack } from "./interfaces/CaptionTrack"; | ||
import { default as IYoutube } from "./Iyoutube"; | ||
@@ -44,2 +45,3 @@ | ||
export { CommentThreadRepliesContinuatedList as CommentThreadRepliesContinuatedList } | ||
export { CaptionTrack as CaptionTrack } | ||
@@ -46,0 +48,0 @@ //Default Export for most NodeJS |
15
todo.md
## Todo | ||
##### Channels: | ||
- [ ] Fetch all Information | ||
- [X] Fetch all Information | ||
- [X] Get Channel Uploads | ||
@@ -9,7 +9,9 @@ - [ ] Get Discussion Section | ||
##### Videos: | ||
- [ ] Fetch all Information (Youtube Player Response) | ||
- [ ] Stream URL Decryption | ||
- [X] Fetch all Information (Youtube Player Response) | ||
- [ ] Stream URL Decryption & Video Formats | ||
- [X] Get Comment Section | ||
- [X] Like and Dislike Comments | ||
- [ ] Write Comments | ||
- [X] Write Comments on Video | ||
- [ ] Delete own Comments | ||
- [ ] Write Comments on Comment Threads | ||
@@ -21,4 +23,5 @@ ##### Playlists: | ||
General: Bugfixes, Enhancements | ||
###### Please keep in mind that I'm working on this Project in my spare time! | ||
General: Documentation, Bugfixes, Enhancements | ||
###### Please keep in mind that I'm working on this Project in my spare time! |
209512
88
4110