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.
Files changed (35) hide show
  1. package/dist/cjs/common/shared/HTTP/HTTP.js +4 -2
  2. package/dist/cjs/common/utils/helper.js +5 -1
  3. package/dist/cjs/music/MusicClient/MusicClient.js +2 -2
  4. package/dist/cjs/music/constants.js +2 -1
  5. package/dist/cjs/youtube/BaseVideo/BaseVideoParser.js +13 -1
  6. package/dist/cjs/youtube/BaseVideo/VideoCaptions.js +5 -4
  7. package/dist/cjs/youtube/Client/Client.js +2 -2
  8. package/dist/cjs/youtube/PlaylistCompact/PlaylistCompact.js +9 -0
  9. package/dist/cjs/youtube/PlaylistCompact/PlaylistCompactParser.js +23 -0
  10. package/dist/cjs/youtube/SearchResult/SearchResultParser.js +10 -0
  11. package/dist/cjs/youtube/SearchResult/proto/index.js +4 -2
  12. package/dist/cjs/youtube/VideoCompact/VideoCompact.js +9 -0
  13. package/dist/cjs/youtube/VideoCompact/VideoCompactParser.js +31 -2
  14. package/dist/esm/common/shared/HTTP/HTTP.js +7 -5
  15. package/dist/esm/common/utils/helper.js +5 -1
  16. package/dist/esm/music/MusicClient/MusicClient.js +3 -3
  17. package/dist/esm/music/constants.js +1 -0
  18. package/dist/esm/youtube/BaseVideo/BaseVideoParser.js +13 -1
  19. package/dist/esm/youtube/BaseVideo/VideoCaptions.js +8 -7
  20. package/dist/esm/youtube/Client/Client.js +2 -2
  21. package/dist/esm/youtube/PlaylistCompact/PlaylistCompact.js +9 -0
  22. package/dist/esm/youtube/PlaylistCompact/PlaylistCompactParser.js +23 -0
  23. package/dist/esm/youtube/SearchResult/SearchResultParser.js +10 -0
  24. package/dist/esm/youtube/SearchResult/proto/index.js +3 -1
  25. package/dist/esm/youtube/VideoCompact/VideoCompact.js +9 -0
  26. package/dist/esm/youtube/VideoCompact/VideoCompactParser.js +31 -2
  27. package/dist/typings/common/shared/HTTP/HTTP.d.ts +7 -1
  28. package/dist/typings/music/MusicClient/MusicClient.d.ts +2 -9
  29. package/dist/typings/music/constants.d.ts +1 -0
  30. package/dist/typings/youtube/Client/Client.d.ts +3 -11
  31. package/dist/typings/youtube/PlaylistCompact/PlaylistCompact.d.ts +6 -0
  32. package/dist/typings/youtube/PlaylistCompact/PlaylistCompactParser.d.ts +1 -0
  33. package/dist/typings/youtube/VideoCompact/VideoCompact.d.ts +8 -0
  34. package/dist/typings/youtube/VideoCompact/VideoCompactParser.d.ts +1 -0
  35. 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
- return current.continuationCommand.token;
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(Object.assign({ apiKey: constants_1.INNERTUBE_API_KEY, baseUrl: constants_1.BASE_URL, clientName: "WEB_REMIX", clientVersion: constants_1.INNERTUBE_CLIENT_VERSION }, fullOptions));
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 = common_1.stripToInt(BaseVideoParser.parseButtonRenderer(topLevelButtons[0]));
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
- const url = (_a = this.languages.find((l) => l.code.toUpperCase() === (languageCode === null || languageCode === void 0 ? void 0 : languageCode.toUpperCase()))) === null || _a === void 0 ? void 0 : _a.url;
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 = (_b = response.data.events) === null || _b === void 0 ? void 0 : _b.reduce((curr, e) => {
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(Object.assign({ apiKey: constants_1.INNERTUBE_API_KEY, baseUrl: constants_1.BASE_URL, clientName: constants_1.INNERTUBE_CLIENT_NAME, clientVersion: constants_1.INNERTUBE_CLIENT_VERSION }, this.options));
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.parse(`
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
- `).root.lookupType("SearchOptions");
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 = (_h = (_g = (_f = (ownerText || shortBylineText)) === null || _f === void 0 ? void 0 : _f.runs[0]) === null || _g === void 0 ? void 0 : _g.navigationEndpoint) === null || _h === void 0 ? void 0 : _h.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 (_a) {
112
- switch (_a.label) {
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*/, _a.sent()];
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
- return current.continuationCommand.token;
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(__assign({ apiKey: INNERTUBE_API_KEY, baseUrl: BASE_URL, clientName: "WEB_REMIX", clientVersion: INNERTUBE_CLIENT_VERSION }, fullOptions));
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 () {
@@ -1,4 +1,5 @@
1
1
  export var INNERTUBE_CLIENT_VERSION = "1.20221219.01.00";
2
+ export var INNERTUBE_CLIENT_NAME = "WEB_REMIX";
2
3
  export var INNERTUBE_API_KEY = "AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30";
3
4
  export var BASE_URL = "music.youtube.com";
4
5
  export var I_END_POINT = "/youtubei/v1";
@@ -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 = stripToInt(BaseVideoParser.parseButtonRenderer(topLevelButtons[0]));
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 (_c) {
102
- switch (_c.label) {
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
- url = (_a = this.languages.find(function (l) { return l.code.toUpperCase() === (languageCode === null || languageCode === void 0 ? void 0 : languageCode.toUpperCase()); })) === null || _a === void 0 ? void 0 : _a.url;
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 = _c.sent();
115
- captions = (_b = response.data.events) === null || _b === void 0 ? void 0 : _b.reduce(function (curr, e) {
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(__assign({ apiKey: INNERTUBE_API_KEY, baseUrl: BASE_URL, clientName: INNERTUBE_CLIENT_NAME, clientVersion: INNERTUBE_CLIENT_VERSION }, this.options));
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.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").root.lookupType("SearchOptions");
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 = (_h = (_g = (_f = (ownerText || shortBylineText)) === null || _f === void 0 ? void 0 : _f.runs[0]) === null || _g === void 0 ? void 0 : _g.navigationEndpoint) === null || _h === void 0 ? void 0 : _h.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 HTTPOptions = {
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 { RequestInit } from "node-fetch";
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 { RequestInit } from "node-fetch";
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: ClientOptions;
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.6.6",
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",