youtubei 1.0.0-rc.2 → 1.0.0-rc.5

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  `Youtubei` is made to replace my other library [scrape-yt](https://github.com/SuspiciousLookingOwl/scrape-yt/). Instead of scrapping data from Youtube page, `youtubei` fetches data by sending a request directly to `https://www.youtube.com/youtubei/v1`, which should be faster and provide more reliable result.
4
4
 
5
- <b>Requires Node >= 12</b>
5
+ <b>Requires Node >= 16</b>
6
6
 
7
7
  #### [Documentation](https://suspiciouslookingowl.github.io/youtubei)
8
8
 
@@ -15,10 +15,18 @@ class BaseChannelParser {
15
15
  }
16
16
  /** Parse tab data from request, tab name is ignored if it's a continuation data */
17
17
  static parseTabData(name, data) {
18
- var _a;
19
- const index = name === "videos" ? 1 : 2;
20
- return (((_a = data.contents) === null || _a === void 0 ? void 0 : _a.twoColumnBrowseResultsRenderer.tabs[index].tabRenderer.content.sectionListRenderer.contents[0].itemSectionRenderer.contents[0].gridRenderer.items) ||
21
- data.onResponseReceivedActions[0].appendContinuationItemsAction.continuationItems);
18
+ var _a, _b, _c;
19
+ const tab = (_a = data.contents) === null || _a === void 0 ? void 0 : _a.twoColumnBrowseResultsRenderer.tabs.find((t) => {
20
+ var _a;
21
+ return (((_a = t.tabRenderer) === null || _a === void 0 ? void 0 : _a.endpoint.browseEndpoint.params) ===
22
+ BaseChannelParser.TAB_TYPE_PARAMS[name]);
23
+ });
24
+ return (((_b = tab === null || tab === void 0 ? void 0 : tab.tabRenderer.content.sectionListRenderer.contents[0].itemSectionRenderer.contents[0].gridRenderer) === null || _b === void 0 ? void 0 : _b.items) || ((_c = data.onResponseReceivedActions) === null || _c === void 0 ? void 0 : _c[0].appendContinuationItemsAction.continuationItems) ||
25
+ []);
22
26
  }
23
27
  }
24
28
  exports.BaseChannelParser = BaseChannelParser;
29
+ BaseChannelParser.TAB_TYPE_PARAMS = {
30
+ videos: "EgZ2aWRlb3M%3D",
31
+ playlists: "EglwbGF5bGlzdHM%3D",
32
+ };
@@ -49,7 +49,7 @@ class ChannelPlaylists extends Continuable_1.Continuable {
49
49
  const data = common_1.mapFilter(items, "gridPlaylistRenderer");
50
50
  return {
51
51
  continuation,
52
- items: data.map((i) => new PlaylistCompact_1.PlaylistCompact({ client: this.client }).load(i)),
52
+ items: data.map((i) => new PlaylistCompact_1.PlaylistCompact({ client: this.client, channel: this.channel }).load(i)),
53
53
  };
54
54
  });
55
55
  }
@@ -49,7 +49,7 @@ class ChannelVideos extends Continuable_1.Continuable {
49
49
  const data = common_1.mapFilter(items, "gridVideoRenderer");
50
50
  return {
51
51
  continuation,
52
- items: data.map((i) => new VideoCompact_1.VideoCompact({ client: this.client }).load(i)),
52
+ items: data.map((i) => new VideoCompact_1.VideoCompact({ client: this.client, channel: this.channel }).load(i)),
53
53
  };
54
54
  });
55
55
  }
