youtubei 1.6.7 → 1.8.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 (58) hide show
  1. package/dist/cjs/common/shared/HTTP/HTTP.js +1 -3
  2. package/dist/cjs/common/utils/helper.js +5 -1
  3. package/dist/cjs/music/MusicClient/MusicClient.js +13 -18
  4. package/dist/cjs/music/MusicSearchResult/MusicSearchResult.js +6 -4
  5. package/dist/cjs/music/MusicSearchResult/MusicSearchResultParser.js +205 -14
  6. package/dist/cjs/music/MusicSearchResult/index.js +0 -1
  7. package/dist/cjs/youtube/BaseChannel/BaseChannel.js +2 -0
  8. package/dist/cjs/youtube/BaseChannel/BaseChannelParser.js +3 -2
  9. package/dist/cjs/youtube/BaseChannel/ChannelPlaylists.js +12 -2
  10. package/dist/cjs/youtube/BaseChannel/ChannelPosts.js +59 -0
  11. package/dist/cjs/youtube/BaseVideo/BaseVideoParser.js +14 -2
  12. package/dist/cjs/youtube/Channel/ChannelParser.js +10 -6
  13. package/dist/cjs/youtube/PlaylistCompact/PlaylistCompact.js +9 -0
  14. package/dist/cjs/youtube/PlaylistCompact/PlaylistCompactParser.js +23 -0
  15. package/dist/cjs/youtube/Post/Post.js +23 -0
  16. package/dist/cjs/youtube/Post/PostParser.js +23 -0
  17. package/dist/cjs/youtube/Post/index.js +14 -0
  18. package/dist/cjs/youtube/SearchResult/SearchResultParser.js +10 -0
  19. package/dist/cjs/youtube/VideoCompact/VideoCompact.js +9 -0
  20. package/dist/cjs/youtube/VideoCompact/VideoCompactParser.js +27 -0
  21. package/dist/esm/common/shared/HTTP/HTTP.js +1 -3
  22. package/dist/esm/common/utils/helper.js +5 -1
  23. package/dist/esm/music/MusicClient/MusicClient.js +16 -20
  24. package/dist/esm/music/MusicSearchResult/MusicSearchResult.js +5 -4
  25. package/dist/esm/music/MusicSearchResult/MusicSearchResultParser.js +221 -14
  26. package/dist/esm/music/MusicSearchResult/index.js +0 -1
  27. package/dist/esm/youtube/BaseChannel/BaseChannel.js +2 -0
  28. package/dist/esm/youtube/BaseChannel/BaseChannelParser.js +3 -2
  29. package/dist/esm/youtube/BaseChannel/ChannelPlaylists.js +11 -3
  30. package/dist/esm/youtube/BaseChannel/ChannelPosts.js +111 -0
  31. package/dist/esm/youtube/BaseVideo/BaseVideoParser.js +14 -2
  32. package/dist/esm/youtube/Channel/ChannelParser.js +12 -8
  33. package/dist/esm/youtube/PlaylistCompact/PlaylistCompact.js +9 -0
  34. package/dist/esm/youtube/PlaylistCompact/PlaylistCompactParser.js +23 -0
  35. package/dist/esm/youtube/Post/Post.js +36 -0
  36. package/dist/esm/youtube/Post/PostParser.js +23 -0
  37. package/dist/esm/youtube/Post/index.js +2 -0
  38. package/dist/esm/youtube/SearchResult/SearchResultParser.js +10 -0
  39. package/dist/esm/youtube/VideoCompact/VideoCompact.js +9 -0
  40. package/dist/esm/youtube/VideoCompact/VideoCompactParser.js +27 -0
  41. package/dist/typings/music/MusicClient/MusicClient.d.ts +3 -7
  42. package/dist/typings/music/MusicSearchResult/MusicSearchResult.d.ts +7 -4
  43. package/dist/typings/music/MusicSearchResult/MusicSearchResultParser.d.ts +15 -3
  44. package/dist/typings/music/MusicSearchResult/index.d.ts +0 -1
  45. package/dist/typings/youtube/BaseChannel/BaseChannel.d.ts +4 -1
  46. package/dist/typings/youtube/BaseChannel/BaseChannelParser.d.ts +1 -0
  47. package/dist/typings/youtube/BaseChannel/ChannelPosts.d.ts +30 -0
  48. package/dist/typings/youtube/PlaylistCompact/PlaylistCompact.d.ts +6 -0
  49. package/dist/typings/youtube/PlaylistCompact/PlaylistCompactParser.d.ts +1 -0
  50. package/dist/typings/youtube/Post/Post.d.ts +32 -0
  51. package/dist/typings/youtube/Post/PostParser.d.ts +5 -0
  52. package/dist/typings/youtube/Post/index.d.ts +2 -0
  53. package/dist/typings/youtube/VideoCompact/VideoCompact.d.ts +6 -0
  54. package/dist/typings/youtube/VideoCompact/VideoCompactParser.d.ts +1 -0
  55. package/package.json +1 -1
  56. package/dist/cjs/music/MusicSearchResult/MusicAllSearchResultParser.js +0 -218
  57. package/dist/esm/music/MusicSearchResult/MusicAllSearchResultParser.js +0 -234
  58. package/dist/typings/music/MusicSearchResult/MusicAllSearchResultParser.d.ts +0 -19
