From 0a595e31f824bc9209ac8dd12d028c51f8dd69ff Mon Sep 17 00:00:00 2001 From: LuanRT Date: Thu, 9 Mar 2023 04:25:24 +0000 Subject: [PATCH] chore: v3.3.0 release --- README.md | 9 ++- deno/package.json | 2 +- deno/src/Innertube.ts | 44 +++++++++++-- deno/src/core/Session.ts | 6 +- deno/src/parser/classes/ConversationBar.ts | 16 +++++ deno/src/parser/classes/DecoratedPlayerBar.ts | 3 +- .../parser/classes/MultiMarkersPlayerBar.ts | 10 ++- deno/src/parser/classes/SharedPost.ts | 2 +- .../classes/TwoColumnWatchNextResults.ts | 64 +++++++++++++++++++ deno/src/parser/map.ts | 3 + deno/src/parser/youtube/VideoInfo.ts | 18 ++++++ deno/src/utils/Constants.ts | 3 +- 12 files changed, 161 insertions(+), 19 deletions(-) create mode 100644 deno/src/parser/classes/ConversationBar.ts diff --git a/README.md b/README.md index a3c77b05..b30944ff 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ const yt = await Innertube.create({ Methods

- * [.getInfo(video_id, client?)](#getinfo) + * [.getInfo(target, client?)](#getinfo) * [.getBasicInfo(video_id, client?)](#getbasicinfo) * [.search(query, filters?)](#search) * [.getSearchSuggestions(query)](#getsearchsuggestions) @@ -273,7 +273,7 @@ const yt = await Innertube.create({ -### getInfo(video_id, client?) +### getInfo(target, client?) Retrieves video info, including playback data and even layout elements such as menus, buttons, etc — all nicely parsed. @@ -281,7 +281,7 @@ Retrieves video info, including playback data and even layout elements such as m | Param | Type | Description | | --- | --- | --- | -| video_id | `string` | The id of the video | +| target | `string` \| `NavigationEndpoint` | If `string`, the id of the video. If `NavigationEndpoint`, the endpoint of watchable elements such as `Video`, `Mix` and `Playlist`. To clarify, valid endpoints have payloads containing at least `videoId` and optionally `playlistId`, `params` and `index`. | | client? | `InnerTubeClient` | `WEB`, `ANDROID`, `YTMUSIC`, `YTMUSIC_ANDROID` or `TV_EMBEDDED` |

@@ -321,6 +321,9 @@ Retrieves video info, including playback data and even layout elements such as m - `#addToWatchHistory()` - Adds the video to the watch history. +- `#autoplay_video_endpoint` + - Returns the endpoint of the video for Autoplay. + - `#page` - Returns original InnerTube response (sanitized). diff --git a/deno/package.json b/deno/package.json index 9d626129..d9d9b6b9 100644 --- a/deno/package.json +++ b/deno/package.json @@ -1,6 +1,6 @@ { "name": "youtubei.js", - "version": "3.2.0", + "version": "3.3.0", "description": "A wrapper around YouTube's private API. Supports YouTube, YouTube Music, YouTube Kids and YouTube Studio (WIP).", "type": "module", "types": "./dist/src/platform/lib.d.ts", diff --git a/deno/src/Innertube.ts b/deno/src/Innertube.ts index 2e1c07c3..01f1b500 100644 --- a/deno/src/Innertube.ts +++ b/deno/src/Innertube.ts @@ -31,7 +31,7 @@ import type Format from './parser/classes/misc/Format.ts'; import type { ApiResponse } from './core/Actions.ts'; import type { IBrowseResponse, IParsedResponse } from './parser/types/index.ts'; import type { DownloadOptions, FormatOptions } from './utils/FormatUtils.ts'; -import { generateRandomString, throwIfMissing } from './utils/Utils.ts'; +import { generateRandomString, InnertubeError, throwIfMissing } from './utils/Utils.ts'; export type InnertubeConfig = SessionOptions; @@ -72,16 +72,48 @@ class Innertube { /** * Retrieves video info. - * @param video_id - The video id. + * @param target - The video id or `NavigationEndpoint`. * @param client - The client to use. */ - async getInfo(video_id: string, client?: InnerTubeClient): Promise { - throwIfMissing({ video_id }); + async getInfo(target: string | NavigationEndpoint, client?: InnerTubeClient): Promise { + throwIfMissing({ target }); + + let payload: { + videoId: string, + playlistId?: string, + params?: string, + playlistIndex?: number + }; + + if (target instanceof NavigationEndpoint) { + const video_id = target.payload?.videoId; + if (!video_id) { + throw new InnertubeError('Missing video id in endpoint payload.', target); + } + payload = { + videoId: video_id + }; + if (target.payload.playlistId) { + payload.playlistId = target.payload.playlistId; + } + if (target.payload.params) { + payload.params = target.payload.params; + } + if (target.payload.index) { + payload.playlistIndex = target.payload.index; + } + } else if (typeof target === 'string') { + payload = { + videoId: target + }; + } else { + throw new InnertubeError('Invalid target, expected either a video id or a valid NavigationEndpoint', target); + } const cpn = generateRandomString(16); - const initial_info = this.actions.getVideoInfo(video_id, cpn, client); - const continuation = this.actions.execute('/next', { videoId: video_id }); + const initial_info = this.actions.getVideoInfo(payload.videoId, cpn, client); + const continuation = this.actions.execute('/next', payload); const response = await Promise.all([ initial_info, continuation ]); return new VideoInfo(response, this.actions, this.session.player, cpn); diff --git a/deno/src/core/Session.ts b/deno/src/core/Session.ts index bae0066a..9b1356f3 100644 --- a/deno/src/core/Session.ts +++ b/deno/src/core/Session.ts @@ -4,7 +4,7 @@ import Actions from './Actions.ts'; import Player from './Player.ts'; import HTTPClient from '../utils/HTTPClient.ts'; -import { Platform, DeviceCategory, generateRandomString, getRandomUserAgent, InnertubeError, SessionError } from '../utils/Utils.ts'; +import { Platform, DeviceCategory, getRandomUserAgent, InnertubeError, SessionError } from '../utils/Utils.ts'; import OAuth, { Credentials, OAuthAuthErrorEventHandler, OAuthAuthEventHandler, OAuthAuthPendingEventHandler } from './OAuth.ts'; import Proto from '../proto/index.ts'; import { ICache } from '../types/Cache.ts'; @@ -232,7 +232,7 @@ export default class Session extends EventEmitterLike { 'user-agent': getRandomUserAgent('desktop'), 'accept': '*/*', 'referer': 'https://www.youtube.com/sw.js', - 'cookie': `PREF=tz=${options.time_zone.replace('/', '.')}` + 'cookie': `PREF=tz=${options.time_zone.replace('/', '.')};VISITOR_INFO1_LIVE=${Constants.CLIENTS.WEB.STATIC_VISITOR_ID};` } }); @@ -294,7 +294,7 @@ export default class Session extends EventEmitterLike { client_name: string; enable_safety_mode: boolean }): SessionData { - const id = generateRandomString(11); + const id = Constants.CLIENTS.WEB.STATIC_VISITOR_ID; const timestamp = Math.floor(Date.now() / 1000); const context: Context = { diff --git a/deno/src/parser/classes/ConversationBar.ts b/deno/src/parser/classes/ConversationBar.ts new file mode 100644 index 00000000..11889cd8 --- /dev/null +++ b/deno/src/parser/classes/ConversationBar.ts @@ -0,0 +1,16 @@ +import { YTNode } from '../helpers.ts'; +import Parser, { RawNode } from '../index.ts'; +import Message from './Message.ts'; + +class ConversationBar extends YTNode { + static type = 'ConversationBar'; + + availability_message: Message | null; + + constructor(data: RawNode) { + super(); + this.availability_message = Parser.parseItem(data.availabilityMessage, Message); + } +} + +export default ConversationBar; \ No newline at end of file diff --git a/deno/src/parser/classes/DecoratedPlayerBar.ts b/deno/src/parser/classes/DecoratedPlayerBar.ts index 2b22b678..d6f60795 100644 --- a/deno/src/parser/classes/DecoratedPlayerBar.ts +++ b/deno/src/parser/classes/DecoratedPlayerBar.ts @@ -2,6 +2,7 @@ import Parser from '../index.ts'; import { YTNode } from '../helpers.ts'; import type Button from './Button.ts'; import type MultiMarkersPlayerBar from './MultiMarkersPlayerBar.ts'; +import type { RawNode } from '../index.ts'; class DecoratedPlayerBar extends YTNode { static type = 'DecoratedPlayerBar'; @@ -9,7 +10,7 @@ class DecoratedPlayerBar extends YTNode { player_bar: MultiMarkersPlayerBar | null; player_bar_action_button: Button | null; - constructor(data: any) { + constructor(data: RawNode) { super(); this.player_bar = Parser.parseItem(data.playerBar); this.player_bar_action_button = Parser.parseItem