youtubei 1.8.4 → 1.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/common/shared/HTTP/HTTP.js +5 -0
- package/dist/cjs/youtube/BaseChannel/ChannelShorts.js +12 -2
- package/dist/cjs/youtube/BaseVideo/BaseVideoParser.js +9 -7
- package/dist/cjs/youtube/VideoCompact/VideoCompactParser.js +6 -5
- package/dist/esm/common/shared/HTTP/HTTP.js +8 -0
- package/dist/esm/youtube/BaseChannel/ChannelShorts.js +11 -3
- package/dist/esm/youtube/BaseVideo/BaseVideoParser.js +10 -8
- package/dist/esm/youtube/VideoCompact/VideoCompactParser.js +6 -5
- package/dist/typings/common/shared/HTTP/HTTP.d.ts +2 -0
- package/dist/typings/youtube/BaseVideo/BaseVideo.d.ts +6 -0
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.HTTP = void 0;
|
|
16
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
16
17
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
17
18
|
const url_1 = require("url");
|
|
18
19
|
const OAuth_1 = require("./OAuth");
|
|
@@ -37,6 +38,7 @@ class HTTP {
|
|
|
37
38
|
this.authorizationPromise = null;
|
|
38
39
|
this.defaultFetchOptions = options.fetchOptions || {};
|
|
39
40
|
this.defaultClientOptions = options.youtubeClientOptions || {};
|
|
41
|
+
this.rawResponseLogPath = options.rawResponseLogPath;
|
|
40
42
|
}
|
|
41
43
|
get(path, options) {
|
|
42
44
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -79,6 +81,9 @@ class HTTP {
|
|
|
79
81
|
}
|
|
80
82
|
const response = yield node_fetch_1.default(urlString, options);
|
|
81
83
|
const data = yield response.json();
|
|
84
|
+
if (this.rawResponseLogPath) {
|
|
85
|
+
yield promises_1.default.appendFile(this.rawResponseLogPath, JSON.stringify({ url: urlString, response: data }) + "\n");
|
|
86
|
+
}
|
|
82
87
|
this.parseCookie(response);
|
|
83
88
|
return { data };
|
|
84
89
|
});
|
|
@@ -46,10 +46,20 @@ class ChannelShorts extends Continuable_1.Continuable {
|
|
|
46
46
|
});
|
|
47
47
|
const items = BaseChannelParser_1.BaseChannelParser.parseTabData("shorts", response.data);
|
|
48
48
|
const continuation = common_1.getContinuationFromItems(items);
|
|
49
|
-
const data =
|
|
49
|
+
const data = items.filter((i) => "reelItemRenderer" in i || "shortsLockupViewModel" in i);
|
|
50
50
|
return {
|
|
51
51
|
continuation,
|
|
52
|
-
items: data.map((i) =>
|
|
52
|
+
items: data.map((i) => {
|
|
53
|
+
const video = new VideoCompact_1.VideoCompact({
|
|
54
|
+
client: this.client,
|
|
55
|
+
channel: this.channel,
|
|
56
|
+
});
|
|
57
|
+
if (i.reelItemRenderer)
|
|
58
|
+
video.load(i.reelItemRenderer);
|
|
59
|
+
else if (i.shortsLockupViewModel)
|
|
60
|
+
video.loadLockup(i.lockupViewModel);
|
|
61
|
+
return video;
|
|
62
|
+
}),
|
|
53
63
|
};
|
|
54
64
|
});
|
|
55
65
|
}
|
|
@@ -8,7 +8,7 @@ const VideoCompact_1 = require("../VideoCompact");
|
|
|
8
8
|
const VideoCaptions_1 = require("./VideoCaptions");
|
|
9
9
|
class BaseVideoParser {
|
|
10
10
|
static loadBaseVideo(target, data) {
|
|
11
|
-
var _a, _b, _c, _d;
|
|
11
|
+
var _a, _b, _c, _d, _e, _f;
|
|
12
12
|
const videoInfo = BaseVideoParser.parseRawData(data);
|
|
13
13
|
// Basic information
|
|
14
14
|
target.id = videoInfo.videoDetails.videoId;
|
|
@@ -16,6 +16,8 @@ class BaseVideoParser {
|
|
|
16
16
|
target.uploadDate = videoInfo.dateText.simpleText;
|
|
17
17
|
target.viewCount = +videoInfo.videoDetails.viewCount || null;
|
|
18
18
|
target.isLiveContent = videoInfo.videoDetails.isLiveContent;
|
|
19
|
+
target.formats = ((_a = videoInfo.streamingData) === null || _a === void 0 ? void 0 : _a.formats) || [];
|
|
20
|
+
target.adaptiveFormats = ((_b = videoInfo.streamingData) === null || _b === void 0 ? void 0 : _b.adaptiveFormats) || [];
|
|
19
21
|
target.thumbnails = new common_1.Thumbnails().load(videoInfo.videoDetails.thumbnail.thumbnails);
|
|
20
22
|
// Channel
|
|
21
23
|
const { title, thumbnail, subscriberCountText } = videoInfo.owner.videoOwnerRenderer;
|
|
@@ -53,13 +55,13 @@ class BaseVideoParser {
|
|
|
53
55
|
: null;
|
|
54
56
|
// Tags and description
|
|
55
57
|
target.tags =
|
|
56
|
-
((
|
|
58
|
+
((_d = (_c = videoInfo.superTitleLink) === null || _c === void 0 ? void 0 : _c.runs) === null || _d === void 0 ? void 0 : _d.map((r) => r.text.trim()).filter((t) => t)) || [];
|
|
57
59
|
target.description = videoInfo.videoDetails.shortDescription || "";
|
|
58
60
|
// related videos
|
|
59
|
-
let secondaryContents = (
|
|
60
|
-
const itemSectionRenderer = (
|
|
61
|
+
let secondaryContents = (_e = data.response.contents.twoColumnWatchNextResults.secondaryResults) === null || _e === void 0 ? void 0 : _e.secondaryResults.results;
|
|
62
|
+
const itemSectionRenderer = (_f = secondaryContents === null || secondaryContents === void 0 ? void 0 : secondaryContents.find((c) => {
|
|
61
63
|
return c.itemSectionRenderer;
|
|
62
|
-
})) === null ||
|
|
64
|
+
})) === null || _f === void 0 ? void 0 : _f.itemSectionRenderer;
|
|
63
65
|
if (itemSectionRenderer)
|
|
64
66
|
secondaryContents = itemSectionRenderer.contents;
|
|
65
67
|
if (secondaryContents) {
|
|
@@ -85,8 +87,8 @@ class BaseVideoParser {
|
|
|
85
87
|
const primaryInfo = contents.find((c) => "videoPrimaryInfoRenderer" in c)
|
|
86
88
|
.videoPrimaryInfoRenderer;
|
|
87
89
|
const secondaryInfo = contents.find((c) => "videoSecondaryInfoRenderer" in c).videoSecondaryInfoRenderer;
|
|
88
|
-
const { videoDetails, captions } = data.playerResponse;
|
|
89
|
-
return Object.assign(Object.assign(Object.assign({}, secondaryInfo), primaryInfo), { videoDetails, captions });
|
|
90
|
+
const { videoDetails, captions, streamingData } = data.playerResponse;
|
|
91
|
+
return Object.assign(Object.assign(Object.assign({}, secondaryInfo), primaryInfo), { videoDetails, captions, streamingData });
|
|
90
92
|
}
|
|
91
93
|
static parseCompactRenderer(data, client) {
|
|
92
94
|
if ("compactVideoRenderer" in data) {
|
|
@@ -39,11 +39,12 @@ class VideoCompactParser {
|
|
|
39
39
|
return target;
|
|
40
40
|
}
|
|
41
41
|
static loadLockupVideoCompact(target, data) {
|
|
42
|
-
var _a, _b;
|
|
42
|
+
var _a, _b, _c;
|
|
43
43
|
const lockupMetadataViewModel = data.metadata.lockupMetadataViewModel;
|
|
44
44
|
const decoratedAvatarViewModel = lockupMetadataViewModel.image.decoratedAvatarViewModel;
|
|
45
|
-
const
|
|
46
|
-
|
|
45
|
+
const thumbnailOverlay = data.contentImage.thumbnailViewModel.overlays[0];
|
|
46
|
+
const thumbnailBadge = (((_a = thumbnailOverlay.thumbnailBottomOverlayViewModel) === null || _a === void 0 ? void 0 : _a.badges[0]) ||
|
|
47
|
+
thumbnailOverlay.thumbnailOverlayBadgeViewModel.thumbnailBadges[0]).thumbnailBadgeViewModel;
|
|
47
48
|
const metadataRows = lockupMetadataViewModel.metadata.contentMetadataViewModel.metadataRows;
|
|
48
49
|
const channel = new BaseChannel_1.BaseChannel({
|
|
49
50
|
client: target.client,
|
|
@@ -52,11 +53,11 @@ class VideoCompactParser {
|
|
|
52
53
|
.browseEndpoint.browseId,
|
|
53
54
|
thumbnails: new common_1.Thumbnails().load(decoratedAvatarViewModel.avatar.avatarViewModel.image.sources),
|
|
54
55
|
});
|
|
55
|
-
const isLive = ((
|
|
56
|
+
const isLive = ((_b = thumbnailBadge.icon) === null || _b === void 0 ? void 0 : _b.sources[0].clientResource.imageName) === "LIVE";
|
|
56
57
|
target.channel = channel;
|
|
57
58
|
target.id = data.contentId;
|
|
58
59
|
target.title = lockupMetadataViewModel.title.content;
|
|
59
|
-
target.isLive = ((
|
|
60
|
+
target.isLive = ((_c = thumbnailBadge.icon) === null || _c === void 0 ? void 0 : _c.sources[0].clientResource.imageName) === "LIVE";
|
|
60
61
|
target.duration = !isLive ? common_1.getDuration(thumbnailBadge.text) : null;
|
|
61
62
|
target.thumbnails = new common_1.Thumbnails().load(data.contentImage.thumbnailViewModel.image.sources);
|
|
62
63
|
target.viewCount = common_1.stripToInt(metadataRows[1].metadataParts[0].text.content);
|
|
@@ -72,6 +72,7 @@ var __read = (this && this.__read) || function (o, n) {
|
|
|
72
72
|
}
|
|
73
73
|
return ar;
|
|
74
74
|
};
|
|
75
|
+
import fs from "fs/promises";
|
|
75
76
|
import fetch from "node-fetch";
|
|
76
77
|
import { URLSearchParams } from "url";
|
|
77
78
|
import { OAuth } from "./OAuth";
|
|
@@ -96,6 +97,7 @@ var HTTP = /** @class */ (function () {
|
|
|
96
97
|
this.authorizationPromise = null;
|
|
97
98
|
this.defaultFetchOptions = options.fetchOptions || {};
|
|
98
99
|
this.defaultClientOptions = options.youtubeClientOptions || {};
|
|
100
|
+
this.rawResponseLogPath = options.rawResponseLogPath;
|
|
99
101
|
}
|
|
100
102
|
HTTP.prototype.get = function (path, options) {
|
|
101
103
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -172,6 +174,12 @@ var HTTP = /** @class */ (function () {
|
|
|
172
174
|
return [4 /*yield*/, response.json()];
|
|
173
175
|
case 6:
|
|
174
176
|
data = _e.sent();
|
|
177
|
+
if (!this.rawResponseLogPath) return [3 /*break*/, 8];
|
|
178
|
+
return [4 /*yield*/, fs.appendFile(this.rawResponseLogPath, JSON.stringify({ url: urlString, response: data }) + "\n")];
|
|
179
|
+
case 7:
|
|
180
|
+
_e.sent();
|
|
181
|
+
_e.label = 8;
|
|
182
|
+
case 8:
|
|
175
183
|
this.parseCookie(response);
|
|
176
184
|
return [2 /*return*/, { data: data }];
|
|
177
185
|
}
|
|
@@ -47,7 +47,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
47
47
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
|
-
import { getContinuationFromItems
|
|
50
|
+
import { getContinuationFromItems } from "../../common";
|
|
51
51
|
import { Continuable } from "../Continuable";
|
|
52
52
|
import { VideoCompact } from "../VideoCompact";
|
|
53
53
|
import { I_END_POINT } from "../constants";
|
|
@@ -93,11 +93,19 @@ var ChannelShorts = /** @class */ (function (_super) {
|
|
|
93
93
|
response = _b.sent();
|
|
94
94
|
items = BaseChannelParser.parseTabData("shorts", response.data);
|
|
95
95
|
continuation = getContinuationFromItems(items);
|
|
96
|
-
data =
|
|
96
|
+
data = items.filter(function (i) { return "reelItemRenderer" in i || "shortsLockupViewModel" in i; });
|
|
97
97
|
return [2 /*return*/, {
|
|
98
98
|
continuation: continuation,
|
|
99
99
|
items: data.map(function (i) {
|
|
100
|
-
|
|
100
|
+
var video = new VideoCompact({
|
|
101
|
+
client: _this.client,
|
|
102
|
+
channel: _this.channel,
|
|
103
|
+
});
|
|
104
|
+
if (i.reelItemRenderer)
|
|
105
|
+
video.load(i.reelItemRenderer);
|
|
106
|
+
else if (i.shortsLockupViewModel)
|
|
107
|
+
video.loadLockup(i.lockupViewModel);
|
|
108
|
+
return video;
|
|
101
109
|
}),
|
|
102
110
|
}];
|
|
103
111
|
}
|
|
@@ -18,7 +18,7 @@ var BaseVideoParser = /** @class */ (function () {
|
|
|
18
18
|
function BaseVideoParser() {
|
|
19
19
|
}
|
|
20
20
|
BaseVideoParser.loadBaseVideo = function (target, data) {
|
|
21
|
-
var _a, _b, _c, _d;
|
|
21
|
+
var _a, _b, _c, _d, _e, _f;
|
|
22
22
|
var videoInfo = BaseVideoParser.parseRawData(data);
|
|
23
23
|
// Basic information
|
|
24
24
|
target.id = videoInfo.videoDetails.videoId;
|
|
@@ -26,9 +26,11 @@ var BaseVideoParser = /** @class */ (function () {
|
|
|
26
26
|
target.uploadDate = videoInfo.dateText.simpleText;
|
|
27
27
|
target.viewCount = +videoInfo.videoDetails.viewCount || null;
|
|
28
28
|
target.isLiveContent = videoInfo.videoDetails.isLiveContent;
|
|
29
|
+
target.formats = ((_a = videoInfo.streamingData) === null || _a === void 0 ? void 0 : _a.formats) || [];
|
|
30
|
+
target.adaptiveFormats = ((_b = videoInfo.streamingData) === null || _b === void 0 ? void 0 : _b.adaptiveFormats) || [];
|
|
29
31
|
target.thumbnails = new Thumbnails().load(videoInfo.videoDetails.thumbnail.thumbnails);
|
|
30
32
|
// Channel
|
|
31
|
-
var
|
|
33
|
+
var _g = videoInfo.owner.videoOwnerRenderer, title = _g.title, thumbnail = _g.thumbnail, subscriberCountText = _g.subscriberCountText;
|
|
32
34
|
if (title) {
|
|
33
35
|
target.channel = new BaseChannel({
|
|
34
36
|
client: target.client,
|
|
@@ -63,13 +65,13 @@ var BaseVideoParser = /** @class */ (function () {
|
|
|
63
65
|
: null;
|
|
64
66
|
// Tags and description
|
|
65
67
|
target.tags =
|
|
66
|
-
((
|
|
68
|
+
((_d = (_c = videoInfo.superTitleLink) === null || _c === void 0 ? void 0 : _c.runs) === null || _d === void 0 ? void 0 : _d.map(function (r) { return r.text.trim(); }).filter(function (t) { return t; })) || [];
|
|
67
69
|
target.description = videoInfo.videoDetails.shortDescription || "";
|
|
68
70
|
// related videos
|
|
69
|
-
var secondaryContents = (
|
|
70
|
-
var itemSectionRenderer = (
|
|
71
|
+
var secondaryContents = (_e = data.response.contents.twoColumnWatchNextResults.secondaryResults) === null || _e === void 0 ? void 0 : _e.secondaryResults.results;
|
|
72
|
+
var itemSectionRenderer = (_f = secondaryContents === null || secondaryContents === void 0 ? void 0 : secondaryContents.find(function (c) {
|
|
71
73
|
return c.itemSectionRenderer;
|
|
72
|
-
})) === null ||
|
|
74
|
+
})) === null || _f === void 0 ? void 0 : _f.itemSectionRenderer;
|
|
73
75
|
if (itemSectionRenderer)
|
|
74
76
|
secondaryContents = itemSectionRenderer.contents;
|
|
75
77
|
if (secondaryContents) {
|
|
@@ -95,8 +97,8 @@ var BaseVideoParser = /** @class */ (function () {
|
|
|
95
97
|
var primaryInfo = contents.find(function (c) { return "videoPrimaryInfoRenderer" in c; })
|
|
96
98
|
.videoPrimaryInfoRenderer;
|
|
97
99
|
var secondaryInfo = contents.find(function (c) { return "videoSecondaryInfoRenderer" in c; }).videoSecondaryInfoRenderer;
|
|
98
|
-
var _a = data.playerResponse, videoDetails = _a.videoDetails, captions = _a.captions;
|
|
99
|
-
return __assign(__assign(__assign({}, secondaryInfo), primaryInfo), { videoDetails: videoDetails, captions: captions });
|
|
100
|
+
var _a = data.playerResponse, videoDetails = _a.videoDetails, captions = _a.captions, streamingData = _a.streamingData;
|
|
101
|
+
return __assign(__assign(__assign({}, secondaryInfo), primaryInfo), { videoDetails: videoDetails, captions: captions, streamingData: streamingData });
|
|
100
102
|
};
|
|
101
103
|
BaseVideoParser.parseCompactRenderer = function (data, client) {
|
|
102
104
|
if ("compactVideoRenderer" in data) {
|
|
@@ -38,11 +38,12 @@ var VideoCompactParser = /** @class */ (function () {
|
|
|
38
38
|
return target;
|
|
39
39
|
};
|
|
40
40
|
VideoCompactParser.loadLockupVideoCompact = function (target, data) {
|
|
41
|
-
var _a, _b;
|
|
41
|
+
var _a, _b, _c;
|
|
42
42
|
var lockupMetadataViewModel = data.metadata.lockupMetadataViewModel;
|
|
43
43
|
var decoratedAvatarViewModel = lockupMetadataViewModel.image.decoratedAvatarViewModel;
|
|
44
|
-
var
|
|
45
|
-
|
|
44
|
+
var thumbnailOverlay = data.contentImage.thumbnailViewModel.overlays[0];
|
|
45
|
+
var thumbnailBadge = (((_a = thumbnailOverlay.thumbnailBottomOverlayViewModel) === null || _a === void 0 ? void 0 : _a.badges[0]) ||
|
|
46
|
+
thumbnailOverlay.thumbnailOverlayBadgeViewModel.thumbnailBadges[0]).thumbnailBadgeViewModel;
|
|
46
47
|
var metadataRows = lockupMetadataViewModel.metadata.contentMetadataViewModel.metadataRows;
|
|
47
48
|
var channel = new BaseChannel({
|
|
48
49
|
client: target.client,
|
|
@@ -51,11 +52,11 @@ var VideoCompactParser = /** @class */ (function () {
|
|
|
51
52
|
.browseEndpoint.browseId,
|
|
52
53
|
thumbnails: new Thumbnails().load(decoratedAvatarViewModel.avatar.avatarViewModel.image.sources),
|
|
53
54
|
});
|
|
54
|
-
var isLive = ((
|
|
55
|
+
var isLive = ((_b = thumbnailBadge.icon) === null || _b === void 0 ? void 0 : _b.sources[0].clientResource.imageName) === "LIVE";
|
|
55
56
|
target.channel = channel;
|
|
56
57
|
target.id = data.contentId;
|
|
57
58
|
target.title = lockupMetadataViewModel.title.content;
|
|
58
|
-
target.isLive = ((
|
|
59
|
+
target.isLive = ((_c = thumbnailBadge.icon) === null || _c === void 0 ? void 0 : _c.sources[0].clientResource.imageName) === "LIVE";
|
|
59
60
|
target.duration = !isLive ? getDuration(thumbnailBadge.text) : null;
|
|
60
61
|
target.thumbnails = new Thumbnails().load(data.contentImage.thumbnailViewModel.image.sources);
|
|
61
62
|
target.viewCount = stripToInt(metadataRows[1].metadataParts[0].text.content);
|
|
@@ -22,6 +22,7 @@ export declare type HTTPOptions = {
|
|
|
22
22
|
initialCookie?: string;
|
|
23
23
|
oauth?: OAuthOptions;
|
|
24
24
|
pot?: PotOptions;
|
|
25
|
+
rawResponseLogPath?: string;
|
|
25
26
|
};
|
|
26
27
|
declare type Response<T = any> = {
|
|
27
28
|
data: T;
|
|
@@ -45,6 +46,7 @@ export declare class HTTP {
|
|
|
45
46
|
private authorizationPromise;
|
|
46
47
|
private pot?;
|
|
47
48
|
oauth: OAuthOptions & OAuthProps;
|
|
49
|
+
private rawResponseLogPath?;
|
|
48
50
|
constructor(options: HTTPOptions);
|
|
49
51
|
get(path: string, options?: Partial<Options>): Promise<Response>;
|
|
50
52
|
post(path: string, options?: Partial<Options>): Promise<Response>;
|
|
@@ -17,6 +17,8 @@ export interface BaseVideoProperties extends BaseProperties {
|
|
|
17
17
|
likeCount?: number | null;
|
|
18
18
|
isLiveContent?: boolean;
|
|
19
19
|
tags?: string[];
|
|
20
|
+
formats?: YoutubeRawData[];
|
|
21
|
+
adaptiveFormats?: YoutubeRawData[];
|
|
20
22
|
}
|
|
21
23
|
/** Represents a Video */
|
|
22
24
|
export declare class BaseVideo extends Base implements BaseVideoProperties {
|
|
@@ -40,6 +42,10 @@ export declare class BaseVideo extends Base implements BaseVideoProperties {
|
|
|
40
42
|
/** Whether this video is a live content or not */
|
|
41
43
|
isLiveContent: boolean;
|
|
42
44
|
/** The tags of this video */
|
|
45
|
+
/** The formats of the video */
|
|
46
|
+
formats: YoutubeRawData[];
|
|
47
|
+
/** The adaptive formats of the video */
|
|
48
|
+
adaptiveFormats: YoutubeRawData[];
|
|
43
49
|
tags: string[];
|
|
44
50
|
/** Continuable of videos / playlists related to this video */
|
|
45
51
|
related: VideoRelated;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "youtubei",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.6",
|
|
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",
|