@@ -0,0 +1,111 @@
1
+ var __extends = (this && this.__extends) || (function () {
2
+ var extendStatics = function (d, b) {
3
+ extendStatics = Object.setPrototypeOf ||
4
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
6
+ return extendStatics(d, b);
7
+ };
8
+ return function (d, b) {
9
+ extendStatics(d, b);
10
+ function __() { this.constructor = d; }
11
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
12
+ };
13
+ })();
14
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16
+ return new (P || (P = Promise))(function (resolve, reject) {
17
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
21
+ });
22
+ };
23
+ var __generator = (this && this.__generator) || function (thisArg, body) {
24
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
25
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
26
+ function verb(n) { return function (v) { return step([n, v]); }; }
27
+ function step(op) {
28
+ if (f) throw new TypeError("Generator is already executing.");
29
+ while (_) try {
30
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
31
+ if (y = 0, t) op = [op[0] & 2, t.value];
32
+ switch (op[0]) {
33
+ case 0: case 1: t = op; break;
34
+ case 4: _.label++; return { value: op[1], done: false };
35
+ case 5: _.label++; y = op[1]; op = [0]; continue;
36
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
37
+ default:
38
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
39
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
40
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
41
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
42
+ if (t[2]) _.ops.pop();
43
+ _.trys.pop(); continue;
44
+ }
45
+ op = body.call(thisArg, _);
46
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
47
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
48
+ }
49
+ };
50
+ import { getContinuationFromItems } from "../../common";
51
+ import { Continuable } from "../Continuable";
52
+ import { Post } from "../Post";
53
+ import { I_END_POINT } from "../constants";
54
+ import { BaseChannelParser } from "./BaseChannelParser";
55
+ /**
56
+ * {@link Continuable} of posts inside a {@link BaseChannel}
57
+ *
58
+ * @example
59
+ * ```js
60
+ * const channel = await youtube.findOne(CHANNEL_NAME, {type: "channel"});
61
+ * await channel.posts.next();
62
+ * console.log(channel.posts.items) // first 30 posts
63
+ *
64
+ * let newPosts = await channel.posts.next();
65
+ * console.log(newPosts) // 30 loaded posts
66
+ * console.log(channel.posts.items) // first 60 posts
67
+ *
68
+ * await channel.posts.next(0); // load the rest of the posts in the channel
69
+ * ```
70
+ */
71
+ var ChannelPosts = /** @class */ (function (_super) {
72
+ __extends(ChannelPosts, _super);
73
+ /** @hidden */
74
+ function ChannelPosts(_a) {
75
+ var client = _a.client, channel = _a.channel;
76
+ var _this = _super.call(this, { client: client, strictContinuationCheck: true }) || this;
77
+ _this.channel = channel;
78
+ return _this;
79
+ }
80
+ ChannelPosts.prototype.fetch = function () {
81
+ var _a;
82
+ return __awaiter(this, void 0, void 0, function () {
83
+ var params, response, items, continuation, data;
84
+ var _this = this;
85
+ return __generator(this, function (_b) {
86
+ switch (_b.label) {
87
+ case 0:
88
+ params = BaseChannelParser.TAB_TYPE_PARAMS.posts;
89
+ return [4 /*yield*/, this.client.http.post(I_END_POINT + "/browse", {
90
+ data: { browseId: (_a = this.channel) === null || _a === void 0 ? void 0 : _a.id, params: params, continuation: this.continuation },
91
+ })];
92
+ case 1:
93
+ response = _b.sent();
94
+ items = BaseChannelParser.parseTabData("posts", response.data);
95
+ continuation = getContinuationFromItems(items);
96
+ data = items
97
+ .map(function (i) { var _a, _b; return (_b = (_a = i.backstagePostThreadRenderer) === null || _a === void 0 ? void 0 : _a.post) === null || _b === void 0 ? void 0 : _b.backstagePostRenderer; })
98
+ .filter(function (i) { return i !== undefined; });
99
+ return [2 /*return*/, {
100
+ continuation: continuation,
101
+ items: data.map(function (i) {
102
+ return new Post({ client: _this.client, channel: _this.channel }).load(i);
103
+ }),
104
+ }];
105
+ }
106
+ });
107
+ });
108
+ };
109
+ return ChannelPosts;
110
+ }(Continuable));
111
+ export { ChannelPosts };
@@ -38,14 +38,16 @@ 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; })) || [];
45
47
  target.description = videoInfo.videoDetails.shortDescription || "";