@@ -12,7 +12,7 @@ class ChannelParser {
12
12
  target.name = title;
13
13
  target.thumbnails = new Thumbnails_1.Thumbnails().load(avatar.thumbnails);
14
14
  target.videoCount = 0; // data not available
15
- target.subscriberCount = subscriberCountText.simpleText;
15
+ target.subscriberCount = subscriberCountText === null || subscriberCountText === void 0 ? void 0 : subscriberCountText.simpleText;
16
16
  const { tvBanner, mobileBanner, banner } = data.header.c4TabbedHeaderRenderer;
17
17
  target.banner = new Thumbnails_1.Thumbnails().load((banner === null || banner === void 0 ? void 0 : banner.thumbnails) || []);
18
18
  target.tvBanner = new Thumbnails_1.Thumbnails().load((tvBanner === null || tvBanner === void 0 ? void 0 : tvBanner.thumbnails) || []);
@@ -12,6 +12,15 @@ exports.SearchProto = protocol_buffers_1.default(`
12
12
  optional int32 uploadDate = 1;
13
13
  optional int32 type = 2;
14
14
  optional int32 duration = 3;
15
+ optional int32 hd = 4;
16
+ optional int32 subtitles = 5;
17
+ optional int32 creativeCommons = 6;
18
+ optional int32 live = 8;
19
+ optional int32 4k = 14;
20
+ optional int32 360 = 15;
21
+ optional int32 location = 23;
22
+ optional int32 hdr = 25;
23
+ optional int32 vr180 = 26;
15
24
  }
16
25
 
17
26
  optional int32 sortBy = 1;
@@ -45,13 +54,15 @@ const searchSortProto = {
45
54
  view: 3,
46
55
  };
47
56
  const optionsToProto = (options) => {
57
+ var _a;
58
+ const featuresRecord = ((_a = options.features) === null || _a === void 0 ? void 0 : _a.reduce((acc, val) => {
59
+ if (val)
60
+ acc[val] = 1;
61
+ return acc;
62
+ }, {})) || {};
48
63
  return {
49
64
  sortBy: options.sortBy && searchSortProto[options.sortBy],
50
- options: {
51
- duration: options.duration && searchDurationProto[options.duration],
52
- type: options.type && searchTypeProto[options.type],
53
- uploadDate: options.uploadDate && searchUploadDateProto[options.uploadDate],
54
- },
65
+ options: Object.assign({ duration: options.duration && searchDurationProto[options.duration], type: options.type && searchTypeProto[options.type], uploadDate: options.uploadDate && searchUploadDateProto[options.uploadDate] }, featuresRecord),
55
66
  };
56
67
  };
57
68
  exports.optionsToProto = optionsToProto;
@@ -37,7 +37,7 @@ let Thumbnails = Thumbnails_1 = class Thumbnails extends Array {
37
37
  *
38
38
  * @example
39
39
  * ```js
40
- * const min = video.thumbnails.min;
40
+ * const best = video.thumbnails.best;
41
41
  * ```
42
42
  */
43
43
  get best() {
@@ -6,16 +6,16 @@ const BaseChannel_1 = require("../BaseChannel");
6
6
  const Thumbnails_1 = require("../Thumbnails");
7
7
  class VideoCompactParser {
8
8
  static loadVideoCompact(target, data) {
9
- var _a, _b;
9
+ var _a, _b, _c;
10
10
  const { videoId, title, lengthText, thumbnail, ownerText, shortBylineText, publishedTimeText, viewCountText, badges, thumbnailOverlays, channelThumbnailSupportedRenderers, detailedMetadataSnippets, } = data;
11
11
  target.id = videoId;
12
12
  target.title = title.simpleText || ((_a = title.runs[0]) === null || _a === void 0 ? void 0 : _a.text);
13
13
  target.thumbnails = new Thumbnails_1.Thumbnails().load(thumbnail.thumbnails);
14
14
  target.uploadDate = publishedTimeText === null || publishedTimeText === void 0 ? void 0 : publishedTimeText.simpleText;
15
15
  target.description =
16
- (detailedMetadataSnippets === null || detailedMetadataSnippets === void 0 ? void 0 : detailedMetadataSnippets[0].snippetText.runs.map((r) => r.text).join("")) || "";
16
+ ((_b = detailedMetadataSnippets === null || detailedMetadataSnippets === void 0 ? void 0 : detailedMetadataSnippets[0].snippetText.runs) === null || _b === void 0 ? void 0 : _b.map((r) => r.text).join("")) || "";
17
17
  target.duration =
18
- common_1.getDuration((lengthText === null || lengthText === void 0 ? void 0 : lengthText.simpleText) || ((_b = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _b === void 0 ? void 0 : _b.text.simpleText) ||
18
+ common_1.getDuration((lengthText === null || lengthText === void 0 ? void 0 : lengthText.simpleText) || ((_c = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _c === void 0 ? void 0 : _c.text.simpleText) ||
19
19
  "") || null;
20
20
  target.isLive = !!((badges === null || badges === void 0 ? void 0 : badges[0].metadataBadgeRenderer.style) === "BADGE_STYLE_TYPE_LIVE_NOW");
21
21
  // Channel
@@ -14,10 +14,18 @@ var BaseChannelParser = /** @class */ (function () {
14
14
  };
15
15
  /** Parse tab data from request, tab name is ignored if it's a continuation data */
16
16
  BaseChannelParser.parseTabData = function (name, data) {
17
- var _a;
18
- var index = name === "videos" ? 1 : 2;
19
- return (((_a = data.contents) === null || _a === void 0 ? void 0 : _a.twoColumnBrowseResultsRenderer.tabs[index].tabRenderer.content.sectionListRenderer.contents[0].itemSectionRenderer.contents[0].gridRenderer.items) ||
20
- data.onResponseReceivedActions[0].appendContinuationItemsAction.continuationItems);
17
+ var _a, _b, _c;
18
+ var tab = (_a = data.contents) === null || _a === void 0 ? void 0 : _a.twoColumnBrowseResultsRenderer.tabs.find(function (t) {
19
+ var _a;
20
+ return (((_a = t.tabRenderer) === null || _a === void 0 ? void 0 : _a.endpoint.browseEndpoint.params) ===
21
+ BaseChannelParser.TAB_TYPE_PARAMS[name]);
22
+ });
23
+ return (((_b = tab === null || tab === void 0 ? void 0 : tab.tabRenderer.content.sectionListRenderer.contents[0].itemSectionRenderer.contents[0].gridRenderer) === null || _b === void 0 ? void 0 : _b.items) || ((_c = data.onResponseReceivedActions) === null || _c === void 0 ? void 0 : _c[0].appendContinuationItemsAction.continuationItems) ||
24
+ []);
25
+ };
26
+ BaseChannelParser.TAB_TYPE_PARAMS = {
27
+ videos: "EgZ2aWRlb3M%3D",
28
+ playlists: "EglwbGF5bGlzdHM%3D",
21
29
  };
22
30
  return BaseChannelParser;
23
31
  }());
@@ -97,7 +97,7 @@ var ChannelPlaylists = /** @class */ (function (_super) {
97
97
  return [2 /*return*/, {
98
98
  continuation: continuation,
99
99
  items: data.map(function (i) {
100
- return new PlaylistCompact({ client: _this.client }).load(i);
100
+ return new PlaylistCompact({ client: _this.client, channel: _this.channel }).load(i);
101
101
  }),
102
102
  }];
103
103
  }
@@ -97,7 +97,7 @@ var ChannelVideos = /** @class */ (function (_super) {
97
97
  return [2 /*return*/, {
98
98
  continuation: continuation,
99
99
  items: data.map(function (i) {
100
- return new VideoCompact({ client: _this.client }).load(i);
100
+ return new VideoCompact({ client: _this.client, channel: _this.channel }).load(i);
101
101
  }),
102
102
  }];
103
103
  }
@@ -22,7 +22,7 @@ var ChannelParser = /** @class */ (function () {
22
22
  target.name = title;
23
23
  target.thumbnails = new Thumbnails().load(avatar.thumbnails);
24
24
  target.videoCount = 0; // data not available
25
- target.subscriberCount = subscriberCountText.simpleText;
25
+ target.subscriberCount = subscriberCountText === null || subscriberCountText === void 0 ? void 0 : subscriberCountText.simpleText;
26
26
  var _b = data.header.c4TabbedHeaderRenderer, tvBanner = _b.tvBanner, mobileBanner = _b.mobileBanner, banner = _b.banner;
27
27
  target.banner = new Thumbnails().load((banner === null || banner === void 0 ? void 0 : banner.thumbnails) || []);
28
28
  target.tvBanner = new Thumbnails().load((tvBanner === null || tvBanner === void 0 ? void 0 : tvBanner.thumbnails) || []);
@@ -1,6 +1,17 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
1
12
  import proto from "protocol-buffers";
2
13
  // TODO move this to .proto file
3
- export var SearchProto = proto("\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}\n\n\t\toptional int32 sortBy = 1;\n\t\toptional Options options = 2;\n\t}\n");
14
+ export var SearchProto = proto("\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");
4
15
  var searchUploadDateProto = {
5
16
  all: 0,
6
17
  hour: 1,
@@ -28,12 +39,14 @@ var searchSortProto = {
28
39
  view: 3,
29
40
  };
30
41
  export var optionsToProto = function (options) {
42
+ var _a;
43
+ var featuresRecord = ((_a = options.features) === null || _a === void 0 ? void 0 : _a.reduce(function (acc, val) {
44
+ if (val)
45
+ acc[val] = 1;
46
+ return acc;
47
+ }, {})) || {};
31
48
  return {
32
49
  sortBy: options.sortBy && searchSortProto[options.sortBy],
33
- options: {
34
- duration: options.duration && searchDurationProto[options.duration],
35
- type: options.type && searchTypeProto[options.type],
36
- uploadDate: options.uploadDate && searchUploadDateProto[options.uploadDate],
37
- },
50
+ options: __assign({ duration: options.duration && searchDurationProto[options.duration], type: options.type && searchTypeProto[options.type], uploadDate: options.uploadDate && searchUploadDateProto[options.uploadDate] }, featuresRecord),
38
51
  };
39
52
  };
@@ -73,7 +73,7 @@ var Thumbnails = /** @class */ (function (_super) {
73
73
  *
74
74
  * @example
75
75
  * ```js
76
- * const min = video.thumbnails.min;
76
+ * const best = video.thumbnails.best;
77
77
  * ```
78
78
  */
79
79
  get: function () {
@@ -5,16 +5,16 @@ var VideoCompactParser = /** @class */ (function () {
5
5
  function VideoCompactParser() {
6
6
  }
7
7
  VideoCompactParser.loadVideoCompact = function (target, data) {
8
- var _a, _b;
8
+ var _a, _b, _c;
9
9
  var videoId = data.videoId, title = data.title, 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;
10
10
  target.id = videoId;
11
11
  target.title = title.simpleText || ((_a = title.runs[0]) === null || _a === void 0 ? void 0 : _a.text);
12
12
  target.thumbnails = new Thumbnails().load(thumbnail.thumbnails);
13
13
  target.uploadDate = publishedTimeText === null || publishedTimeText === void 0 ? void 0 : publishedTimeText.simpleText;
14
14
  target.description =
15
- (detailedMetadataSnippets === null || detailedMetadataSnippets === void 0 ? void 0 : detailedMetadataSnippets[0].snippetText.runs.map(function (r) { return r.text; }).join("")) || "";
15
+ ((_b = detailedMetadataSnippets === null || detailedMetadataSnippets === void 0 ? void 0 : detailedMetadataSnippets[0].snippetText.runs) === null || _b === void 0 ? void 0 : _b.map(function (r) { return r.text; }).join("")) || "";
16
16
  target.duration =
17
- getDuration((lengthText === null || lengthText === void 0 ? void 0 : lengthText.simpleText) || ((_b = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _b === void 0 ? void 0 : _b.text.simpleText) ||
17
+ getDuration((lengthText === null || lengthText === void 0 ? void 0 : lengthText.simpleText) || ((_c = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _c === void 0 ? void 0 : _c.text.simpleText) ||
18
18
  "") || null;
19
19
  target.isLive = !!((badges === null || badges === void 0 ? void 0 : badges[0].metadataBadgeRenderer.style) === "BADGE_STYLE_TYPE_LIVE_NOW");
20
20
  // Channel
@@ -1,6 +1,10 @@
1
1
  import { YoutubeRawData } from "../../common";
2
2
  import { BaseChannel } from "./BaseChannel";
3
3
  export declare class BaseChannelParser {
4
+ static TAB_TYPE_PARAMS: {
5
+ readonly videos: "EgZ2aWRlb3M%3D";
6
+ readonly playlists: "EglwbGF5bGlzdHM%3D";
7
+ };
4
8
  static loadBaseChannel(target: BaseChannel, data: YoutubeRawData): BaseChannel;
5
9
  /** Parse tab data from request, tab name is ignored if it's a continuation data */
6
10
  static parseTabData(name: "videos" | "playlists", data: YoutubeRawData): YoutubeRawData;
@@ -7,11 +7,13 @@ export declare type SearchOptions = {
7
7
  duration?: SearchDuration;
8
8
  uploadDate?: SearchUploadDate;
9
9
  sortBy?: SearchSort;
10
+ features?: SearchFeature[];
10
11
  };
11
12
  export declare type SearchUploadDate = "all" | "hour" | "today" | "week" | "month" | "year";
12
13
  export declare type SearchType = "all" | "video" | "channel" | "playlist";
13
14
  export declare type SearchDuration = "all" | "short" | "medium" | "long";
14
15
  export declare type SearchSort = "relevance" | "rating" | "date" | "view";
16
+ export declare type SearchFeature = "live" | "4k" | "hd" | "subtitles" | "creativeCommons" | "360" | "vr180" | "3d" | "hdr" | "location";
15
17
  export declare type SearchResultItem<T = "all"> = T extends "video" | VideoCompact ? VideoCompact : T extends "channel" | BaseChannel ? BaseChannel : T extends "playlist" | PlaylistCompact ? PlaylistCompact : VideoCompact | BaseChannel | PlaylistCompact;
16
18
  /**
17
19
  * Represents search result, usually returned from `client.search();`.
@@ -2,6 +2,16 @@ declare type Options = {
2
2
  uploadDate?: number;
3
3
  type?: number;
4
4
  duration?: number;
5
+ live?: number;
6
+ "4k"?: number;
7
+ hd?: number;
8
+ subtitles?: number;
9
+ creativeCommons?: number;
10
+ "360"?: number;
11
+ vr180?: number;
12
+ "3d"?: number;
13
+ hdr?: number;
14
+ location?: number;
5
15
  };
6
16
  declare type SearchOptions = {
7
17
  sortBy?: number;
@@ -9,6 +9,16 @@ export declare const SearchProto: {
9
9
  uploadDate?: number | undefined;
10
10
  type?: number | undefined;
11
11
  duration?: number | undefined;
12
+ live?: number | undefined;
13
+ "4k"?: number | undefined;
14
+ hd?: number | undefined;
15
+ subtitles?: number | undefined;
16
+ creativeCommons?: number | undefined;
17
+ "360"?: number | undefined;
18
+ vr180?: number | undefined;
19
+ "3d"?: number | undefined;
20
+ hdr?: number | undefined;
21
+ location?: number | undefined;
12
22
  } | undefined;
13
23
  }) => Buffer;
14
24
  decode: (buf: Buffer) => {
@@ -17,6 +27,16 @@ export declare const SearchProto: {
17
27
  uploadDate?: number | undefined;
18
28
  type?: number | undefined;
19
29
  duration?: number | undefined;
30
+ live?: number | undefined;
31
+ "4k"?: number | undefined;
32
+ hd?: number | undefined;
33
+ subtitles?: number | undefined;
34
+ creativeCommons?: number | undefined;
35
+ "360"?: number | undefined;
36
+ vr180?: number | undefined;
37
+ "3d"?: number | undefined;
38
+ hdr?: number | undefined;
39
+ location?: number | undefined;
20
40
  } | undefined;
21
41
  };
22
42
  };
@@ -27,7 +27,7 @@ export declare class Thumbnails extends Array<Thumbnail> {
27
27
  *
28
28
  * @example
29
29
  * ```js
30
- * const min = video.thumbnails.min;
30
+ * const best = video.thumbnails.best;
31
31
  * ```
32
32
  */
33
33
  get best(): string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "youtubei",
3
- "version": "1.0.0-rc.2",
3
+ "version": "1.0.0-rc.5",
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",