youtubei 0.0.1-rc.3 → 0.0.1-rc.32

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 (62) hide show
  1. package/README.md +6 -5
  2. package/dist/classes/Base.d.ts +10 -0
  3. package/dist/classes/{client/types.js → Base.js} +3 -0
  4. package/dist/classes/BaseVideo.d.ts +59 -0
  5. package/dist/classes/BaseVideo.js +121 -0
  6. package/dist/classes/Channel.d.ts +27 -31
  7. package/dist/classes/Channel.js +59 -135
  8. package/dist/classes/ChannelCompact.d.ts +74 -23
  9. package/dist/classes/ChannelCompact.js +114 -103
  10. package/dist/classes/Chat.d.ts +29 -0
  11. package/dist/classes/Chat.js +31 -0
  12. package/dist/classes/Client.d.ts +49 -0
  13. package/dist/classes/Client.js +97 -0
  14. package/dist/classes/Comment.d.ts +50 -0
  15. package/dist/classes/Comment.js +84 -0
  16. package/dist/classes/LiveVideo.d.ts +47 -0
  17. package/dist/classes/LiveVideo.js +94 -0
  18. package/dist/classes/MixPlaylist.d.ts +32 -0
  19. package/dist/classes/MixPlaylist.js +44 -0
  20. package/dist/classes/Playlist.d.ts +35 -18
  21. package/dist/classes/Playlist.js +80 -116
  22. package/dist/classes/PlaylistCompact.d.ts +27 -15
  23. package/dist/classes/PlaylistCompact.js +42 -46
  24. package/dist/classes/Reply.d.ts +38 -0
  25. package/dist/classes/Reply.js +35 -0
  26. package/dist/classes/SearchResult.d.ts +52 -8
  27. package/dist/classes/SearchResult.js +101 -122
  28. package/dist/classes/Thumbnails.d.ts +42 -0
  29. package/dist/classes/Thumbnails.js +66 -0
  30. package/dist/classes/Video.d.ts +44 -37
  31. package/dist/classes/Video.js +74 -83
  32. package/dist/classes/VideoCompact.d.ts +38 -19
  33. package/dist/classes/VideoCompact.js +53 -53
  34. package/dist/classes/index.d.ts +10 -2
  35. package/dist/classes/index.js +20 -4
  36. package/dist/common/HTTP.d.ts +26 -0
  37. package/dist/common/HTTP.js +85 -0
  38. package/dist/common/decorators.js +6 -26
  39. package/dist/common/helper.d.ts +4 -0
  40. package/dist/common/helper.js +37 -18
  41. package/dist/common/index.d.ts +2 -1
  42. package/dist/common/index.js +5 -3
  43. package/dist/common/mixins.d.ts +2 -0
  44. package/dist/common/mixins.js +12 -0
  45. package/dist/common/types.d.ts +0 -5
  46. package/dist/constants.d.ts +5 -2
  47. package/dist/constants.js +6 -3
  48. package/package.json +23 -20
  49. package/.prettierrc +0 -8
  50. package/.vscode/settings.json +0 -4
  51. package/CHANGELOG.md +0 -6
  52. package/debug.log +0 -47
  53. package/dist/classes/BaseCompact.d.ts +0 -10
  54. package/dist/classes/BaseCompact.js +0 -27
  55. package/dist/classes/client/Client.d.ts +0 -23
  56. package/dist/classes/client/Client.js +0 -128
  57. package/dist/classes/client/index.d.ts +0 -2
  58. package/dist/classes/client/index.js +0 -19
  59. package/dist/classes/client/types.d.ts +0 -12
  60. package/dist/common/axios.d.ts +0 -4
  61. package/dist/common/axios.js +0 -44
  62. package/jest.config.js +0 -5
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const events_1 = require("events");
13
+ const common_1 = require("../common");
14
+ const _1 = require(".");
15
+ const constants_1 = require("../constants");
16
+ /** Represents a video that's currently live, usually returned from `client.getVideo()` */
17
+ class LiveVideo extends _1.BaseVideo {
18
+ /** @hidden */
19
+ constructor(video = {}) {
20
+ super();
21
+ this._delay = 0;
22
+ this._timeoutMs = 0;
23
+ this._isChatPlaying = false;
24
+ this._chatQueue = [];
25
+ Object.assign(this, video);
26
+ }
27
+ /**
28
+ * Load this instance with raw data from Youtube
29
+ *
30
+ * @hidden
31
+ */
32
+ load(data) {
33
+ var _a;
34
+ super.load(data);
35
+ const videoInfo = _1.BaseVideo.parseRawData(data);
36
+ this.watchingCount = +videoInfo.viewCount.videoViewCountRenderer.viewCount.runs
37
+ .map((r) => r.text)
38
+ .join(" ")
39
+ .replace(/[^0-9]/g, "");
40
+ this.chatContinuation = (_a = data[3].response.contents.twoColumnWatchNextResults.conversationBar.liveChatRenderer) === null || _a === void 0 ? void 0 : _a.continuations[0].reloadContinuationData.continuation;
41
+ return this;
42
+ }
43
+ /**
44
+ * Start polling for get live chat request
45
+ *
46
+ * @param delay chat delay in millisecond
47
+ */
48
+ playChat(delay = 0) {
49
+ if (this._isChatPlaying)
50
+ return;
51
+ this._delay = delay;
52
+ this._isChatPlaying = true;
53
+ this.pollChatContinuation();
54
+ }
55
+ /** Stop request polling for live chat */
56
+ stopChat() {
57
+ if (!this._chatRequestPoolingTimeout)
58
+ return;
59
+ this._isChatPlaying = false;
60
+ clearTimeout(this._chatRequestPoolingTimeout);
61
+ }
62
+ /** Start request polling */
63
+ pollChatContinuation() {
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ const response = yield this.client.http.post(constants_1.LIVE_CHAT_END_POINT, {
66
+ data: { continuation: this.chatContinuation },
67
+ });
68
+ if (!response.data.continuationContents)
69
+ return;
70
+ this.parseChat(response.data);
71
+ const continuation = response.data.continuationContents.liveChatContinuation.continuations[0];
72
+ const continuationData = continuation.timedContinuationData || continuation.invalidationContinuationData;
73
+ this._timeoutMs = continuationData.timeoutMs;
74
+ this.chatContinuation = continuationData.continuation;
75
+ this._chatRequestPoolingTimeout = setTimeout(() => this.pollChatContinuation(), this._timeoutMs);
76
+ });
77
+ }
78
+ /** Parse chat data from Youtube and add to chatQueue */
79
+ parseChat(data) {
80
+ var _a;
81
+ const chats = ((_a = data.continuationContents.liveChatContinuation.actions) === null || _a === void 0 ? void 0 : _a.flatMap((a) => { var _a; return ((_a = a.addChatItemAction) === null || _a === void 0 ? void 0 : _a.item.liveChatTextMessageRenderer) || []; })) || [];
82
+ for (const rawChatData of chats) {
83
+ const chat = new _1.Chat({ client: this.client }).load(rawChatData);
84
+ if (this._chatQueue.find((c) => c.id === chat.id))
85
+ continue;
86
+ this._chatQueue.push(chat);
87
+ setTimeout(() => {
88
+ this.emit("chat", chat);
89
+ }, chat.timestamp / 1000 - (new Date().getTime() - this._delay));
90
+ }
91
+ }
92
+ }
93
+ common_1.applyMixins(LiveVideo, [events_1.EventEmitter]);
94
+ exports.default = LiveVideo;
@@ -0,0 +1,32 @@
1
+ import { Base, BaseAttributes, VideoCompact } from ".";
2
+ import { YoutubeRawData } from "../common";
3
+ /** @hidden */
4
+ interface PlaylistAttributes extends BaseAttributes {
5
+ title: string;
6
+ videoCount: number;
7
+ videos: VideoCompact[];
8
+ }
9
+ /** Represents a MixPlaylist, usually returned from `client.getPlaylist()` */
10
+ export default class MixPlaylist extends Base implements PlaylistAttributes {
11
+ /** The title of this playlist */
12
+ title: string;
13
+ /** How many videos in this playlist */
14
+ videoCount: number;
15
+ /** How many viewers does this playlist have */
16
+ videos: VideoCompact[];
17
+ /** @hidden */
18
+ constructor(playlist?: Partial<MixPlaylist>);
19
+ /**
20
+ * Load this instance with raw data from Youtube
21
+ *
22
+ * @hidden
23
+ */
24
+ load(data: YoutubeRawData): MixPlaylist;
25
+ /**
26
+ * Get compact videos
27
+ *
28
+ * @param MixplaylistContents raw object from youtubei
29
+ */
30
+ private static parseVideos;
31
+ }
32
+ export {};
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const _1 = require(".");
4
+ /** Represents a MixPlaylist, usually returned from `client.getPlaylist()` */
5
+ class MixPlaylist extends _1.Base {
6
+ /** @hidden */
7
+ constructor(playlist = {}) {
8
+ super();
9
+ /** How many viewers does this playlist have */
10
+ this.videos = [];
11
+ Object.assign(this, playlist);
12
+ }
13
+ /**
14
+ * Load this instance with raw data from Youtube
15
+ *
16
+ * @hidden
17
+ */
18
+ load(data) {
19
+ const twoColumnWatchNextResults = data.contents.twoColumnWatchNextResults;
20
+ const playlist = twoColumnWatchNextResults.playlist.playlist;
21
+ this.title = playlist.titleText.simpleText;
22
+ this.id = playlist.playlistId;
23
+ this.videoCount = playlist.contents.length;
24
+ this.videos = MixPlaylist.parseVideos(playlist.contents, this);
25
+ return this;
26
+ }
27
+ /**
28
+ * Get compact videos
29
+ *
30
+ * @param MixplaylistContents raw object from youtubei
31
+ */
32
+ static parseVideos(MixplaylistContents, playlist) {
33
+ const videosRenderer = MixplaylistContents.map((c) => c.playlistPanelVideoRenderer);
34
+ const videos = [];
35
+ for (const videoRenderer of videosRenderer) {
36
+ if (!videoRenderer)
37
+ continue;
38
+ const video = new _1.VideoCompact({ client: playlist.client }).load(videoRenderer);
39
+ videos.push(video);
40
+ }
41
+ return videos;
42
+ }
43
+ }
44
+ exports.default = MixPlaylist;
@@ -1,36 +1,53 @@
1
+ import { BaseAttributes, VideoCompact, ChannelCompact, Base } from ".";
1
2
  import { YoutubeRawData } from "../common";
