youtubei 1.6.6 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/common/shared/HTTP/HTTP.js +4 -2
- package/dist/cjs/common/utils/helper.js +5 -1
- package/dist/cjs/music/MusicClient/MusicClient.js +2 -2
- package/dist/cjs/music/constants.js +2 -1
- package/dist/cjs/youtube/BaseVideo/BaseVideoParser.js +13 -1
- package/dist/cjs/youtube/BaseVideo/VideoCaptions.js +5 -4
- package/dist/cjs/youtube/Client/Client.js +2 -2
- package/dist/cjs/youtube/PlaylistCompact/PlaylistCompact.js +9 -0
- package/dist/cjs/youtube/PlaylistCompact/PlaylistCompactParser.js +23 -0
- package/dist/cjs/youtube/SearchResult/SearchResultParser.js +10 -0
- package/dist/cjs/youtube/SearchResult/proto/index.js +4 -2
- package/dist/cjs/youtube/VideoCompact/VideoCompact.js +9 -0
- package/dist/cjs/youtube/VideoCompact/VideoCompactParser.js +31 -2
- package/dist/esm/common/shared/HTTP/HTTP.js +7 -5
- package/dist/esm/common/utils/helper.js +5 -1
- package/dist/esm/music/MusicClient/MusicClient.js +3 -3
- package/dist/esm/music/constants.js +1 -0
- package/dist/esm/youtube/BaseVideo/BaseVideoParser.js +13 -1
- package/dist/esm/youtube/BaseVideo/VideoCaptions.js +8 -7
- package/dist/esm/youtube/Client/Client.js +2 -2
- package/dist/esm/youtube/PlaylistCompact/PlaylistCompact.js +9 -0
- package/dist/esm/youtube/PlaylistCompact/PlaylistCompactParser.js +23 -0
- package/dist/esm/youtube/SearchResult/SearchResultParser.js +10 -0
- package/dist/esm/youtube/SearchResult/proto/index.js +3 -1
- package/dist/esm/youtube/VideoCompact/VideoCompact.js +9 -0
- package/dist/esm/youtube/VideoCompact/VideoCompactParser.js +31 -2
- package/dist/typings/common/shared/HTTP/HTTP.d.ts +7 -1
- package/dist/typings/music/MusicClient/MusicClient.d.ts +2 -9
- package/dist/typings/music/constants.d.ts +1 -0
- package/dist/typings/youtube/Client/Client.d.ts +3 -11
- package/dist/typings/youtube/PlaylistCompact/PlaylistCompact.d.ts +6 -0
- package/dist/typings/youtube/PlaylistCompact/PlaylistCompactParser.d.ts +1 -0
- package/dist/typings/youtube/VideoCompact/VideoCompact.d.ts +8 -0
- package/dist/typings/youtube/VideoCompact/VideoCompactParser.d.ts +1 -0
- package/package.json +1 -1
|
@@ -33,6 +33,7 @@ class HTTP {
|
|
|
33
33
|
"accept-encoding": "gzip, deflate, br",
|
|
34
34
|
};
|
|
35
35
|
this.oauth = Object.assign({ enabled: false, token: null, expiresAt: null }, options.oauth);
|
|
36
|
+
this.pot = options.pot;
|
|
36
37
|
this.authorizationPromise = null;
|
|
37
38
|
this.defaultFetchOptions = options.fetchOptions || {};
|
|
38
39
|
this.defaultClientOptions = options.youtubeClientOptions || {};
|
|
@@ -43,10 +44,11 @@ class HTTP {
|
|
|
43
44
|
});
|
|
44
45
|
}
|
|
45
46
|
post(path, options) {
|
|
47
|
+
var _a;
|
|
46
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
47
49
|
return yield this.request(path, Object.assign(Object.assign({}, options), { method: "POST", params: Object.assign({ key: this.apiKey, prettyPrint: "false" }, options === null || options === void 0 ? void 0 : options.params), data: Object.assign({ context: {
|
|
48
|
-
client: Object.assign({ clientName: this.clientName, clientVersion: this.clientVersion }, this.defaultClientOptions),
|
|
49
|
-
} }, options === null || options === void 0 ? void 0 : options.data) }));
|
|
50
|
+
client: Object.assign({ clientName: this.clientName, clientVersion: this.clientVersion, visitorData: (_a = this.pot) === null || _a === void 0 ? void 0 : _a.visitorData }, this.defaultClientOptions),
|
|
51
|
+
}, serviceIntegrityDimensions: this.pot ? { poToken: this.pot.token } : undefined }, options === null || options === void 0 ? void 0 : options.data) }));
|
|
50
52
|
});
|
|
51
53
|
}
|
|
52
54
|
request(path, partialOptions) {
|
|
@@ -26,6 +26,7 @@ const stripToInt = (string) => {
|
|
|
26
26
|
};
|
|
27
27
|
exports.stripToInt = stripToInt;
|
|
28
28
|
const getContinuationFromItems = (items, accessors = ["continuationEndpoint"]) => {
|
|
29
|
+
var _a, _b, _c;
|
|
29
30
|
const continuation = items[items.length - 1];
|
|
30
31
|
const renderer = continuation === null || continuation === void 0 ? void 0 : continuation.continuationItemRenderer;
|
|
31
32
|
if (!renderer)
|
|
@@ -34,7 +35,10 @@ const getContinuationFromItems = (items, accessors = ["continuationEndpoint"]) =
|
|
|
34
35
|
for (const accessor of accessors) {
|
|
35
36
|
current = current[accessor];
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
if ((_b = (_a = current === null || current === void 0 ? void 0 : current.commandExecutorCommand) === null || _a === void 0 ? void 0 : _a.commands) === null || _b === void 0 ? void 0 : _b.length) {
|
|
39
|
+
current = current.commandExecutorCommand.commands.find((cmd) => "continuationCommand" in cmd);
|
|
40
|
+
}
|
|
41
|
+
return (_c = current === null || current === void 0 ? void 0 : current.continuationCommand) === null || _c === void 0 ? void 0 : _c.token;
|
|
38
42
|
};
|
|
39
43
|
exports.getContinuationFromItems = getContinuationFromItems;
|
|
40
44
|
const mapFilter = (items, key) => {
|
|
@@ -17,8 +17,8 @@ const constants_1 = require("../constants");
|
|
|
17
17
|
/** Youtube Music Client */
|
|
18
18
|
class MusicClient {
|
|
19
19
|
constructor(options = {}) {
|
|
20
|
-
const fullOptions = Object.assign(Object.assign({ initialCookie: "", fetchOptions: {} }, options), { youtubeClientOptions: Object.assign({ hl: "en", gl: "US" }, options.youtubeClientOptions) });
|
|
21
|
-
this.http = new common_1.HTTP(
|
|
20
|
+
const fullOptions = Object.assign(Object.assign({ initialCookie: "", oauth: { enabled: false }, fetchOptions: {} }, options), { youtubeClientOptions: Object.assign({ hl: "en", gl: "US" }, options.youtubeClientOptions), apiKey: options.apiKey || constants_1.INNERTUBE_API_KEY, baseUrl: options.baseUrl || constants_1.BASE_URL, clientName: options.clientName || constants_1.INNERTUBE_CLIENT_NAME, clientVersion: options.clientVersion || constants_1.INNERTUBE_CLIENT_VERSION });
|
|
21
|
+
this.http = new common_1.HTTP(fullOptions);
|
|
22
22
|
}
|
|
23
23
|
search(query, type) {
|
|
24
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.I_END_POINT = exports.BASE_URL = exports.INNERTUBE_API_KEY = exports.INNERTUBE_CLIENT_VERSION = void 0;
|
|
3
|
+
exports.I_END_POINT = exports.BASE_URL = exports.INNERTUBE_API_KEY = exports.INNERTUBE_CLIENT_NAME = exports.INNERTUBE_CLIENT_VERSION = void 0;
|
|
4
4
|
exports.INNERTUBE_CLIENT_VERSION = "1.20221219.01.00";
|
|
5
|
+
exports.INNERTUBE_CLIENT_NAME = "WEB_REMIX";
|
|
5
6
|
exports.INNERTUBE_API_KEY = "AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30";
|
|
6
7
|
exports.BASE_URL = "music.youtube.com";
|
|
7
8
|
exports.I_END_POINT = "/youtubei/v1";
|
|
@@ -28,7 +28,9 @@ class BaseVideoParser {
|
|
|
28
28
|
});
|
|
29
29
|
// Like Count and Dislike Count
|
|
30
30
|
const topLevelButtons = videoInfo.videoActions.menuRenderer.topLevelButtons;
|
|
31
|
-
target.likeCount =
|
|
31
|
+
target.likeCount = topLevelButtons
|
|
32
|
+
? common_1.stripToInt(BaseVideoParser.parseButtonRenderer(topLevelButtons[0]))
|
|
33
|
+
: null;
|
|
32
34
|
// Tags and description
|
|
33
35
|
target.tags =
|
|
34
36
|
((_b = (_a = videoInfo.superTitleLink) === null || _a === void 0 ? void 0 : _a.runs) === null || _b === void 0 ? void 0 : _b.map((r) => r.text.trim()).filter((t) => t)) || [];
|
|
@@ -73,6 +75,16 @@ class BaseVideoParser {
|
|
|
73
75
|
else if ("compactRadioRenderer" in data) {
|
|
74
76
|
return new PlaylistCompact_1.PlaylistCompact({ client }).load(data.compactRadioRenderer);
|
|
75
77
|
}
|
|
78
|
+
else if ("lockupViewModel" in data) {
|
|
79
|
+
// new data structure for related contents
|
|
80
|
+
const type = data.lockupViewModel.contentType;
|
|
81
|
+
if (type === "LOCKUP_CONTENT_TYPE_VIDEO") {
|
|
82
|
+
return new VideoCompact_1.VideoCompact({ client }).loadLockup(data.lockupViewModel);
|
|
83
|
+
}
|
|
84
|
+
else if (type === "LOCKUP_CONTENT_TYPE_PLAYLIST") {
|
|
85
|
+
return new PlaylistCompact_1.PlaylistCompact({ client }).loadLockup(data.lockupViewModel);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
76
88
|
}
|
|
77
89
|
static parseRelatedFromSecondaryContent(secondaryContents, client) {
|
|
78
90
|
return secondaryContents
|
|
@@ -52,18 +52,19 @@ class VideoCaptions extends Base_1.Base {
|
|
|
52
52
|
* Get captions of a specific language or a translation of a specific language
|
|
53
53
|
*/
|
|
54
54
|
get(languageCode, translationLanguageCode) {
|
|
55
|
-
var _a, _b;
|
|
55
|
+
var _a, _b, _c;
|
|
56
56
|
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
-
if (!languageCode)
|
|
57
|
+
if (!languageCode && ((_a = this.client.options.youtubeClientOptions) === null || _a === void 0 ? void 0 : _a.hl)) {
|
|
58
58
|
languageCode = this.client.options.youtubeClientOptions.hl;
|
|
59
|
-
|
|
59
|
+
}
|
|
60
|
+
const url = (_b = this.languages.find((l) => l.code.toUpperCase() === (languageCode === null || languageCode === void 0 ? void 0 : languageCode.toUpperCase()))) === null || _b === void 0 ? void 0 : _b.url;
|
|
60
61
|
if (!url)
|
|
61
62
|
return undefined;
|
|
62
63
|
const params = { fmt: "json3" };
|
|
63
64
|
if (translationLanguageCode)
|
|
64
65
|
params["tlang"] = translationLanguageCode;
|
|
65
66
|
const response = yield this.client.http.get(url, { params });
|
|
66
|
-
const captions = (
|
|
67
|
+
const captions = (_c = response.data.events) === null || _c === void 0 ? void 0 : _c.reduce((curr, e) => {
|
|
67
68
|
var _a;
|
|
68
69
|
if (e.segs === undefined)
|
|
69
70
|
return curr;
|
|
@@ -21,8 +21,8 @@ const constants_1 = require("../constants");
|
|
|
21
21
|
/** Youtube Client */
|
|
22
22
|
class Client {
|
|
23
23
|
constructor(options = {}) {
|
|
24
|
-
this.options = Object.assign(Object.assign({ initialCookie: "", oauth: { enabled: false }, fetchOptions: {} }, options), { youtubeClientOptions: Object.assign({ hl: "en", gl: "US" }, options.youtubeClientOptions) });
|
|
25
|
-
this.http = new common_1.HTTP(
|
|
24
|
+
this.options = Object.assign(Object.assign({ initialCookie: "", oauth: { enabled: false }, fetchOptions: {} }, options), { youtubeClientOptions: Object.assign({ hl: "en", gl: "US" }, options.youtubeClientOptions), apiKey: options.apiKey || constants_1.INNERTUBE_API_KEY, baseUrl: options.baseUrl || constants_1.BASE_URL, clientName: options.clientName || constants_1.INNERTUBE_CLIENT_NAME, clientVersion: options.clientVersion || constants_1.INNERTUBE_CLIENT_VERSION });
|
|
25
|
+
this.http = new common_1.HTTP(this.options);
|
|
26
26
|
}
|
|
27
27
|
get oauth() {
|
|
28
28
|
return {
|
|
@@ -28,6 +28,15 @@ class PlaylistCompact extends Base_1.Base {
|
|
|
28
28
|
PlaylistCompactParser_1.PlaylistCompactParser.loadPlaylistCompact(this, data);
|
|
29
29
|
return this;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Load this instance with raw lockup data from Youtube
|
|
33
|
+
*
|
|
34
|
+
* @hidden
|
|
35
|
+
*/
|
|
36
|
+
loadLockup(data) {
|
|
37
|
+
PlaylistCompactParser_1.PlaylistCompactParser.loadLockupPlaylistCompact(this, data);
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
31
40
|
/**
|
|
32
41
|
* Get {@link Playlist} object based on current playlist id
|
|
33
42
|
*
|
|
@@ -23,5 +23,28 @@ class PlaylistCompactParser {
|
|
|
23
23
|
}
|
|
24
24
|
return target;
|
|
25
25
|
}
|
|
26
|
+
static loadLockupPlaylistCompact(target, data) {
|
|
27
|
+
const lockupMetadataViewModel = data.metadata.lockupMetadataViewModel;
|
|
28
|
+
const channelMetadata = lockupMetadataViewModel.metadata.contentMetadataViewModel.metadataRows[0]
|
|
29
|
+
.metadataParts[0];
|
|
30
|
+
const thumbnailViewModel = data.contentImage.collectionThumbnailViewModel.primaryThumbnail.thumbnailViewModel;
|
|
31
|
+
if (channelMetadata.text.commandRuns) {
|
|
32
|
+
// not a mix
|
|
33
|
+
const channel = new BaseChannel_1.BaseChannel({
|
|
34
|
+
client: target.client,
|
|
35
|
+
name: channelMetadata.text.content,
|
|
36
|
+
id: channelMetadata.text.commandRuns[0].onTap.innertubeCommand.browseEndpoint
|
|
37
|
+
.browseId,
|
|
38
|
+
});
|
|
39
|
+
target.channel = channel;
|
|
40
|
+
}
|
|
41
|
+
target.id = data.contentId;
|
|
42
|
+
target.title = lockupMetadataViewModel.title.content;
|
|
43
|
+
target.videoCount =
|
|
44
|
+
common_1.stripToInt(thumbnailViewModel.overlays[0].thumbnailOverlayBadgeViewModel.thumbnailBadges[0]
|
|
45
|
+
.thumbnailBadgeViewModel.text) || 0;
|
|
46
|
+
target.thumbnails = new common_1.Thumbnails().load(thumbnailViewModel.image.sources);
|
|
47
|
+
return target;
|
|
48
|
+
}
|
|
26
49
|
}
|
|
27
50
|
exports.PlaylistCompactParser = PlaylistCompactParser;
|
|
@@ -33,6 +33,16 @@ class SearchResultParser {
|
|
|
33
33
|
contents.push(new VideoCompact_1.VideoCompact({ client }).load(c.videoRenderer));
|
|
34
34
|
else if ("channelRenderer" in c)
|
|
35
35
|
contents.push(new BaseChannel_1.BaseChannel({ client }).load(c.channelRenderer));
|
|
36
|
+
else if ("lockupViewModel" in c) {
|
|
37
|
+
// new data structure for search result
|
|
38
|
+
const type = c.lockupViewModel.contentType;
|
|
39
|
+
if (type === "LOCKUP_CONTENT_TYPE_VIDEO") {
|
|
40
|
+
contents.push(new VideoCompact_1.VideoCompact({ client }).loadLockup(c.lockupViewModel));
|
|
41
|
+
}
|
|
42
|
+
else if (type === "LOCKUP_CONTENT_TYPE_PLAYLIST") {
|
|
43
|
+
contents.push(new PlaylistCompact_1.PlaylistCompact({ client }).loadLockup(c.lockupViewModel));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
36
46
|
}
|
|
37
47
|
return contents;
|
|
38
48
|
}
|
|
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.optionsToProto = exports.SearchProto = void 0;
|
|
7
7
|
const protobufjs_1 = __importDefault(require("protobufjs"));
|
|
8
8
|
// TODO move this to .proto file
|
|
9
|
-
exports.SearchProto = protobufjs_1.default
|
|
9
|
+
exports.SearchProto = protobufjs_1.default
|
|
10
|
+
.parse(`
|
|
10
11
|
message SearchOptions {
|
|
11
12
|
message Options {
|
|
12
13
|
optional int32 uploadDate = 1;
|
|
@@ -26,7 +27,8 @@ exports.SearchProto = protobufjs_1.default.parse(`
|
|
|
26
27
|
optional int32 sortBy = 1;
|
|
27
28
|
optional Options options = 2;
|
|
28
29
|
}
|
|
29
|
-
`)
|
|
30
|
+
`)
|
|
31
|
+
.root.lookupType("SearchOptions");
|
|
30
32
|
const searchUploadDateProto = {
|
|
31
33
|
all: 0,
|
|
32
34
|
hour: 1,
|
|
@@ -32,6 +32,15 @@ class VideoCompact extends Base_1.Base {
|
|
|
32
32
|
VideoCompactParser_1.VideoCompactParser.loadVideoCompact(this, data);
|
|
33
33
|
return this;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Load this instance with raw lockup data from Youtube
|
|
37
|
+
*
|
|
38
|
+
* @hidden
|
|
39
|
+
*/
|
|
40
|
+
loadLockup(data) {
|
|
41
|
+
VideoCompactParser_1.VideoCompactParser.loadLockupVideoCompact(this, data);
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
35
44
|
/**
|
|
36
45
|
* Get {@link Video} object based on current video id
|
|
37
46
|
*
|
|
@@ -5,7 +5,7 @@ const common_1 = require("../../common");
|
|
|
5
5
|
const BaseChannel_1 = require("../BaseChannel");
|
|
6
6
|
class VideoCompactParser {
|
|
7
7
|
static loadVideoCompact(target, data) {
|
|
8
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
8
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
9
9
|
const { videoId, title, headline, lengthText, thumbnail, ownerText, shortBylineText, publishedTimeText, viewCountText, badges, thumbnailOverlays, channelThumbnailSupportedRenderers, detailedMetadataSnippets, } = data;
|
|
10
10
|
target.id = videoId;
|
|
11
11
|
target.title = headline
|
|
@@ -21,8 +21,10 @@ class VideoCompactParser {
|
|
|
21
21
|
target.isLive =
|
|
22
22
|
!!((badges === null || badges === void 0 ? void 0 : badges[0].metadataBadgeRenderer.style) === "BADGE_STYLE_TYPE_LIVE_NOW") ||
|
|
23
23
|
((_e = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _e === void 0 ? void 0 : _e.style) === "LIVE";
|
|
24
|
+
target.isShort =
|
|
25
|
+
((_f = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _f === void 0 ? void 0 : _f.style) === "SHORTS" || false;
|
|
24
26
|
// Channel
|
|
25
|
-
const browseEndpoint = (
|
|
27
|
+
const browseEndpoint = (_j = (_h = (_g = (ownerText || shortBylineText)) === null || _g === void 0 ? void 0 : _g.runs[0]) === null || _h === void 0 ? void 0 : _h.navigationEndpoint) === null || _j === void 0 ? void 0 : _j.browseEndpoint;
|
|
26
28
|
if (browseEndpoint) {
|
|
27
29
|
const id = browseEndpoint.browseId;
|
|
28
30
|
const thumbnails = channelThumbnailSupportedRenderers === null || channelThumbnailSupportedRenderers === void 0 ? void 0 : channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail.thumbnails;
|
|
@@ -36,5 +38,32 @@ class VideoCompactParser {
|
|
|
36
38
|
target.viewCount = common_1.stripToInt((viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.simpleText) || (viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.runs[0].text));
|
|
37
39
|
return target;
|
|
38
40
|
}
|
|
41
|
+
static loadLockupVideoCompact(target, data) {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
const lockupMetadataViewModel = data.metadata.lockupMetadataViewModel;
|
|
44
|
+
const decoratedAvatarViewModel = lockupMetadataViewModel.image.decoratedAvatarViewModel;
|
|
45
|
+
const thumbnailBadge = data.contentImage.thumbnailViewModel.overlays[0].thumbnailOverlayBadgeViewModel
|
|
46
|
+
.thumbnailBadges[0].thumbnailBadgeViewModel;
|
|
47
|
+
const metadataRows = lockupMetadataViewModel.metadata.contentMetadataViewModel.metadataRows;
|
|
48
|
+
const channel = new BaseChannel_1.BaseChannel({
|
|
49
|
+
client: target.client,
|
|
50
|
+
name: metadataRows[0].metadataParts[0].text.content,
|
|
51
|
+
id: decoratedAvatarViewModel.rendererContext.commandContext.onTap.innertubeCommand
|
|
52
|
+
.browseEndpoint.browseId,
|
|
53
|
+
thumbnails: new common_1.Thumbnails().load(decoratedAvatarViewModel.avatar.avatarViewModel.image.sources),
|
|
54
|
+
});
|
|
55
|
+
const isLive = ((_a = thumbnailBadge.icon) === null || _a === void 0 ? void 0 : _a.sources[0].clientResource.imageName) === "LIVE";
|
|
56
|
+
target.channel = channel;
|
|
57
|
+
target.id = data.contentId;
|
|
58
|
+
target.title = lockupMetadataViewModel.title.content;
|
|
59
|
+
target.isLive = ((_b = thumbnailBadge.icon) === null || _b === void 0 ? void 0 : _b.sources[0].clientResource.imageName) === "LIVE";
|
|
60
|
+
target.duration = !isLive ? common_1.getDuration(thumbnailBadge.text) : null;
|
|
61
|
+
target.thumbnails = new common_1.Thumbnails().load(data.contentImage.thumbnailViewModel.image.sources);
|
|
62
|
+
target.viewCount = common_1.stripToInt(metadataRows[1].metadataParts[0].text.content);
|
|
63
|
+
target.uploadDate = !isLive
|
|
64
|
+
? metadataRows[1].metadataParts[metadataRows[1].metadataParts.length - 1].text.content
|
|
65
|
+
: undefined;
|
|
66
|
+
return target;
|
|
67
|
+
}
|
|
39
68
|
}
|
|
40
69
|
exports.VideoCompactParser = VideoCompactParser;
|
|
@@ -92,6 +92,7 @@ var HTTP = /** @class */ (function () {
|
|
|
92
92
|
"accept-encoding": "gzip, deflate, br",
|
|
93
93
|
};
|
|
94
94
|
this.oauth = __assign({ enabled: false, token: null, expiresAt: null }, options.oauth);
|
|
95
|
+
this.pot = options.pot;
|
|
95
96
|
this.authorizationPromise = null;
|
|
96
97
|
this.defaultFetchOptions = options.fetchOptions || {};
|
|
97
98
|
this.defaultClientOptions = options.youtubeClientOptions || {};
|
|
@@ -107,13 +108,14 @@ var HTTP = /** @class */ (function () {
|
|
|
107
108
|
});
|
|
108
109
|
};
|
|
109
110
|
HTTP.prototype.post = function (path, options) {
|
|
111
|
+
var _a;
|
|
110
112
|
return __awaiter(this, void 0, void 0, function () {
|
|
111
|
-
return __generator(this, function (
|
|
112
|
-
switch (
|
|
113
|
+
return __generator(this, function (_b) {
|
|
114
|
+
switch (_b.label) {
|
|
113
115
|
case 0: return [4 /*yield*/, this.request(path, __assign(__assign({}, options), { method: "POST", params: __assign({ key: this.apiKey, prettyPrint: "false" }, options === null || options === void 0 ? void 0 : options.params), data: __assign({ context: {
|
|
114
|
-
client: __assign({ clientName: this.clientName, clientVersion: this.clientVersion }, this.defaultClientOptions),
|
|
115
|
-
} }, options === null || options === void 0 ? void 0 : options.data) }))];
|
|
116
|
-
case 1: return [2 /*return*/,
|
|
116
|
+
client: __assign({ clientName: this.clientName, clientVersion: this.clientVersion, visitorData: (_a = this.pot) === null || _a === void 0 ? void 0 : _a.visitorData }, this.defaultClientOptions),
|
|
117
|
+
}, serviceIntegrityDimensions: this.pot ? { poToken: this.pot.token } : undefined }, options === null || options === void 0 ? void 0 : options.data) }))];
|
|
118
|
+
case 1: return [2 /*return*/, _b.sent()];
|
|
117
119
|
}
|
|
118
120
|
});
|
|
119
121
|
});
|
|
@@ -33,6 +33,7 @@ export var stripToInt = function (string) {
|
|
|
33
33
|
};
|
|
34
34
|
export var getContinuationFromItems = function (items, accessors) {
|
|
35
35
|
var e_1, _a;
|
|
36
|
+
var _b, _c, _d;
|
|
36
37
|
if (accessors === void 0) { accessors = ["continuationEndpoint"]; }
|
|
37
38
|
var continuation = items[items.length - 1];
|
|
38
39
|
var renderer = continuation === null || continuation === void 0 ? void 0 : continuation.continuationItemRenderer;
|
|
@@ -52,7 +53,10 @@ export var getContinuationFromItems = function (items, accessors) {
|
|
|
52
53
|
}
|
|
53
54
|
finally { if (e_1) throw e_1.error; }
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
+
if ((_c = (_b = current === null || current === void 0 ? void 0 : current.commandExecutorCommand) === null || _b === void 0 ? void 0 : _b.commands) === null || _c === void 0 ? void 0 : _c.length) {
|
|
57
|
+
current = current.commandExecutorCommand.commands.find(function (cmd) { return "continuationCommand" in cmd; });
|
|
58
|
+
}
|
|
59
|
+
return (_d = current === null || current === void 0 ? void 0 : current.continuationCommand) === null || _d === void 0 ? void 0 : _d.token;
|
|
56
60
|
};
|
|
57
61
|
export var mapFilter = function (items, key) {
|
|
58
62
|
return items
|
|
@@ -48,13 +48,13 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
48
48
|
import { HTTP } from "../../common";
|
|
49
49
|
import { MusicLyrics } from "../MusicLyrics";
|
|
50
50
|
import { MusicAllSearchResultParser, MusicSearchResult, } from "../MusicSearchResult";
|
|
51
|
-
import { BASE_URL, INNERTUBE_API_KEY, INNERTUBE_CLIENT_VERSION, I_END_POINT } from "../constants";
|
|
51
|
+
import { BASE_URL, INNERTUBE_API_KEY, INNERTUBE_CLIENT_NAME, INNERTUBE_CLIENT_VERSION, I_END_POINT, } from "../constants";
|
|
52
52
|
/** Youtube Music Client */
|
|
53
53
|
var MusicClient = /** @class */ (function () {
|
|
54
54
|
function MusicClient(options) {
|
|
55
55
|
if (options === void 0) { options = {}; }
|
|
56
|
-
var fullOptions = __assign(__assign({ initialCookie: "", fetchOptions: {} }, options), { youtubeClientOptions: __assign({ hl: "en", gl: "US" }, options.youtubeClientOptions) });
|
|
57
|
-
this.http = new HTTP(
|
|
56
|
+
var fullOptions = __assign(__assign({ initialCookie: "", oauth: { enabled: false }, fetchOptions: {} }, options), { youtubeClientOptions: __assign({ hl: "en", gl: "US" }, options.youtubeClientOptions), apiKey: options.apiKey || INNERTUBE_API_KEY, baseUrl: options.baseUrl || BASE_URL, clientName: options.clientName || INNERTUBE_CLIENT_NAME, clientVersion: options.clientVersion || INNERTUBE_CLIENT_VERSION });
|
|
57
|
+
this.http = new HTTP(fullOptions);
|
|
58
58
|
}
|
|
59
59
|
MusicClient.prototype.search = function (query, type) {
|
|
60
60
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -38,7 +38,9 @@ var BaseVideoParser = /** @class */ (function () {
|
|
|
38
38
|
});
|
|
39
39
|
// Like Count and Dislike Count
|
|
40
40
|
var topLevelButtons = videoInfo.videoActions.menuRenderer.topLevelButtons;
|
|
41
|
-
target.likeCount =
|
|
41
|
+
target.likeCount = topLevelButtons
|
|
42
|
+
? stripToInt(BaseVideoParser.parseButtonRenderer(topLevelButtons[0]))
|
|
43
|
+
: null;
|
|
42
44
|
// Tags and description
|
|
43
45
|
target.tags =
|
|
44
46
|
((_b = (_a = videoInfo.superTitleLink) === null || _a === void 0 ? void 0 : _a.runs) === null || _b === void 0 ? void 0 : _b.map(function (r) { return r.text.trim(); }).filter(function (t) { return t; })) || [];
|
|
@@ -83,6 +85,16 @@ var BaseVideoParser = /** @class */ (function () {
|
|
|
83
85
|
else if ("compactRadioRenderer" in data) {
|
|
84
86
|
return new PlaylistCompact({ client: client }).load(data.compactRadioRenderer);
|
|
85
87
|
}
|
|
88
|
+
else if ("lockupViewModel" in data) {
|
|
89
|
+
// new data structure for related contents
|
|
90
|
+
var type = data.lockupViewModel.contentType;
|
|
91
|
+
if (type === "LOCKUP_CONTENT_TYPE_VIDEO") {
|
|
92
|
+
return new VideoCompact({ client: client }).loadLockup(data.lockupViewModel);
|
|
93
|
+
}
|
|
94
|
+
else if (type === "LOCKUP_CONTENT_TYPE_PLAYLIST") {
|
|
95
|
+
return new PlaylistCompact({ client: client }).loadLockup(data.lockupViewModel);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
86
98
|
};
|
|
87
99
|
BaseVideoParser.parseRelatedFromSecondaryContent = function (secondaryContents, client) {
|
|
88
100
|
return secondaryContents
|
|
@@ -95,15 +95,16 @@ var VideoCaptions = /** @class */ (function (_super) {
|
|
|
95
95
|
* Get captions of a specific language or a translation of a specific language
|
|
96
96
|
*/
|
|
97
97
|
VideoCaptions.prototype.get = function (languageCode, translationLanguageCode) {
|
|
98
|
-
var _a, _b;
|
|
98
|
+
var _a, _b, _c;
|
|
99
99
|
return __awaiter(this, void 0, void 0, function () {
|
|
100
100
|
var url, params, response, captions;
|
|
101
|
-
return __generator(this, function (
|
|
102
|
-
switch (
|
|
101
|
+
return __generator(this, function (_d) {
|
|
102
|
+
switch (_d.label) {
|
|
103
103
|
case 0:
|
|
104
|
-
if (!languageCode)
|
|
104
|
+
if (!languageCode && ((_a = this.client.options.youtubeClientOptions) === null || _a === void 0 ? void 0 : _a.hl)) {
|
|
105
105
|
languageCode = this.client.options.youtubeClientOptions.hl;
|
|
106
|
-
|
|
106
|
+
}
|
|
107
|
+
url = (_b = this.languages.find(function (l) { return l.code.toUpperCase() === (languageCode === null || languageCode === void 0 ? void 0 : languageCode.toUpperCase()); })) === null || _b === void 0 ? void 0 : _b.url;
|
|
107
108
|
if (!url)
|
|
108
109
|
return [2 /*return*/, undefined];
|
|
109
110
|
params = { fmt: "json3" };
|
|
@@ -111,8 +112,8 @@ var VideoCaptions = /** @class */ (function (_super) {
|
|
|
111
112
|
params["tlang"] = translationLanguageCode;
|
|
112
113
|
return [4 /*yield*/, this.client.http.get(url, { params: params })];
|
|
113
114
|
case 1:
|
|
114
|
-
response =
|
|
115
|
-
captions = (
|
|
115
|
+
response = _d.sent();
|
|
116
|
+
captions = (_c = response.data.events) === null || _c === void 0 ? void 0 : _c.reduce(function (curr, e) {
|
|
116
117
|
var _a;
|
|
117
118
|
if (e.segs === undefined)
|
|
118
119
|
return curr;
|
|
@@ -73,8 +73,8 @@ import { BASE_URL, INNERTUBE_API_KEY, INNERTUBE_CLIENT_NAME, INNERTUBE_CLIENT_VE
|
|
|
73
73
|
var Client = /** @class */ (function () {
|
|
74
74
|
function Client(options) {
|
|
75
75
|
if (options === void 0) { options = {}; }
|
|
76
|
-
this.options = __assign(__assign({ initialCookie: "", oauth: { enabled: false }, fetchOptions: {} }, options), { youtubeClientOptions: __assign({ hl: "en", gl: "US" }, options.youtubeClientOptions) });
|
|
77
|
-
this.http = new HTTP(
|
|
76
|
+
this.options = __assign(__assign({ initialCookie: "", oauth: { enabled: false }, fetchOptions: {} }, options), { youtubeClientOptions: __assign({ hl: "en", gl: "US" }, options.youtubeClientOptions), apiKey: options.apiKey || INNERTUBE_API_KEY, baseUrl: options.baseUrl || BASE_URL, clientName: options.clientName || INNERTUBE_CLIENT_NAME, clientVersion: options.clientVersion || INNERTUBE_CLIENT_VERSION });
|
|
77
|
+
this.http = new HTTP(this.options);
|
|
78
78
|
}
|
|
79
79
|
Object.defineProperty(Client.prototype, "oauth", {
|
|
80
80
|
get: function () {
|
|
@@ -67,6 +67,15 @@ var PlaylistCompact = /** @class */ (function (_super) {
|
|
|
67
67
|
PlaylistCompactParser.loadPlaylistCompact(this, data);
|
|
68
68
|
return this;
|
|
69
69
|
};
|
|
70
|
+
/**
|
|
71
|
+
* Load this instance with raw lockup data from Youtube
|
|
72
|
+
*
|
|
73
|
+
* @hidden
|
|
74
|
+
*/
|
|
75
|
+
PlaylistCompact.prototype.loadLockup = function (data) {
|
|
76
|
+
PlaylistCompactParser.loadLockupPlaylistCompact(this, data);
|
|
77
|
+
return this;
|
|
78
|
+
};
|
|
70
79
|
/**
|
|
71
80
|
* Get {@link Playlist} object based on current playlist id
|
|
72
81
|
*
|
|
@@ -22,6 +22,29 @@ var PlaylistCompactParser = /** @class */ (function () {
|
|
|
22
22
|
}
|
|
23
23
|
return target;
|
|
24
24
|
};
|
|
25
|
+
PlaylistCompactParser.loadLockupPlaylistCompact = function (target, data) {
|
|
26
|
+
var lockupMetadataViewModel = data.metadata.lockupMetadataViewModel;
|
|
27
|
+
var channelMetadata = lockupMetadataViewModel.metadata.contentMetadataViewModel.metadataRows[0]
|
|
28
|
+
.metadataParts[0];
|
|
29
|
+
var thumbnailViewModel = data.contentImage.collectionThumbnailViewModel.primaryThumbnail.thumbnailViewModel;
|
|
30
|
+
if (channelMetadata.text.commandRuns) {
|
|
31
|
+
// not a mix
|
|
32
|
+
var channel = new BaseChannel({
|
|
33
|
+
client: target.client,
|
|
34
|
+
name: channelMetadata.text.content,
|
|
35
|
+
id: channelMetadata.text.commandRuns[0].onTap.innertubeCommand.browseEndpoint
|
|
36
|
+
.browseId,
|
|
37
|
+
});
|
|
38
|
+
target.channel = channel;
|
|
39
|
+
}
|
|
40
|
+
target.id = data.contentId;
|
|
41
|
+
target.title = lockupMetadataViewModel.title.content;
|
|
42
|
+
target.videoCount =
|
|
43
|
+
stripToInt(thumbnailViewModel.overlays[0].thumbnailOverlayBadgeViewModel.thumbnailBadges[0]
|
|
44
|
+
.thumbnailBadgeViewModel.text) || 0;
|
|
45
|
+
target.thumbnails = new Thumbnails().load(thumbnailViewModel.image.sources);
|
|
46
|
+
return target;
|
|
47
|
+
};
|
|
25
48
|
return PlaylistCompactParser;
|
|
26
49
|
}());
|
|
27
50
|
export { PlaylistCompactParser };
|
|
@@ -46,6 +46,16 @@ var SearchResultParser = /** @class */ (function () {
|
|
|
46
46
|
contents.push(new VideoCompact({ client: client }).load(c.videoRenderer));
|
|
47
47
|
else if ("channelRenderer" in c)
|
|
48
48
|
contents.push(new BaseChannel({ client: client }).load(c.channelRenderer));
|
|
49
|
+
else if ("lockupViewModel" in c) {
|
|
50
|
+
// new data structure for search result
|
|
51
|
+
var type = c.lockupViewModel.contentType;
|
|
52
|
+
if (type === "LOCKUP_CONTENT_TYPE_VIDEO") {
|
|
53
|
+
contents.push(new VideoCompact({ client: client }).loadLockup(c.lockupViewModel));
|
|
54
|
+
}
|
|
55
|
+
else if (type === "LOCKUP_CONTENT_TYPE_PLAYLIST") {
|
|
56
|
+
contents.push(new PlaylistCompact({ client: client }).loadLockup(c.lockupViewModel));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
61
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
@@ -11,7 +11,9 @@ var __assign = (this && this.__assign) || function () {
|
|
|
11
11
|
};
|
|
12
12
|
import protobuf from "protobufjs";
|
|
13
13
|
// TODO move this to .proto file
|
|
14
|
-
export var SearchProto = protobuf
|
|
14
|
+
export var SearchProto = protobuf
|
|
15
|
+
.parse("\n\tmessage SearchOptions {\n\t\tmessage Options {\n\t\t\toptional int32 uploadDate = 1;\n\t\t\toptional int32 type = 2;\n\t\t\toptional int32 duration = 3;\n\t\t\toptional int32 hd = 4;\n\t\t\toptional int32 subtitles = 5;\n\t\t\toptional int32 creativeCommons = 6;\n\t\t\toptional int32 live = 8;\n\t\t\toptional int32 _4k = 14;\n\t\t\toptional int32 _360 = 15;\n\t\t\toptional int32 location = 23;\n\t\t\toptional int32 hdr = 25;\n\t\t\toptional int32 vr180 = 26;\n\t\t}\n\n\t\toptional int32 sortBy = 1;\n\t\toptional Options options = 2;\n\t}\n")
|
|
16
|
+
.root.lookupType("SearchOptions");
|
|
15
17
|
var searchUploadDateProto = {
|
|
16
18
|
all: 0,
|
|
17
19
|
hour: 1,
|
|
@@ -75,6 +75,15 @@ var VideoCompact = /** @class */ (function (_super) {
|
|
|
75
75
|
VideoCompactParser.loadVideoCompact(this, data);
|
|
76
76
|
return this;
|
|
77
77
|
};
|
|
78
|
+
/**
|
|
79
|
+
* Load this instance with raw lockup data from Youtube
|
|
80
|
+
*
|
|
81
|
+
* @hidden
|
|
82
|
+
*/
|
|
83
|
+
VideoCompact.prototype.loadLockup = function (data) {
|
|
84
|
+
VideoCompactParser.loadLockupVideoCompact(this, data);
|
|
85
|
+
return this;
|
|
86
|
+
};
|
|
78
87
|
/**
|
|
79
88
|
* Get {@link Video} object based on current video id
|
|
80
89
|
*
|
|
@@ -4,7 +4,7 @@ var VideoCompactParser = /** @class */ (function () {
|
|
|
4
4
|
function VideoCompactParser() {
|
|
5
5
|
}
|
|
6
6
|
VideoCompactParser.loadVideoCompact = function (target, data) {
|
|
7
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
7
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
8
8
|
var videoId = data.videoId, title = data.title, headline = data.headline, lengthText = data.lengthText, thumbnail = data.thumbnail, ownerText = data.ownerText, shortBylineText = data.shortBylineText, publishedTimeText = data.publishedTimeText, viewCountText = data.viewCountText, badges = data.badges, thumbnailOverlays = data.thumbnailOverlays, channelThumbnailSupportedRenderers = data.channelThumbnailSupportedRenderers, detailedMetadataSnippets = data.detailedMetadataSnippets;
|
|
9
9
|
target.id = videoId;
|
|
10
10
|
target.title = headline
|
|
@@ -20,8 +20,10 @@ var VideoCompactParser = /** @class */ (function () {
|
|
|
20
20
|
target.isLive =
|
|
21
21
|
!!((badges === null || badges === void 0 ? void 0 : badges[0].metadataBadgeRenderer.style) === "BADGE_STYLE_TYPE_LIVE_NOW") ||
|
|
22
22
|
((_e = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _e === void 0 ? void 0 : _e.style) === "LIVE";
|
|
23
|
+
target.isShort =
|
|
24
|
+
((_f = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _f === void 0 ? void 0 : _f.style) === "SHORTS" || false;
|
|
23
25
|
// Channel
|
|
24
|
-
var browseEndpoint = (
|
|
26
|
+
var browseEndpoint = (_j = (_h = (_g = (ownerText || shortBylineText)) === null || _g === void 0 ? void 0 : _g.runs[0]) === null || _h === void 0 ? void 0 : _h.navigationEndpoint) === null || _j === void 0 ? void 0 : _j.browseEndpoint;
|
|
25
27
|
if (browseEndpoint) {
|
|
26
28
|
var id = browseEndpoint.browseId;
|
|
27
29
|
var thumbnails = channelThumbnailSupportedRenderers === null || channelThumbnailSupportedRenderers === void 0 ? void 0 : channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail.thumbnails;
|
|
@@ -35,6 +37,33 @@ var VideoCompactParser = /** @class */ (function () {
|
|
|
35
37
|
target.viewCount = stripToInt((viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.simpleText) || (viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.runs[0].text));
|
|
36
38
|
return target;
|
|
37
39
|
};
|
|
40
|
+
VideoCompactParser.loadLockupVideoCompact = function (target, data) {
|
|
41
|
+
var _a, _b;
|
|
42
|
+
var lockupMetadataViewModel = data.metadata.lockupMetadataViewModel;
|
|
43
|
+
var decoratedAvatarViewModel = lockupMetadataViewModel.image.decoratedAvatarViewModel;
|
|
44
|
+
var thumbnailBadge = data.contentImage.thumbnailViewModel.overlays[0].thumbnailOverlayBadgeViewModel
|
|
45
|
+
.thumbnailBadges[0].thumbnailBadgeViewModel;
|
|
46
|
+
var metadataRows = lockupMetadataViewModel.metadata.contentMetadataViewModel.metadataRows;
|
|
47
|
+
var channel = new BaseChannel({
|
|
48
|
+
client: target.client,
|
|
49
|
+
name: metadataRows[0].metadataParts[0].text.content,
|
|
50
|
+
id: decoratedAvatarViewModel.rendererContext.commandContext.onTap.innertubeCommand
|
|
51
|
+
.browseEndpoint.browseId,
|
|
52
|
+
thumbnails: new Thumbnails().load(decoratedAvatarViewModel.avatar.avatarViewModel.image.sources),
|
|
53
|
+
});
|
|
54
|
+
var isLive = ((_a = thumbnailBadge.icon) === null || _a === void 0 ? void 0 : _a.sources[0].clientResource.imageName) === "LIVE";
|
|
55
|
+
target.channel = channel;
|
|
56
|
+
target.id = data.contentId;
|
|
57
|
+
target.title = lockupMetadataViewModel.title.content;
|
|
58
|
+
target.isLive = ((_b = thumbnailBadge.icon) === null || _b === void 0 ? void 0 : _b.sources[0].clientResource.imageName) === "LIVE";
|
|
59
|
+
target.duration = !isLive ? getDuration(thumbnailBadge.text) : null;
|
|
60
|
+
target.thumbnails = new Thumbnails().load(data.contentImage.thumbnailViewModel.image.sources);
|
|
61
|
+
target.viewCount = stripToInt(metadataRows[1].metadataParts[0].text.content);
|
|
62
|
+
target.uploadDate = !isLive
|
|
63
|
+
? metadataRows[1].metadataParts[metadataRows[1].metadataParts.length - 1].text.content
|
|
64
|
+
: undefined;
|
|
65
|
+
return target;
|
|
66
|
+
};
|
|
38
67
|
return VideoCompactParser;
|
|
39
68
|
}());
|
|
40
69
|
export { VideoCompactParser };
|
|
@@ -8,7 +8,11 @@ export declare type OAuthProps = {
|
|
|
8
8
|
expiresAt: Date | null;
|
|
9
9
|
refreshToken?: string;
|
|
10
10
|
};
|
|
11
|
-
declare type
|
|
11
|
+
export declare type PotOptions = {
|
|
12
|
+
token: string;
|
|
13
|
+
visitorData: string;
|
|
14
|
+
};
|
|
15
|
+
export declare type HTTPOptions = {
|
|
12
16
|
apiKey: string;
|
|
13
17
|
baseUrl: string;
|
|
14
18
|
clientName: string;
|
|
@@ -17,6 +21,7 @@ declare type HTTPOptions = {
|
|
|
17
21
|
youtubeClientOptions?: Record<string, unknown>;
|
|
18
22
|
initialCookie?: string;
|
|
19
23
|
oauth?: OAuthOptions;
|
|
24
|
+
pot?: PotOptions;
|
|
20
25
|
};
|
|
21
26
|
declare type Response<T = any> = {
|
|
22
27
|
data: T;
|
|
@@ -38,6 +43,7 @@ export declare class HTTP {
|
|
|
38
43
|
private defaultFetchOptions;
|
|
39
44
|
private defaultClientOptions;
|
|
40
45
|
private authorizationPromise;
|
|
46
|
+
private pot?;
|
|
41
47
|
oauth: OAuthOptions & OAuthProps;
|
|
42
48
|
constructor(options: HTTPOptions);
|
|
43
49
|
get(path: string, options?: Partial<Options>): Promise<Response>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { HTTP, Shelf } from "../../common";
|
|
1
|
+
import { HTTP, HTTPOptions, Shelf } from "../../common";
|
|
3
2
|
import { MusicAlbumCompact } from "../MusicAlbumCompact";
|
|
4
3
|
import { MusicArtistCompact } from "../MusicArtistCompact";
|
|
5
4
|
import { MusicLyrics } from "../MusicLyrics";
|
|
@@ -10,13 +9,7 @@ export declare type MusicTopShelf = {
|
|
|
10
9
|
item?: MusicVideoCompact | MusicAlbumCompact | MusicPlaylistCompact | MusicArtistCompact;
|
|
11
10
|
more?: (MusicVideoCompact | MusicAlbumCompact | MusicPlaylistCompact | MusicArtistCompact)[];
|
|
12
11
|
};
|
|
13
|
-
export declare type MusicClientOptions =
|
|
14
|
-
initialCookie: string;
|
|
15
|
-
/** Optional options for http client */
|
|
16
|
-
fetchOptions: Partial<RequestInit>;
|
|
17
|
-
/** Optional options passed when sending a request to youtube (context.client) */
|
|
18
|
-
youtubeClientOptions: Record<string, unknown>;
|
|
19
|
-
};
|
|
12
|
+
export declare type MusicClientOptions = HTTPOptions;
|
|
20
13
|
/** Youtube Music Client */
|
|
21
14
|
export declare class MusicClient {
|
|
22
15
|
/** @hidden */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const INNERTUBE_CLIENT_VERSION = "1.20221219.01.00";
|
|
2
|
+
export declare const INNERTUBE_CLIENT_NAME = "WEB_REMIX";
|
|
2
3
|
export declare const INNERTUBE_API_KEY = "AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30";
|
|
3
4
|
export declare const BASE_URL = "music.youtube.com";
|
|
4
5
|
export declare const I_END_POINT = "/youtubei/v1";
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { HTTP, OAuthOptions, OAuthProps } from "../../common";
|
|
1
|
+
import { HTTP, HTTPOptions, OAuthProps } from "../../common";
|
|
3
2
|
import { Caption } from "../Caption";
|
|
4
3
|
import { Channel } from "../Channel";
|
|
5
4
|
import { LiveVideo } from "../LiveVideo";
|
|
@@ -7,20 +6,13 @@ import { MixPlaylist } from "../MixPlaylist";
|
|
|
7
6
|
import { Playlist } from "../Playlist";
|
|
8
7
|
import { SearchOptions, SearchResult, SearchResultItem } from "../SearchResult";
|
|
9
8
|
import { Video } from "../Video";
|
|
10
|
-
export declare type ClientOptions =
|
|
11
|
-
initialCookie: string;
|
|
12
|
-
oauth: OAuthOptions;
|
|
13
|
-
/** Optional options for http client */
|
|
14
|
-
fetchOptions: Partial<RequestInit>;
|
|
15
|
-
/** Optional options passed when sending a request to youtube (context.client) */
|
|
16
|
-
youtubeClientOptions: Record<string, string>;
|
|
17
|
-
};
|
|
9
|
+
export declare type ClientOptions = HTTPOptions;
|
|
18
10
|
/** Youtube Client */
|
|
19
11
|
export declare class Client {
|
|
20
12
|
/** @hidden */
|
|
21
13
|
http: HTTP;
|
|
22
14
|
/** @hidden */
|
|
23
|
-
options:
|
|
15
|
+
options: HTTPOptions;
|
|
24
16
|
constructor(options?: Partial<ClientOptions>);
|
|
25
17
|
get oauth(): OAuthProps;
|
|
26
18
|
/**
|
|
@@ -29,6 +29,12 @@ export declare class PlaylistCompact extends Base implements PlaylistCompactProp
|
|
|
29
29
|
* @hidden
|
|
30
30
|
*/
|
|
31
31
|
load(data: YoutubeRawData): PlaylistCompact;
|
|
32
|
+
/**
|
|
33
|
+
* Load this instance with raw lockup data from Youtube
|
|
34
|
+
*
|
|
35
|
+
* @hidden
|
|
36
|
+
*/
|
|
37
|
+
loadLockup(data: YoutubeRawData): PlaylistCompact;
|
|
32
38
|
/**
|
|
33
39
|
* Get {@link Playlist} object based on current playlist id
|
|
34
40
|
*
|
|
@@ -2,4 +2,5 @@ import { YoutubeRawData } from "../../common";
|
|
|
2
2
|
import { PlaylistCompact } from "./PlaylistCompact";
|
|
3
3
|
export declare class PlaylistCompactParser {
|
|
4
4
|
static loadPlaylistCompact(target: PlaylistCompact, data: YoutubeRawData): PlaylistCompact;
|
|
5
|
+
static loadLockupPlaylistCompact(target: PlaylistCompact, data: YoutubeRawData): PlaylistCompact;
|
|
5
6
|
}
|
|
@@ -28,6 +28,8 @@ export declare class VideoCompact extends Base implements VideoCompactProperties
|
|
|
28
28
|
duration: number | null;
|
|
29
29
|
/** Whether this video is a live now or not */
|
|
30
30
|
isLive: boolean;
|
|
31
|
+
/** Whether this video is a shorts or not */
|
|
32
|
+
isShort: boolean;
|
|
31
33
|
/** The channel who uploads this video */
|
|
32
34
|
channel?: BaseChannel;
|
|
33
35
|
/** The date this video is uploaded at */
|
|
@@ -44,6 +46,12 @@ export declare class VideoCompact extends Base implements VideoCompactProperties
|
|
|
44
46
|
* @hidden
|
|
45
47
|
*/
|
|
46
48
|
load(data: YoutubeRawData): VideoCompact;
|
|
49
|
+
/**
|
|
50
|
+
* Load this instance with raw lockup data from Youtube
|
|
51
|
+
*
|
|
52
|
+
* @hidden
|
|
53
|
+
*/
|
|
54
|
+
loadLockup(data: YoutubeRawData): VideoCompact;
|
|
47
55
|
/**
|
|
48
56
|
* Get {@link Video} object based on current video id
|
|
49
57
|
*
|
|
@@ -2,4 +2,5 @@ import { YoutubeRawData } from "../../common";
|
|
|
2
2
|
import { VideoCompact } from "./VideoCompact";
|
|
3
3
|
export declare class VideoCompactParser {
|
|
4
4
|
static loadVideoCompact(target: VideoCompact, data: YoutubeRawData): VideoCompact;
|
|
5
|
+
static loadLockupVideoCompact(target: VideoCompact, data: YoutubeRawData): VideoCompact;
|
|
5
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "youtubei",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Simple package to get information from youtube such as videos, playlists, channels, video information & comments, related videos, up next video, and more!",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|