46
48
  // related videos
47
49
  var secondaryContents = (_c = data.response.contents.twoColumnWatchNextResults.secondaryResults) === null || _c === void 0 ? void 0 : _c.secondaryResults.results;
48
- var itemSectionRenderer = (_d = secondaryContents.find(function (c) {
50
+ var itemSectionRenderer = (_d = secondaryContents === null || secondaryContents === void 0 ? void 0 : secondaryContents.find(function (c) {
49
51
  return c.itemSectionRenderer;
50
52
  })) === null || _d === void 0 ? void 0 : _d.itemSectionRenderer;
51
53
  if (itemSectionRenderer)
@@ -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
@@ -17,9 +17,9 @@ var ChannelParser = /** @class */ (function () {
17
17
  function ChannelParser() {
18
18
  }
19
19
  ChannelParser.loadChannel = function (target, data) {
20
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
20
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
21
21
  var channelId, title, handle, description, avatar, subscriberCountText, videoCountText, tvBanner, mobileBanner, banner;
22
- var _m = data.header, c4TabbedHeaderRenderer = _m.c4TabbedHeaderRenderer, pageHeaderRenderer = _m.pageHeaderRenderer;
22
+ var _k = data.header, c4TabbedHeaderRenderer = _k.c4TabbedHeaderRenderer, pageHeaderRenderer = _k.pageHeaderRenderer;
23
23
  if (c4TabbedHeaderRenderer) {
24
24
  channelId = c4TabbedHeaderRenderer.channelId;
25
25
  title = c4TabbedHeaderRenderer.title;
@@ -35,12 +35,16 @@ var ChannelParser = /** @class */ (function () {
35
35
  data.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.endpoint
36
36
  .browseEndpoint.browseId;
37
37
  title = pageHeaderRenderer.pageTitle;
38
- var _o = pageHeaderRenderer.content.pageHeaderViewModel, metadata = _o.metadata, imageModel = _o.image, bannerModel = _o.banner, descriptionModel = _o.description;
39
- var metadataRow = metadata.contentMetadataViewModel.metadataRows.find(function (m) { return m.metadataParts && m.metadataParts.length == 2; });
40
- var handleRow = metadata.contentMetadataViewModel.metadataRows.find(function (m) { return m.metadataParts && m.metadataParts.length == 1; });
41
- handle = (_j = handleRow === null || handleRow === void 0 ? void 0 : handleRow.metadataParts[0].text) === null || _j === void 0 ? void 0 : _j.content;
42
- videoCountText = (_k = metadataRow.metadataParts.find(function (m) { return m.text.styleRuns; })) === null || _k === void 0 ? void 0 : _k.text.content;
43
- subscriberCountText = (_l = metadataRow.metadataParts.find(function (m) { return !m.text.styleRuns; })) === null || _l === void 0 ? void 0 : _l.text.content;
38
+ var _l = pageHeaderRenderer.content.pageHeaderViewModel, metadata = _l.metadata, imageModel = _l.image, bannerModel = _l.banner, descriptionModel = _l.description;
39
+ var metadataParts = metadata.contentMetadataViewModel.metadataRows
40
+ .map(function (m) { return m.metadataParts; })
41
+ .flat();
42
+ var handlePart = metadataParts.find(function (m) { var _a; return (_a = m.text.styleRuns) === null || _a === void 0 ? void 0 : _a.some(function (s) { return "weightLabel" in s; }); });
43
+ var subscriberCountPart = metadataParts.find(function (m) { return m.accessibilityLabel; });
44
+ var videoCountPart = metadataParts.find(function (m) { var _a; return (_a = m.text.styleRuns) === null || _a === void 0 ? void 0 : _a.some(function (s) { return "startIndex" in s; }); });
45
+ handle = (_j = handlePart === null || handlePart === void 0 ? void 0 : handlePart.text) === null || _j === void 0 ? void 0 : _j.content;
46
+ videoCountText = videoCountPart === null || videoCountPart === void 0 ? void 0 : videoCountPart.text.content;
47
+ subscriberCountText = subscriberCountPart === null || subscriberCountPart === void 0 ? void 0 : subscriberCountPart.text.content;
44
48
  avatar = imageModel.decoratedAvatarViewModel.avatar.avatarViewModel.image.sources;
45
49
  banner = bannerModel === null || bannerModel === void 0 ? void 0 : bannerModel.imageBannerViewModel.image.sources;
46
50
  description = descriptionModel === null || descriptionModel === void 0 ? void 0 : descriptionModel.descriptionPreviewViewModel.description.content;
@@ -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 _a;
27
+ var lockupMetadataViewModel = data.metadata.lockupMetadataViewModel;
28
+ var channelMetadata = (_a = lockupMetadataViewModel.metadata.contentMetadataViewModel.metadataRows) === null || _a === void 0 ? void 0 : _a[0].metadataParts[0];
29
+ var thumbnailViewModel = data.contentImage.collectionThumbnailViewModel.primaryThumbnail.thumbnailViewModel;
30
+ if (channelMetadata === null || channelMetadata === void 0 ? void 0 : 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 };
@@ -0,0 +1,36 @@
1
+ var __extends = (this && this.__extends) || (function () {
2
+ var extendStatics = function (d, b) {
3
+ extendStatics = Object.setPrototypeOf ||
4
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
6
+ return extendStatics(d, b);
7
+ };
8
+ return function (d, b) {
9
+ extendStatics(d, b);
10
+ function __() { this.constructor = d; }
11
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
12
+ };
13
+ })();
14
+ import { Base } from "../Base";
15
+ import { PostParser } from "./PostParser";
16
+ /** Represents a chat in a live stream */
17
+ var Post = /** @class */ (function (_super) {
18
+ __extends(Post, _super);
19
+ /** @hidden */
20
+ function Post(attr) {
21
+ var _this = _super.call(this, attr.client) || this;
22
+ Object.assign(_this, attr);
23
+ return _this;
24
+ }
25
+ /**
26
+ * Load this instance with raw data from Youtube
27
+ *
28
+ * @hidden
29
+ */
30
+ Post.prototype.load = function (data) {
31
+ PostParser.loadPost(this, data);
32
+ return this;
33
+ };
34
+ return Post;
35
+ }(Base));
36
+ export { Post };
@@ -0,0 +1,23 @@
1
+ import { BaseChannel } from "../BaseChannel";
2
+ var PostParser = /** @class */ (function () {
3
+ function PostParser() {
4
+ }
5
+ PostParser.loadPost = function (target, data) {
6
+ var _a, _b, _c, _d;
7
+ var postId = data.postId, authorText = data.authorText, authorThumbnail = data.authorThumbnail, authorEndpoint = data.authorEndpoint, contentText = data.contentText, publishedTimeText = data.publishedTimeText, voteCount = data.voteCount;
8
+ // Basic information
9
+ target.id = postId;
10
+ target.content = (_a = contentText === null || contentText === void 0 ? void 0 : contentText.runs) === null || _a === void 0 ? void 0 : _a.map(function (r) { return r.text; }).join("");
11
+ target.channel = new BaseChannel({
12
+ id: (_b = authorEndpoint === null || authorEndpoint === void 0 ? void 0 : authorEndpoint.browseEndpoint) === null || _b === void 0 ? void 0 : _b.browseId,
13
+ name: (_c = authorText.runs) === null || _c === void 0 ? void 0 : _c[0].text,
14
+ thumbnails: authorThumbnail.thumbnails,
15
+ client: target.client,
16
+ });
17
+ target.timestamp = (_d = publishedTimeText.runs[0]) === null || _d === void 0 ? void 0 : _d.text;
18
+ target.voteCount = voteCount.simpleText;
19
+ return target;
20
+ };
21
+ return PostParser;
22
+ }());
23
+ export { PostParser };
@@ -0,0 +1,2 @@
1
+ export * from "./Post";
2
+ export * from "./PostParser";
@@ -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 }; }
@@ -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
  *
@@ -37,6 +37,33 @@ var VideoCompactParser = /** @class */ (function () {
37
37
  target.viewCount = stripToInt((viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.simpleText) || (viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.runs[0].text));
38
38
  return target;
39
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
+ };
40
67
  return VideoCompactParser;
41
68
  }());
42
69
  export { VideoCompactParser };
@@ -1,4 +1,4 @@
1
- import { HTTP, HTTPOptions, Shelf } from "../../common";
1
+ import { HTTP, HTTPOptions } from "../../common";
2
2
  import { MusicAlbumCompact } from "../MusicAlbumCompact";
3
3
  import { MusicArtistCompact } from "../MusicArtistCompact";
4
4
  import { MusicLyrics } from "../MusicLyrics";
@@ -22,17 +22,13 @@ export declare class MusicClient {
22
22
  * @param type Search type
23
23
  *
24
24
  */
25
- search(query: string): Promise<Shelf<MusicVideoCompact[] | MusicAlbumCompact[] | MusicPlaylistCompact[] | MusicArtistCompact[]>[]>;
26
- search<T extends MusicSearchType>(query: string, type: T): Promise<MusicSearchResult<T>>;
25
+ search<T extends MusicSearchType>(query: string, type?: T): Promise<MusicSearchResult<T>>;
27
26
  /**
28
27
  * Searches for all video, song, album, playlist, or artist
29
28
  *
30
29
  * @param query The search query
31
30
  */
32
- searchAll(query: string): Promise<{
33
- top?: MusicTopShelf;
34
- shelves: Shelf<MusicVideoCompact[] | MusicAlbumCompact[] | MusicPlaylistCompact[] | MusicArtistCompact[]>[];
35
- }>;
31
+ searchAll(query: string): Promise<MusicSearchResult>;
36
32
  /**
37
33
  * Get lyrics of a song
38
34
  *
@@ -1,12 +1,15 @@
1
+ import { MusicAlbumCompact } from "../MusicAlbumCompact";
2
+ import { MusicArtistCompact } from "../MusicArtistCompact";
1
3
  import { FetchResult, MusicContinuable, MusicContinuableConstructorParams } from "../MusicContinuable";
4
+ import { MusicPlaylistCompact } from "../MusicPlaylistCompact";
2
5
  import { MusicSongCompact } from "../MusicSongCompact";
3
6
  import { MusicVideoCompact } from "../MusicVideoCompact";
4
7
  export declare enum MusicSearchTypeEnum {
5
8
  Song = "song",
6
9
  Video = "video"
7
10
  }
8
- export declare type MusicSearchType = "song" | "video" | MusicSearchTypeEnum;
9
- export declare type MusicSearchResultItem<T = "song"> = T extends "song" ? MusicSongCompact : MusicVideoCompact;
11
+ export declare type MusicSearchType = "song" | "video" | MusicSearchTypeEnum | undefined;
12
+ export declare type MusicSearchResultItem<T = undefined> = T extends "song" ? MusicSongCompact : T extends "video" ? MusicVideoCompact : MusicVideoCompact | MusicAlbumCompact | MusicPlaylistCompact | MusicArtistCompact;
10
13
  declare type MusicLyricsProperties = MusicContinuableConstructorParams & {
11
14
  type?: MusicSearchType;
12
15
  };
@@ -32,7 +35,7 @@ declare type MusicLyricsProperties = MusicContinuableConstructorParams & {
32
35
  *
33
36
  * @noInheritDoc
34
37
  */
35
- export declare class MusicSearchResult<T extends MusicSearchType | undefined = "song"> extends MusicContinuable<MusicSearchResultItem<T>> {
38
+ export declare class MusicSearchResult<T extends MusicSearchType = undefined> extends MusicContinuable<MusicSearchResultItem<T>> {
36
39
  private type;
37
40
  /** @hidden */
38
41
  constructor({ client, type }: MusicLyricsProperties);
@@ -44,7 +47,7 @@ export declare class MusicSearchResult<T extends MusicSearchType | undefined = "
44
47
  *
45
48
  * @hidden
46
49
  */
47
- search(query: string, type: MusicSearchType): Promise<MusicSearchResult<T>>;
50
+ search(query: string, type?: MusicSearchType): Promise<MusicSearchResult<T>>;
48
51
  protected fetch(): Promise<FetchResult<MusicSearchResultItem<T>>>;
49
52
  }
50
53
  export {};
@@ -1,13 +1,25 @@
1
1
  import { YoutubeRawData } from "../../common";
2
2
  import { MusicClient } from "../MusicClient";
3
- import { MusicSearchResultItem, MusicSearchType } from "./MusicSearchResult";
3
+ import { MusicSongCompact } from "../MusicSongCompact";
4
+ import { MusicVideoCompact } from "../MusicVideoCompact";
5
+ import { MusicSearchResultItem } from "./MusicSearchResult";
4
6
  declare type ParseReturnType = {
5
7
  data: MusicSearchResultItem[];
6
8
  continuation: string | undefined;
7
9
  };
8
10
  export declare class MusicSearchResultParser {
9
- static parseInitialSearchResult(data: YoutubeRawData, type: MusicSearchType, client: MusicClient): ParseReturnType;
10
- static parseContinuationSearchResult(data: YoutubeRawData, type: MusicSearchType, client: MusicClient): ParseReturnType;
11
+ static parseInitialSearchResult(data: YoutubeRawData, client: MusicClient): ParseReturnType;
12
+ static parseContinuationSearchResult(data: YoutubeRawData, client: MusicClient): ParseReturnType;
13
+ private static parseTopResult;
11
14
  private static parseSearchResult;
15
+ private static parseSearchItem;
16
+ static parseVideoItem(item: YoutubeRawData, pageType: string, client: MusicClient): MusicSongCompact | MusicVideoCompact | undefined;
17
+ private static parsePlaylistItem;
18
+ private static parseAlbumItem;
19
+ private static parseArtistItem;
20
+ private static parseAlbum;
21
+ private static parseArtists;
22
+ private static parseChannel;
23
+ private static parseArtistsOrChannel;
12
24
  }
13
25
  export {};
@@ -1,3 +1,2 @@
1
- export * from "./MusicAllSearchResultParser";
2
1
  export * from "./MusicSearchResult";
3
2
  export * from "./MusicSearchResultParser";
@@ -2,6 +2,7 @@ import { Thumbnails, YoutubeRawData } from "../../common";
2
2
  import { Base, BaseProperties } from "../Base";
3
3
  import { ChannelLive } from "./ChannelLive";
4
4
  import { ChannelPlaylists } from "./ChannelPlaylists";
5
+ import { ChannelPosts } from "./ChannelPosts";
5
6
  import { ChannelShorts } from "./ChannelShorts";
6
7
  import { ChannelVideos } from "./ChannelVideos";
7
8
  /** @hidden */
@@ -17,7 +18,7 @@ export declare class BaseChannel extends Base implements BaseChannelProperties {
17
18
  /** The channel's name */
18
19
  name: string;
19
20
  /** The channel's handle start with @ */
20
- handle: string;
21
+ handle?: string;
21
22
  /** The channel's description */
22
23
  description?: string;
23
24
  /** Thumbnails of this Channel */
@@ -36,6 +37,8 @@ export declare class BaseChannel extends Base implements BaseChannelProperties {
36
37
  live: ChannelLive;
37
38
  /** Continuable of playlists */
38
39
  playlists: ChannelPlaylists;
40
+ /** Continuable of posts */
41
+ posts: ChannelPosts;
39
42
  /** @hidden */
40
43
  constructor(attr: BaseChannelProperties);
41
44
  /** The URL of the channel page */
@@ -7,6 +7,7 @@ export declare class BaseChannelParser {
7
7
  readonly shorts: "EgZzaG9ydHPyBgUKA5oBAA%3D%3D";
8
8
  readonly live: "EgdzdHJlYW1z8gYECgJ6AA%3D%3D";
9
9
  readonly playlists: "EglwbGF5bGlzdHPyBgQKAkIA";
10
+ readonly posts: "EgVwb3N0c_IGBAoCSgA%3D";
10
11
  };
11
12
  static loadBaseChannel(target: BaseChannel, data: YoutubeRawData): BaseChannel;
12
13
  /** Parse tab data from request, tab name is ignored if it's a continuation data */
@@ -0,0 +1,30 @@
1
+ import { Continuable, ContinuableConstructorParams, FetchResult } from "../Continuable";
2
+ import { Post } from "../Post";
3
+ import { BaseChannel } from "./BaseChannel";
4
+ declare type ConstructorParams = ContinuableConstructorParams & {
5
+ channel?: BaseChannel;
6
+ };
7
+ /**
8
+ * {@link Continuable} of posts inside a {@link BaseChannel}
9
+ *
10
+ * @example
11
+ * ```js
12
+ * const channel = await youtube.findOne(CHANNEL_NAME, {type: "channel"});
13
+ * await channel.posts.next();
14
+ * console.log(channel.posts.items) // first 30 posts
15
+ *
16
+ * let newPosts = await channel.posts.next();
17
+ * console.log(newPosts) // 30 loaded posts
18
+ * console.log(channel.posts.items) // first 60 posts
19
+ *
20
+ * await channel.posts.next(0); // load the rest of the posts in the channel
21
+ * ```
22
+ */
23
+ export declare class ChannelPosts extends Continuable<Post> {
24
+ /** The channel this posts belongs to */
25
+ channel?: BaseChannel;
26
+ /** @hidden */
27
+ constructor({ client, channel }: ConstructorParams);
28
+ protected fetch(): Promise<FetchResult<Post>>;
29
+ }
30
+ export {};
@@ -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
  }
@@ -0,0 +1,32 @@
1
+ import { YoutubeRawData } from "../../common";
2
+ import { Base, BaseProperties } from "../Base";
3
+ import { BaseChannel } from "../BaseChannel";
4
+ /** @hidden */
5
+ interface PostProperties extends BaseProperties {
6
+ id?: string;
7
+ channel?: BaseChannel;
8
+ content?: string;
9
+ timestamp?: string;
10
+ voteCount?: string;
11
+ }
12
+ /** Represents a chat in a live stream */
13
+ export declare class Post extends Base implements PostProperties {
14
+ id?: string;
15
+ /** The channel who posted this post */
16
+ channel: BaseChannel;
17
+ /** The content of this post */
18
+ content: string;
19
+ /** Timestamp */
20
+ timestamp: string;
21
+ /** Vote count like '1.2K likes' */
22
+ voteCount: string;
23
+ /** @hidden */
24
+ constructor(attr: PostProperties);
25
+ /**
26
+ * Load this instance with raw data from Youtube
27
+ *
28
+ * @hidden
29
+ */
30
+ load(data: YoutubeRawData): Post;
31
+ }
32
+ export {};
@@ -0,0 +1,5 @@
1
+ import { YoutubeRawData } from "../../common";
2
+ import { Post } from "./Post";
3
+ export declare class PostParser {
4
+ static loadPost(target: Post, data: YoutubeRawData): Post;
5
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./Post";
2
+ export * from "./PostParser";
@@ -46,6 +46,12 @@ export declare class VideoCompact extends Base implements VideoCompactProperties
46
46
  * @hidden
47
47
  */
48
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;
49
55
  /**
50
56
  * Get {@link Video} object based on current video id
51
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.7",
3
+ "version": "1.8.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",