2
- import Channel from "./Channel";
3
- import VideoCompact from "./VideoCompact";
4
- interface PlaylistAttributes {
5
- id: string;
3
+ /** @hidden */
4
+ interface PlaylistAttributes extends BaseAttributes {
6
5
  title: string;
7
6
  videoCount: number;
8
7
  viewCount: number;
9
8
  lastUpdatedAt: string;
10
- channel?: Channel;
9
+ channel?: ChannelCompact;
11
10
  videos: VideoCompact[];
11
+ continuation?: string;
12
12
  }
13
- /**
14
- * Represent a Playlist
15
- */
16
- export default class Playlist implements PlaylistAttributes {
17
- id: string;
13
+ /** Represents a Playlist, usually returned from `client.getPlaylist()` */
14
+ export default class Playlist extends Base implements PlaylistAttributes {
15
+ /** The title of this playlist */
18
16
  title: string;
17
+ /** How many videos in this playlist */
19
18
  videoCount: number;
19
+ /** How many viewers does this playlist have */
20
20
  viewCount: number;
21
+ /** Last time this playlist is updated */
21
22
  lastUpdatedAt: string;
22
- channel?: Channel;
23
+ /** The channel that made this playlist */
24
+ channel?: ChannelCompact;
25
+ /** Videos in the playlist */
23
26
  videos: VideoCompact[];
24
- private latestContinuationToken;
27
+ /** Current continuation token to load next videos */
28
+ continuation: string | undefined;
29
+ /** @hidden */
25
30
  constructor(playlist?: Partial<Playlist>);
26
31
  /**
27
- * Load instance attributes from youtube raw data
32
+ * Load this instance with raw data from Youtube
28
33
  *
29
- * @param youtubeRawData raw object from youtubei
34
+ * @hidden
30
35
  */
31
- load(youtubeRawData: YoutubeRawData): Playlist;
36
+ load(data: YoutubeRawData): Playlist;
32
37
  /**
33
- * Load next videos of the playlist
38
+ * Load next 100 videos of the playlist, and push the loaded videos to {@link Playlist.videos}
39
+ *
40
+ * @example
41
+ * ```js
42
+ * const playlist = await youtube.getPlaylist(PLAYLIST_ID);
43
+ * console.log(playlist.videos) // first 100 videos
44
+ *
45
+ * let newVideos = await playlist.next();
46
+ * console.log(newVideos) // 100 loaded videos
47
+ * console.log(playlist.videos) // first 200 videos
48
+ *
49
+ * await playlist.next(0); // load the rest of the videos in the playlist
50
+ * ```
34
51
  *
35
52
  * @param count How many times to load the next videos. Set 0 to load all videos (might take a while on a large playlist!)
36
53
  */
@@ -40,7 +57,7 @@ export default class Playlist implements PlaylistAttributes {
40
57
  *
41
58
  * @param playlistContents raw object from youtubei
42
59
  */
43
- private getVideos;
44
- private getSideBarInfo;
60
+ private static parseVideos;
61
+ private static parseSideBarInfo;
45
62
  }
46
63
  export {};
@@ -8,160 +8,124 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (_) try {
18
- 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;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
- var __importDefault = (this && this.__importDefault) || function (mod) {
39
- return (mod && mod.__esModule) ? mod : { "default": mod };
40
- };
41
11
  Object.defineProperty(exports, "__esModule", { value: true });
42
- var common_1 = require("../common");
43
- var constants_1 = require("../constants");
44
- var Channel_1 = __importDefault(require("./Channel"));
45
- var VideoCompact_1 = __importDefault(require("./VideoCompact"));
46
- /**
47
- * Represent a Playlist
48
- */
49
- var Playlist = /** @class */ (function () {
50
- function Playlist(playlist) {
51
- if (playlist === void 0) { playlist = {}; }
12
+ const _1 = require(".");
13
+ const common_1 = require("../common");
14
+ const constants_1 = require("../constants");
15
+ /** Represents a Playlist, usually returned from `client.getPlaylist()` */
16
+ class Playlist extends _1.Base {
17
+ /** @hidden */
18
+ constructor(playlist = {}) {
19
+ super();
20
+ /** Videos in the playlist */
21
+ this.videos = [];
52
22
  Object.assign(this, playlist);
53
23
  }
54
24
  /**
55
- * Load instance attributes from youtube raw data
25
+ * Load this instance with raw data from Youtube
56
26
  *
57
- * @param youtubeRawData raw object from youtubei
27
+ * @hidden
58
28
  */
59
- Playlist.prototype.load = function (youtubeRawData) {
60
- var _a, _b;
61
- var sidebarRenderer = youtubeRawData.sidebar.playlistSidebarRenderer.items;
62
- var primaryRenderer = sidebarRenderer[0].playlistSidebarPrimaryInfoRenderer;
29
+ load(data) {
30
+ var _a, _b, _c;
31
+ const sidebarRenderer = data.sidebar.playlistSidebarRenderer.items;
32
+ const primaryRenderer = sidebarRenderer[0].playlistSidebarPrimaryInfoRenderer;
33
+ const metadata = data.metadata.playlistMetadataRenderer;
63
34
  // Basic information
64
- this.id = primaryRenderer.title.runs[0].navigationEndpoint.watchEndpoint.playlistId;
65
- this.title = primaryRenderer.title.runs[0].text;
66
- var stats = primaryRenderer.stats;
35
+ this.id = (_a = Object.values(metadata)
36
+ .find((v) => v.includes("playlist?list="))) === null || _a === void 0 ? void 0 : _a.split("=")[1];
37
+ this.title = metadata.title;
38
+ const { stats } = primaryRenderer;
67
39
  if (primaryRenderer.stats.length === 3) {
68
- this.videoCount = this.getSideBarInfo(stats[0], true);
69
- this.viewCount = this.getSideBarInfo(stats[1], true);
70
- this.lastUpdatedAt = this.getSideBarInfo(stats[2], false);
40
+ this.videoCount = Playlist.parseSideBarInfo(stats[0], true);
41
+ this.viewCount = Playlist.parseSideBarInfo(stats[1], true);
42
+ this.lastUpdatedAt = Playlist.parseSideBarInfo(stats[2], false);
71
43
  }
72
44
  else if (stats.length === 2) {
73
- this.videoCount = this.getSideBarInfo(stats[0], true);
74
- this.lastUpdatedAt = this.getSideBarInfo(stats[1], false);
45
+ this.videoCount = Playlist.parseSideBarInfo(stats[0], true);
46
+ this.lastUpdatedAt = Playlist.parseSideBarInfo(stats[1], false);
75
47
  }
76
- // Videos
77
- var playlistContents = youtubeRawData.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content
48
+ const playlistContents = ((_b = data.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content
78
49
  .sectionListRenderer.contents[0].itemSectionRenderer.contents[0]
79
- .playlistVideoListRenderer.contents;
80
- var videos = this.getVideos(playlistContents);
50
+ .playlistVideoListRenderer) === null || _b === void 0 ? void 0 : _b.contents) || [];
81
51
  // Video Continuation Token
82
- this.latestContinuationToken = (_a = playlistContents[100]) === null || _a === void 0 ? void 0 : _a.continuationItemRenderer.continuationEndpoint.continuationCommand.token;
83
- this.videos = videos;
52
+ this.continuation = common_1.getContinuationFromItems(playlistContents);
84
53
  // Channel
85
- var videoOwner = ((_b = sidebarRenderer[1]) === null || _b === void 0 ? void 0 : _b.playlistSidebarSecondaryInfoRenderer.videoOwner) || undefined;
54
+ const videoOwner = (_c = sidebarRenderer[1]) === null || _c === void 0 ? void 0 : _c.playlistSidebarSecondaryInfoRenderer.videoOwner;
86
55
  if (videoOwner) {
87
- var _c = videoOwner.videoOwnerRenderer, title = _c.title, thumbnail = _c.thumbnail;
88
- this.channel = new Channel_1.default({
56
+ const { title, thumbnail } = videoOwner.videoOwnerRenderer;
57
+ this.channel = new _1.ChannelCompact({
89
58
  id: title.runs[0].navigationEndpoint.browseEndpoint.browseId,
90
59
  name: title.runs[0].text,
91
- thumbnails: thumbnail.thumbnails,
92
- url: "https://www.youtube.com" +
93
- title.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url,
60
+ thumbnails: new _1.Thumbnails().load(thumbnail.thumbnails),
61
+ client: this.client,
94
62
  });
95
63
  }
64
+ // Videos
65
+ this.videos = Playlist.parseVideos(playlistContents, this);
96
66
  return this;
97
- };
67
+ }
98
68
  /**
99
- * Load next videos of the playlist
69
+ * Load next 100 videos of the playlist, and push the loaded videos to {@link Playlist.videos}
70
+ *
71
+ * @example
72
+ * ```js
73
+ * const playlist = await youtube.getPlaylist(PLAYLIST_ID);
74
+ * console.log(playlist.videos) // first 100 videos
75
+ *
76
+ * let newVideos = await playlist.next();
77
+ * console.log(newVideos) // 100 loaded videos
78
+ * console.log(playlist.videos) // first 200 videos
79
+ *
80
+ * await playlist.next(0); // load the rest of the videos in the playlist
81
+ * ```
100
82
  *
101
83
  * @param count How many times to load the next videos. Set 0 to load all videos (might take a while on a large playlist!)
102
84
  */
103
- Playlist.prototype.next = function (count) {
104
- var _a;
105
- if (count === void 0) { count = 1; }
106
- return __awaiter(this, void 0, void 0, function () {
107
- var newVideos, i, response, playlistContents;
108
- var _b;
109
- return __generator(this, function (_c) {
110
- switch (_c.label) {
111
- case 0:
112
- newVideos = [];
113
- i = 0;
114
- _c.label = 1;
115
- case 1:
116
- if (!(i < count || count == 0)) return [3 /*break*/, 4];
117
- if (!this.latestContinuationToken)
118
- return [3 /*break*/, 4];
119
- return [4 /*yield*/, common_1.axios.post(constants_1.I_END_POINT + "/browse", {
120
- continuation: this.latestContinuationToken,
121
- })];
122
- case 2:
123
- response = _c.sent();
124
- playlistContents = response.data.onResponseReceivedActions[0].appendContinuationItemsAction
125
- .continuationItems;
126
- newVideos.push.apply(newVideos, this.getVideos(playlistContents));
127
- this.latestContinuationToken = (_a = playlistContents[100]) === null || _a === void 0 ? void 0 : _a.continuationItemRenderer.continuationEndpoint.continuationCommand.token;
128
- _c.label = 3;
129
- case 3:
130
- i++;
131
- return [3 /*break*/, 1];
132
- case 4:
133
- (_b = this.videos).push.apply(_b, newVideos);
134
- return [2 /*return*/, newVideos];
135
- }
136
- });
85
+ next(count = 1) {
86
+ return __awaiter(this, void 0, void 0, function* () {
87
+ const newVideos = [];
88
+ for (let i = 0; i < count || count == 0; i++) {
89
+ if (!this.continuation)
90
+ break;
91
+ const response = yield this.client.http.post(`${constants_1.I_END_POINT}/browse`, {
92
+ data: { continuation: this.continuation },
93
+ });
94
+ const playlistContents = response.data.onResponseReceivedActions[0].appendContinuationItemsAction
95
+ .continuationItems;
96
+ const videos = common_1.mapFilter(playlistContents, "playlistVideoRenderer");
97
+ newVideos.push(...videos.map((video) => new _1.VideoCompact({ client: this.client }).load(video)));
98
+ this.continuation = common_1.getContinuationFromItems(playlistContents);
99
+ }
100
+ this.videos.push(...newVideos);
101
+ return newVideos;
137
102
  });
138
- };
103
+ }
139
104
  /**
140
105
  * Get compact videos
141
106
  *
142
107
  * @param playlistContents raw object from youtubei
143
108
  */
144
- Playlist.prototype.getVideos = function (playlistContents) {
145
- var videosRenderer = playlistContents.map(function (c) { return c.playlistVideoRenderer; });
146
- var videos = [];
147
- for (var _i = 0, videosRenderer_1 = videosRenderer; _i < videosRenderer_1.length; _i++) {
148
- var videoRenderer = videosRenderer_1[_i];
109
+ static parseVideos(playlistContents, playlist) {
110
+ const videosRenderer = playlistContents.map((c) => c.playlistVideoRenderer);
111
+ const videos = [];
112
+ for (const videoRenderer of videosRenderer) {
149
113
  if (!videoRenderer)
150
114
  continue;
151
- videos.push(new VideoCompact_1.default().load(videoRenderer));
115
+ const video = new _1.VideoCompact({ client: playlist.client }).load(videoRenderer);
116
+ videos.push(video);
152
117
  }
153
118
  return videos;
154
- };
155
- Playlist.prototype.getSideBarInfo = function (stats, parseInt) {
156
- var data;
119
+ }
120
+ static parseSideBarInfo(stats, parseInt) {
121
+ let data;
157
122
  if ("runs" in stats)
158
- data = stats.runs.map(function (r) { return r.text; }).join("");
123
+ data = stats.runs.map((r) => r.text).join("");
159
124
  else
160
125
  data = stats.simpleText.replace(/[^0-9]/g, "");
161
126
  if (parseInt)
162
127
  data = +data.replace(/[^0-9]/g, "");
163
128
  return data;
164
- };
165
- return Playlist;
166
- }());
129
+ }
130
+ }
167
131
  exports.default = Playlist;
@@ -1,26 +1,38 @@
1
- import { Thumbnail, YoutubeRawData } from "../common";
2
- import BaseCompact from "./BaseCompact";
3
- import Channel from "./Channel";
4
- interface PlaylistCompactAttributes {
5
- id: string;
1
+ import { Thumbnails, BaseAttributes, Base, Playlist, ChannelCompact } from ".";
2
+ import { YoutubeRawData } from "../common";
3
+ /** @hidden */
4
+ interface PlaylistCompactAttributes extends BaseAttributes {
6
5
  title: string;
7
- thumbnails: Thumbnail[];
8
- channel?: Channel;
6
+ thumbnails: Thumbnails;
7
+ channel?: ChannelCompact;
9
8
  videoCount: number;
10
9
  }
11
- /**
12
- * Represent a Compact Playlist (e.g. from search result, upNext / related of a video)
13
- */
14
- export default class PlaylistCompact extends BaseCompact implements PlaylistCompactAttributes {
10
+ /** Represents a Compact Playlist (e.g. from search result, upNext / related of a video) */
11
+ export default class PlaylistCompact extends Base implements PlaylistCompactAttributes {
12
+ /** The playlist's title */
15
13
  title: string;
16
- channel?: Channel;
14
+ /** Thumbnails of the playlist with different sizes */
15
+ thumbnails: Thumbnails;
16
+ /** The channel that made this playlist */
17
+ channel?: ChannelCompact;
18
+ /** How many videos in this playlist */
17
19
  videoCount: number;
20
+ /** @hidden */
18
21
  constructor(playlist?: Partial<PlaylistCompactAttributes>);
19
22
  /**
20
- * Load instance attributes from youtube raw data
23
+ * Load this instance with raw data from Youtube
21
24
  *
22
- * @param youtubeRawData raw object from youtubei
25
+ * @hidden
23
26
  */
24
- load(youtubeRawData: YoutubeRawData): PlaylistCompact;
27
+ load(data: YoutubeRawData): PlaylistCompact;
28
+ /**
29
+ * Get {@link Playlist} object based on current playlist id
30
+ *
31
+ * Equivalent to
32
+ * ```js
33
+ * client.getPlaylist(playlistCompact.id);
34
+ * ```
35
+ */
36
+ getPlaylist(): Promise<Playlist | undefined>;
25
37
  }
26
38
  export {};
@@ -1,63 +1,59 @@
1
1
  "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- extendStatics(d, b);
11
- function __() { this.constructor = d; }
12
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13
- };
14
- })();
15
- var __importDefault = (this && this.__importDefault) || function (mod) {
16
- return (mod && mod.__esModule) ? mod : { "default": mod };
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
17
10
  };
18
11
  Object.defineProperty(exports, "__esModule", { value: true });
19
- var BaseCompact_1 = __importDefault(require("./BaseCompact"));
20
- var Channel_1 = __importDefault(require("./Channel"));
21
- /**
22
- * Represent a Compact Playlist (e.g. from search result, upNext / related of a video)
23
- */
24
- var PlaylistCompact = /** @class */ (function (_super) {
25
- __extends(PlaylistCompact, _super);
26
- function PlaylistCompact(playlist) {
27
- if (playlist === void 0) { playlist = {}; }
28
- var _this = _super.call(this) || this;
29
- Object.assign(_this, playlist);
30
- return _this;
12
+ const _1 = require(".");
13
+ const common_1 = require("../common");
14
+ /** Represents a Compact Playlist (e.g. from search result, upNext / related of a video) */
15
+ class PlaylistCompact extends _1.Base {
16
+ /** @hidden */
17
+ constructor(playlist = {}) {
18
+ super();
19
+ Object.assign(this, playlist);
31
20
  }
32
21
  /**
33
- * Load instance attributes from youtube raw data
22
+ * Load this instance with raw data from Youtube
34
23
  *
35
- * @param youtubeRawData raw object from youtubei
24
+ * @hidden
36
25
  */
37
- PlaylistCompact.prototype.load = function (youtubeRawData) {
26
+ load(data) {
38
27
  var _a;
39
- var playlistId = youtubeRawData.playlistId, title = youtubeRawData.title, thumbnail = youtubeRawData.thumbnail, shortBylineText = youtubeRawData.shortBylineText, videoCount = youtubeRawData.videoCount, videoCountShortText = youtubeRawData.videoCountShortText;
28
+ const { playlistId, title, thumbnail, shortBylineText, videoCount, videoCountShortText, } = data;
40
29
  this.id = playlistId;
41
30
  this.title = title.simpleText || title.runs[0].text;
42
- this.videoCount =
43
- +((_a = (videoCount !== null && videoCount !== void 0 ? videoCount : videoCountShortText.simpleText)) === null || _a === void 0 ? void 0 : _a.replace(/[^0-9]/g, "")) || 0;
31
+ this.videoCount = common_1.stripToInt(videoCount || videoCountShortText.simpleText) || 0;
44
32
  // Thumbnail
45
- var thumbnails = youtubeRawData.thumbnails;
46
- if (!thumbnails)
47
- thumbnails = thumbnail.thumbnails;
48
- else
49
- thumbnails = thumbnails[0].thumbnails;
50
- this.thumbnails = thumbnails;
33
+ this.thumbnails = new _1.Thumbnails().load(((_a = data.thumbnails) === null || _a === void 0 ? void 0 : _a[0].thumbnails) || thumbnail.thumbnails);
51
34
  // Channel
52
35
  if (shortBylineText && shortBylineText.simpleText !== "YouTube") {
53
- this.channel = new Channel_1.default({
54
- id: shortBylineText.runs[0].navigationEndpoint.browseEndpoint.browseId,
55
- name: shortBylineText.runs[0].text,
56
- url: "https://www.youtube.com" + shortBylineText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url,
36
+ const shortByLine = shortBylineText.runs[0];
37
+ this.channel = new _1.ChannelCompact({
38
+ id: shortByLine.navigationEndpoint.browseEndpoint.browseId,
39
+ name: shortByLine.text,
40
+ client: this.client,
57
41
  });
58
42
  }
59
43
  return this;
60
- };
61
- return PlaylistCompact;
62
- }(BaseCompact_1.default));
44
+ }
45
+ /**
46
+ * Get {@link Playlist} object based on current playlist id
47
+ *
48
+ * Equivalent to
49
+ * ```js
50
+ * client.getPlaylist(playlistCompact.id);
51
+ * ```
52
+ */
53
+ getPlaylist() {
54
+ return __awaiter(this, void 0, void 0, function* () {
55
+ return (yield this.client.getPlaylist(this.id));
56
+ });
57
+ }
58
+ }
63
59
  exports.default = PlaylistCompact;