diff --git a/.eslintrc.yml b/.eslintrc.yml index e9f58aa2..c6e6843d 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -23,6 +23,7 @@ rules: quotes: [error, single] + jsdoc/newline-after-description: 'off' jsdoc/require-returns-description: 'off' jsdoc/require-param-description: 'off' jsdoc/no-undefined-types: 'off' diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index a843be5f..01bbe9c2 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -6,7 +6,7 @@ body: - type: textarea id: feature-description attributes: - label: Describe your suggestion + label: Describe your suggestion placeholder: How would it work? validations: required: true @@ -26,8 +26,8 @@ body: - label: I am running the latest version. required: true - label: I checked the documentation and found no answer. - required: true - - label: I have searched the existing issues and made sure this is not a duplicate. - required: true - - label: I have provided sufficient information. required: true + - label: I have searched the existing issues and made sure this is not a duplicate. + required: true + - label: I have provided sufficient information. + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/issue.yml b/.github/ISSUE_TEMPLATE/issue.yml index c6c6671c..27377d2a 100644 --- a/.github/ISSUE_TEMPLATE/issue.yml +++ b/.github/ISSUE_TEMPLATE/issue.yml @@ -57,7 +57,7 @@ body: label: Anything else? description: | Links? References? Anything that will give us more context about the issue you are encountering! - + Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. validations: required: false @@ -70,8 +70,8 @@ body: - label: I am running the latest version. required: false - label: I checked the documentation and found no answer. - required: true - - label: I have searched the existing issues and made sure this is not a duplicate. - required: true - - label: I have provided sufficient information. required: true + - label: I have searched the existing issues and made sure this is not a duplicate. + required: true + - label: I have provided sufficient information. + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml index 53639ffe..946131a2 100644 --- a/.github/ISSUE_TEMPLATE/question.yml +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -6,7 +6,7 @@ body: - type: textarea id: question attributes: - label: Question + label: Question placeholder: What do you want to know? validations: required: true @@ -26,8 +26,8 @@ body: - label: I am running the latest version. required: true - label: I checked the documentation and found no answer. - required: true - - label: I have searched the existing issues and made sure this is not a duplicate. - required: true - - label: I have provided sufficient information. required: true + - label: I have searched the existing issues and made sure this is not a duplicate. + required: true + - label: I have provided sufficient information. + required: true \ No newline at end of file diff --git a/examples/index.js b/examples/index.js deleted file mode 100644 index 5667a20f..00000000 --- a/examples/index.js +++ /dev/null @@ -1,95 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const Innertube = require('..'); -const creds_path = './yt_oauth_creds.json'; -const creds = fs.existsSync(creds_path) && JSON.parse(fs.readFileSync(creds_path).toString()) || {}; - -/** - * - */ -async function start() { - const youtube = await new Innertube(); - - youtube.ev.on('auth', (data) => { - if (data.status === 'AUTHORIZATION_PENDING') { - console.info(`Hello!\nOn your phone or computer, go to ${data.verification_url} and enter the code ${data.code}`); - } else if (data.status === 'SUCCESS') { - fs.writeFileSync(creds_path, JSON.stringify(data.credentials)); - console.info('Successfully signed-in, enjoy!'); - } - }); - - youtube.ev.on('update-credentials', (data) => { - fs.writeFileSync(creds_path, JSON.stringify(data.credentials)); - console.info('Credentials updated!', data); - }); - - await youtube.signIn(creds); - - const search = await youtube.search('Looking for life on Mars - documentary'); - console.info('Search results:', search); - - const video = await youtube.getDetails(search.videos[0].id); - console.info('Video details:', video); - - if (youtube.logged_in) { - const myNotifications = await youtube.getNotifications(); - console.info('My notifications:', myNotifications); - - const like = await video.like(); - if (like.success) { - console.info('Video marked as liked!'); - } - - const dislike = await video.dislike(); - if (dislike.success) { - console.info('Video marked as disliked!'); - } - - const removeDislikeOrLike = await video.removeLike(); - if (removeDislikeOrLike.success) { - console.info('Removed the dislike/like!') - } - - const myComment = await video.comment('Haha, nice!'); - if (myComment.success) { - console.info('Comment successfully posted!') - } - - const subscribe = await video.subscribe(); - if (subscribe.success) { - console.info('Just subscribed to', video.metadata.channel_name + '!'); - } - - const unsubscribe = await video.unsubscribe(); - if (unsubscribe.success) { - console.info('Just unsubscribed from', video.metadata.channel_name + ' :('); - } - } - - // Downloading videos: - const stream = youtube.download(search.videos[0].id, { - format: 'mp4', // Optional, ignored when type is set to audio and defaults to mp4, and I recommend to leave it as it is - quality: '360p', // if a video doesn't have a specific quality it'll fall back to 360p, this is ignored when type is set to audio - type: 'videoandaudio' // can be “video”, “audio” and “videoandaudio” - }); - - stream.pipe(fs.createWriteStream(`./${search.videos[0].id}.mp4`)); - - stream.on('start', () => { - console.info('[DOWNLOADER]', 'Starting download now!'); - }); - - stream.on('info', (info) => { - console.info('[DOWNLOADER]', `Downloading ${info.title} by ${info.basic_info.channel.name}`); - }); - - stream.on('end', () => { - console.info('[DOWNLOADER]', 'Done!'); - }); - - stream.on('error', (err) => console.error('[ERROR]', err)); -} - -start(); \ No newline at end of file diff --git a/examples/livechat/README.md b/examples/livechat/README.md new file mode 100644 index 00000000..b25555db --- /dev/null +++ b/examples/livechat/README.md @@ -0,0 +1,72 @@ +## Live Chat + +The library's Live Chat parser and poller were highly based on YouTube's original compiled code, this makes it behave in a similar if not identical way to YouTube's Live Chat. Here you can do all sorts of funny things, ex; track messages, donations, polls, and much more. + +## Usage + +Before fetching a Live Chat, you have to retrieve the target livestream's info: + +```js +const info = await session.getInfo('video_id'); +``` + +Then you may request a Live Chat instance: +```js +const livechat = await info.getLiveChat(); +``` + +## API + +* LiveChat + * [.ev](#ev) ⇒ `EventEmitter` + * [.start](#start) ⇒ `function` + * [.stop](#stop) ⇒ `function` + * [.sendMessage](#sendmessage) ⇒ `function` + + +### ev +Live Chat's EventEmitter. + +**Events:** + +- `start` + + Arguments: + | Type | Description | + | --- | --- | + | `object` | Initial chat data, actions, info, etc. | + +- `chat-update` + + Arguments: + | Type | Description | + | --- | --- | + | `object` | Chat Action | + +- `metadata-update` + + Arguments: + | Type | Description | + | --- | --- | + | `object` | LiveStream Metadata | + + +### start() +Starts the Live Chat. + + +### stop() +Stops the Live Chat. + + +### sendMessage(text) +Sends a message. + +| Param | Type | Description | +| --- | --- | --- | +| text | `string` | Message content | + +**Returns:** `Promise.` + +## Example +See [`index.js`]('./index.js'). diff --git a/examples/livechat/index.js b/examples/livechat/index.js new file mode 100644 index 00000000..2c60f6e7 --- /dev/null +++ b/examples/livechat/index.js @@ -0,0 +1,62 @@ +import Innertube from '../..'; + +const session = await new Innertube(); + +const info = await session.getInfo('video_id'); +const livechat = await info.getLiveChat(); + +livechat.ev.on('start', (initial_data) => { + /** + * Initial info is what you see when you first open a Live Chat — this is; inital actions, account's info and so on. + */ + + console.info(`Hey ${initial_data.viewer_name}, welcome to ${info.basic_info.channel.name}\'s Live Chat!`); +}); + +livechat.ev.on('chat-update', (action) => { + /** + * An action represents what is being added to + * the live chat. All actions have a `type` property, + * including their item (if the action has an item). + * + * Below are a few examples of how this can be used. + */ + + if (action.type === 'AddChatItemAction') { + const hours = new Date(action.item.timestamp).toLocaleTimeString('en-US', { + hour: '2-digit', + minute: '2-digit' + }); + + switch (action.item.type) { + case 'LiveChatTextMessage': + console.info( + `${hours} - ${action.item.author.name.toString()}:\n` + + `${action.item.message.toString()}\n` + ); + break; + case 'LiveChatPaidMessage': + console.info(` + ${hours} - ${action.item.author.name.toString()} + ${action.item.purchase_amount} + `); + break; + default: + console.debug(action); + } + } + + if (action.type === 'MarkChatItemAsDeletedAction') { + console.warn(`Message ${action.target_item_id} just got deleted and should be replaced with ${action.delete_state_message.toString()}!`); + } +}); + +livechat.ev.on('metadata-update', (metadata) => { + console.info(` + VIEWS: ${metadata.views.view_count.toString()} + LIKES: ${metadata.likes.default_text} + DATE: ${metadata.date.date_text} + `); +}); + +livechat.start(); \ No newline at end of file diff --git a/lib/Innertube.js b/lib/Innertube.js index 4b9cf1ee..06d8bd5f 100644 --- a/lib/Innertube.js +++ b/lib/Innertube.js @@ -2,7 +2,6 @@ const OAuth = require('./core/OAuth'); const Actions = require('./core/Actions'); -const Livechat = require('./core/Livechat'); const SessionBuilder = require('./core/SessionBuilder'); const AccountManager = require('./core/AccountManager'); const PlaylistManager = require('./core/PlaylistManager'); @@ -207,43 +206,6 @@ class Innertube { return suggestions; } - - /** - * Retrieves video info. - * - * @deprecated do not use this, it is slow and inefficient. - * Use {@link getInfo} instead. - * @param {string} video_id - the video id. - * @returns {Promise.<{ title: string, description: string, thumbnail: any[], metadata: object }>} - */ - async getDetails(video_id) { - Utils.throwIfMissing({ video_id }); - - const response = await this.actions.getVideoInfo(video_id); - const continuation = await this.actions.next({ video_id }); - response.continuation = continuation.data; - - const details = new OldParser(this, response, { - client: 'YOUTUBE', - data_type: 'VIDEO_INFO' - }).parse(); - - const livechat_ctoken = continuation.data.contents?.twoColumnWatchNextResults - ?.conversationBar?.liveChatRenderer?.continuations?.find((continuation) => continuation.reloadContinuationData) - .reloadContinuationData.continuation; - - details.like = () => this.actions.engage('like/like', { video_id }); - details.dislike = () => this.actions.engage('like/dislike', { video_id }); - details.removeLike = () => this.actions.engage('like/removelike', { video_id }); - details.subscribe = () => this.actions.engage('subscription/subscribe', { channel_id: details.metadata.channel_id }); - details.unsubscribe = () => this.actions.engage('subscription/unsubscribe', { channel_id: details.metadata.channel_id }); - details.comment = (text) => this.actions.engage('comment/create_comment', { video_id, text }); - details.getComments = (sort_by) => this.getComments(video_id, sort_by); - details.getLivechat = () => new Livechat(this, livechat_ctoken, details.metadata.channel_id, video_id); - details.setNotificationPreferences = (type) => this.actions.notifications('modify_channel_preference', { channel_id: details.metadata.channel_id, pref: type || 'NONE' }); - - return details; - } /** * Retrieves comments for a video. diff --git a/lib/core/Actions.js b/lib/core/Actions.js index a5ac58e3..dad3295d 100644 --- a/lib/core/Actions.js +++ b/lib/core/Actions.js @@ -334,10 +334,11 @@ class Actions { * @returns {Promise.} */ async livechat(action, args = {}) { - const data = {}; + const data = { client: args.client }; switch (action) { case 'live_chat/get_live_chat': + case 'live_chat/get_live_chat_replay': data.continuation = args.ctoken; break; case 'live_chat/send_message': diff --git a/lib/core/Livechat.js b/lib/core/Livechat.js deleted file mode 100644 index 45affc3d..00000000 --- a/lib/core/Livechat.js +++ /dev/null @@ -1,139 +0,0 @@ -'use strict'; - -const EventEmitter = require('events'); - -/** @namespace */ -class Livechat extends EventEmitter { - constructor(session, token, channel_id, video_id) { - super(session); - - if (!token) - throw new Error('Could not retrieve livechat data'); - - this.ctoken = token; - this.session = session; - this.video_id = video_id; - this.channel_id = channel_id; - - this.message_queue = []; - this.id_cache = []; - - this.poll_intervals_ms = 1000; - this.running = true; - - this.#poll(); - } - - async #poll() { - if (!this.running) return; - - const livechat = await this.session.actions.livechat('live_chat/get_live_chat', { ctoken: this.ctoken }); - if (!livechat.success) { - this.emit('error', { message: `Failed polling livechat: ${livechat.message}. Retrying...` }); - return await this.#poll(); - } - - const continuation_contents = livechat.data.continuationContents; - const action_group = continuation_contents.liveChatContinuation.actions; - this.#enqueueActionGroup(action_group); - - this.message_queue.forEach((message) => { - if (this.id_cache.includes(message.id)) return; - setTimeout(() => this.emit('chat-update', message), message.timestamp / 1000 - new Date().getTime()); - this.id_cache.push(message.id); - }); - - this.message_queue = []; - - const data = { video_id: this.video_id }; - if (this.metadata_ctoken) data.ctoken = this.metadata_ctoken; - - const updated_metadata = await this.session.actions.livechat('updated_metadata', data); - if (!updated_metadata.success) { - this.emit('error', { message: `Failed polling livechat metadata: ${livechat.message}.` }); - } - - this.metadata_ctoken = updated_metadata.data.continuation.timedContinuationData.continuation; - - const metadata = updated_metadata.data.actions; - this.emit('update-metadata', { - likes: metadata[1].updateToggleButtonTextAction.defaultText.simpleText, - view_count: { - simple_text: metadata[0].updateViewershipAction.viewCount.videoViewCountRenderer.viewCount.simpleText, - short_view_count: metadata[0].updateViewershipAction.viewCount.videoViewCountRenderer.extraShortViewCount.simpleText - } - }); - - this.livechat_poller = setTimeout(async () => await this.#poll(), this.poll_intervals_ms); - } - - #enqueueActionGroup(group) { - group.forEach((action) => { - if (!action.addChatItemAction) return; //TODO: handle different action types - const message_content = action.addChatItemAction.item.liveChatTextMessageRenderer; - if (!message_content) return; - - const message = { - text: message_content.message.runs.map((item) => item.text).join(' '), - author: { - name: message_content.authorName && message_content.authorName.simpleText || 'N/', - channel_id: message_content.authorExternalChannelId, - profile_picture: message_content.authorPhoto.thumbnails - }, - timestamp: message_content.timestampUsec, - id: message_content.id - }; - - this.message_queue.push(message); - }); - } - - async sendMessage(text) { - const message = await this.session.actions.livechat('live_chat/send_message', { text, channel_id: this.channel_id, video_id: this.video_id }); - if (!message.success) return message; - - const deleteMessage = async () => { - const menu = await this.session.actions.livechat('live_chat/get_item_context_menu', { params: { params: message.data.actions[0].addChatItemAction.item.liveChatTextMessageRenderer.contextMenuEndpoint.liveChatItemContextMenuEndpoint.params, pbj: 1 } }); - if (!menu.success) return menu; - - const chat_item_menu = menu.data.liveChatItemContextMenuSupportedRenderers.menuRenderer.items[0]; - - const cmd = await this.session.actions.livechat('live_chat/moderate', { params: chat_item_menu.menuServiceItemRenderer.serviceEndpoint.moderateLiveChatEndpoint.params }); - if (!cmd.success) return cmd; - - return { success: true, status_code: cmd.status_code }; - }; - - return { - success: true, - status_code: message.status_code, - deleteMessage: deleteMessage, - message_data: { - text: message.data.actions[0].addChatItemAction.item.liveChatTextMessageRenderer.message.runs.map((item) => item.text).join(' '), - author: { - name: message.data.actions[0].addChatItemAction.item.liveChatTextMessageRenderer.authorName && message.data.actions[0].addChatItemAction.item.liveChatTextMessageRenderer.authorName.simpleText || 'N/', - channel_id: message.data.actions[0].addChatItemAction.item.liveChatTextMessageRenderer.authorExternalChannelId, - profile_picture: message.data.actions[0].addChatItemAction.item.liveChatTextMessageRenderer.authorPhoto.thumbnails - }, - timestamp: message.data.actions[0].addChatItemAction.item.liveChatTextMessageRenderer.timestampUsec, - id: message.data.actions[0].addChatItemAction.item.liveChatTextMessageRenderer.id - } - }; - } - - /** - * Blocks a user. - * - * @todo Implement this method - */ - async blockUser() { - throw new Error('Not implemented'); - } - - stop() { - this.running = false; - clearTimeout(this.livechat_poller); - } -} - -module.exports = Livechat; \ No newline at end of file diff --git a/lib/parser/contents/classes/EmojiRun.js b/lib/parser/contents/classes/EmojiRun.js new file mode 100644 index 00000000..6f06e60e --- /dev/null +++ b/lib/parser/contents/classes/EmojiRun.js @@ -0,0 +1,20 @@ +'use strict'; + +const Thumbnail = require('./Thumbnail'); + +class EmojiRun { + constructor(data) { + this.text = + data.emoji?.emojiId || + data.emoji?.shortcuts?.[0] || null; + + this.emoji = { + emoji_id: data.emoji.emojiId, + shortcuts: data.emoji.shortcuts, + search_terms: data.emoji.searchTerms, + image: Thumbnail.fromResponse(data.emoji.image) + } + } +} + +module.exports = EmojiRun; \ No newline at end of file diff --git a/lib/parser/contents/classes/LiveChat.js b/lib/parser/contents/classes/LiveChat.js index 7d51ef40..2f8c0a6c 100644 --- a/lib/parser/contents/classes/LiveChat.js +++ b/lib/parser/contents/classes/LiveChat.js @@ -19,6 +19,8 @@ class LiveChat { reconnected_message: new Text(data.clientMessages.reconnectedMessage), generic_error: new Text(data.clientMessages.genericError) }; + + this.is_replay = data.isReplay || false; } } diff --git a/lib/parser/contents/classes/LiveChatAuthorBadge.js b/lib/parser/contents/classes/LiveChatAuthorBadge.js new file mode 100644 index 00000000..cdadbba9 --- /dev/null +++ b/lib/parser/contents/classes/LiveChatAuthorBadge.js @@ -0,0 +1,14 @@ +'use strict'; + +const MetadataBadge = require('./MetadataBadge'); +const Thumbnail = require('./Thumbnail'); + +class LiveChatAuthorBadge extends MetadataBadge { + constructor(data) { + super(data); + + this.custom_thumbnail = data.customThumbnail && Thumbnail.fromResponse(data.customThumbnail) || null; + } +} + +module.exports = LiveChatAuthorBadge; \ No newline at end of file diff --git a/lib/parser/contents/classes/LiveChatItemList.js b/lib/parser/contents/classes/LiveChatItemList.js new file mode 100644 index 00000000..6bc41b4e --- /dev/null +++ b/lib/parser/contents/classes/LiveChatItemList.js @@ -0,0 +1,14 @@ +'use strict'; + +const Parser = require('..'); + +class LiveChatItemList { + type = 'LiveChatItemList'; + + constructor(data) { + this.max_items_to_display = data.maxItemsToDisplay; + this.more_comments_below_button = Parser.parse(data.moreCommentsBelowButton); + } +} + +module.exports = LiveChatItemList; \ No newline at end of file diff --git a/lib/parser/contents/classes/LiveChatMessageInput.js b/lib/parser/contents/classes/LiveChatMessageInput.js new file mode 100644 index 00000000..67afd9af --- /dev/null +++ b/lib/parser/contents/classes/LiveChatMessageInput.js @@ -0,0 +1,16 @@ +'use strict'; + +const Text = require('./Text') +const Parser = require('..'); +const Thumbnail = require('./Thumbnail'); + +class LiveChatMessageInput { + constructor(data) { + this.author_name = new Text(data.authorName); + this.author_photo = Thumbnail.fromResponse(data.authorPhoto); + this.send_button = Parser.parse(data.sendButton); + this.target_id = data.targetId; + } +} + +module.exports = LiveChatMessageInput; \ No newline at end of file diff --git a/lib/parser/contents/classes/LiveChatParticipant.js b/lib/parser/contents/classes/LiveChatParticipant.js new file mode 100644 index 00000000..dd0f393a --- /dev/null +++ b/lib/parser/contents/classes/LiveChatParticipant.js @@ -0,0 +1,17 @@ +'use strict'; + +const Parser = require('..'); +const Text = require('./Text'); +const Thumbnail = require('./Thumbnail'); + +class LiveChatParticipant { + type = 'LiveChatParticipant'; + + constructor(data) { + this.name = new Text(data.authorName); + this.photo = Thumbnail.fromResponse(data.authorPhoto); + this.badges = Parser.parse(data.authorBadges); + } +} + +module.exports = LiveChatParticipant; \ No newline at end of file diff --git a/lib/parser/contents/classes/LiveChatParticipantsList.js b/lib/parser/contents/classes/LiveChatParticipantsList.js new file mode 100644 index 00000000..bcee2e73 --- /dev/null +++ b/lib/parser/contents/classes/LiveChatParticipantsList.js @@ -0,0 +1,15 @@ +'use strict'; + +const Parser = require('..'); +const Text = require('./Text'); + +class LiveChatParticipantsList { + type = 'LiveChatParticipantsList'; + + constructor(data) { + this.title = new Text(data.title); + this.participants = Parser.parse(data.participants); + } +} + +module.exports = LiveChatParticipantsList; \ No newline at end of file diff --git a/lib/parser/contents/classes/MetadataBadge.js b/lib/parser/contents/classes/MetadataBadge.js index 2270fb10..2069342b 100644 --- a/lib/parser/contents/classes/MetadataBadge.js +++ b/lib/parser/contents/classes/MetadataBadge.js @@ -2,9 +2,9 @@ class MetadataBadge { constructor(data) { - this.icon_type = data.icon?.iconType; - this.style = data.style; - this.tooltip = data.tooltip; + this.icon_type = data.icon?.iconType || null; + this.style = data.style || null; + this.tooltip = data.tooltip || null; } } diff --git a/lib/parser/contents/classes/NavigatableText.js b/lib/parser/contents/classes/NavigatableText.js index c3ec6e68..e0966d37 100644 --- a/lib/parser/contents/classes/NavigatableText.js +++ b/lib/parser/contents/classes/NavigatableText.js @@ -1,3 +1,5 @@ +'use strict'; + const Text = require('./Text'); const NavigationEndpoint = require('./NavigationEndpoint'); diff --git a/lib/parser/contents/classes/NavigationEndpoint.js b/lib/parser/contents/classes/NavigationEndpoint.js index 6885e0bc..ff36e381 100644 --- a/lib/parser/contents/classes/NavigationEndpoint.js +++ b/lib/parser/contents/classes/NavigationEndpoint.js @@ -148,6 +148,24 @@ class NavigationEndpoint { params: data.getReportFormEndpoint.params } } + + if (data?.liveChatItemContextMenuEndpoint) { + this.live_chat_item_context_menu = { + params: data?.liveChatItemContextMenuEndpoint?.params + } + } + + if (data?.sendLiveChatVoteEndpoint) { + this.send_live_chat_vote = { + params: data.sendLiveChatVoteEndpoint.params + } + } + + if (data?.liveChatItemContextMenuEndpoint) { + this.live_chat_item_context_menu = { + params: data.liveChatItemContextMenuEndpoint.params + } + } } async call(actions, client) { diff --git a/lib/parser/contents/classes/Text.js b/lib/parser/contents/classes/Text.js index af5c24a0..c2a4fb92 100644 --- a/lib/parser/contents/classes/Text.js +++ b/lib/parser/contents/classes/Text.js @@ -1,12 +1,19 @@ 'use strict'; const TextRun = require('./TextRun'); +const EmojiRun = require('./EmojiRun'); class Text { + text; + constructor(data) { if (data?.hasOwnProperty('runs')) { - this.text = data.runs.map((run) => run.text).join(''); - this.runs = data.runs.map((run) => new TextRun(run)); + this.runs = data.runs.map((run) => run.emoji && + new EmojiRun(run) || + new TextRun(run) + ); + + this.text = this.runs.map((run) => run.text).join(''); } else { this.text = data?.simpleText || 'N/A'; } diff --git a/lib/parser/contents/classes/Thumbnail.js b/lib/parser/contents/classes/Thumbnail.js index b6a62f45..47713f62 100644 --- a/lib/parser/contents/classes/Thumbnail.js +++ b/lib/parser/contents/classes/Thumbnail.js @@ -11,6 +11,7 @@ class Thumbnail { * @type {number} */ height; + constructor ({ url, width, height }) { this.url = url; this.width = width; @@ -20,14 +21,12 @@ class Thumbnail { /** * Get thumbnails from response object * - * @param {*} response response object + * @param {object} data - response object * @returns {Thumbnail[]} sorted array of thumbnails */ - static fromResponse({ thumbnails }) { - if (!thumbnails) { - return; - } - return thumbnails.map(x => new Thumbnail(x)).sort((a, b) => b.width - a.width); + static fromResponse(data) { + if (!data || !data.thumbnails) return; + return data.thumbnails.map(x => new Thumbnail(x)).sort((a, b) => b.width - a.width); } } diff --git a/lib/parser/contents/classes/livechat/AddBannerToLiveChatCommand.js b/lib/parser/contents/classes/livechat/AddBannerToLiveChatCommand.js new file mode 100644 index 00000000..a911474c --- /dev/null +++ b/lib/parser/contents/classes/livechat/AddBannerToLiveChatCommand.js @@ -0,0 +1,11 @@ +'use strict'; + +const Parser = require('../..'); + +class AddBannerToLiveChatCommand { + constructor(data) { + return Parser.parse(data.bannerRenderer, 'livechat/items'); + } +} + +module.exports = AddBannerToLiveChatCommand; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/AddChatItemAction.js b/lib/parser/contents/classes/livechat/AddChatItemAction.js new file mode 100644 index 00000000..e6f32552 --- /dev/null +++ b/lib/parser/contents/classes/livechat/AddChatItemAction.js @@ -0,0 +1,14 @@ +'use strict'; + +const Parser = require('../..'); + +class AddChatItemAction { + type = 'AddChatItemAction'; + + constructor(data) { + this.item = Parser.parse(data.item, 'livechat/items'); + this.client_id = data.clientId || null; + } +} + +module.exports = AddChatItemAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/AddLiveChatTickerItemAction.js b/lib/parser/contents/classes/livechat/AddLiveChatTickerItemAction.js new file mode 100644 index 00000000..ac50d55f --- /dev/null +++ b/lib/parser/contents/classes/livechat/AddLiveChatTickerItemAction.js @@ -0,0 +1,14 @@ +'use strict'; + +const Parser = require('../..'); + +class AddLiveChatTickerItemAction { + type = 'AddLiveChatTickerItemAction'; + + constructor(data) { + this.item = Parser.parse(data.item, 'livechat/items'); + this.duration_sec = data.durationSec; + } +} + +module.exports = AddLiveChatTickerItemAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/LiveChatActionPanel.js b/lib/parser/contents/classes/livechat/LiveChatActionPanel.js new file mode 100644 index 00000000..b4880ef7 --- /dev/null +++ b/lib/parser/contents/classes/livechat/LiveChatActionPanel.js @@ -0,0 +1,15 @@ +'use strict'; + +const Parser = require('../..'); + +class LiveChatActionPanel { + type = 'LiveChatActionPanel'; + + constructor(data) { + this.id = data.id; + this.contents = Parser.parse(data.contents, 'livechat/items'); + this.target_id = data.targetId; + } +} + +module.exports = LiveChatActionPanel; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/MarkChatItemAsDeletedAction.js b/lib/parser/contents/classes/livechat/MarkChatItemAsDeletedAction.js new file mode 100644 index 00000000..5c633609 --- /dev/null +++ b/lib/parser/contents/classes/livechat/MarkChatItemAsDeletedAction.js @@ -0,0 +1,14 @@ +'use strict'; + +const Text = require('../Text'); + +class MarkChatItemAsDeletedAction { + type = 'MarkChatItemAsDeletedAction'; + + constructor(data) { + this.deleted_state_message = new Text(data.deletedStateMessage); + this.target_item_id = data.targetItemId; + } +} + +module.exports = MarkChatItemAsDeletedAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/MarkChatItemsByAuthorAsDeletedAction.js b/lib/parser/contents/classes/livechat/MarkChatItemsByAuthorAsDeletedAction.js new file mode 100644 index 00000000..ac0f4d9a --- /dev/null +++ b/lib/parser/contents/classes/livechat/MarkChatItemsByAuthorAsDeletedAction.js @@ -0,0 +1,14 @@ +'use strict'; + +const Text = require('../Text'); + +class MarkChatItemsByAuthorAsDeletedAction { + type = 'MarkChatItemsByAuthorAsDeletedAction'; + + constructor(data) { + this.deleted_state_message = new Text(data.deletedStateMessage); + this.channel_id = data.externalChannelId; + } +} + +module.exports = MarkChatItemsByAuthorAsDeletedAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/ReplaceChatItemAction.js b/lib/parser/contents/classes/livechat/ReplaceChatItemAction.js new file mode 100644 index 00000000..9e6a4d0c --- /dev/null +++ b/lib/parser/contents/classes/livechat/ReplaceChatItemAction.js @@ -0,0 +1,12 @@ +'use strict'; + +const Parser = require('../..'); + +class ReplaceChatItemAction { + constructor(data) { + this.target_item_id = data.targetItemId; + this.replacement_item = Parser.parse(data.replacementItem, 'livechat/items'); + } +} + +module.exports = ReplaceChatItemAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/ReplayChatItemAction.js b/lib/parser/contents/classes/livechat/ReplayChatItemAction.js new file mode 100644 index 00000000..25247879 --- /dev/null +++ b/lib/parser/contents/classes/livechat/ReplayChatItemAction.js @@ -0,0 +1,18 @@ +'use strict'; + +const Parser = require('../..'); + +class ReplayChatItemAction { + type = 'ReplayChatItemAction'; + + constructor(data) { + this.actions = Parser.parse(data.actions?.map((action) => { + delete action.clickTrackingParams; + return action; + }), 'livechat') || []; + + this.video_offset_time_msec = data.videoOffsetTimeMsec; + } +} + +module.exports = ReplayChatItemAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/ShowLiveChatActionPanelAction.js b/lib/parser/contents/classes/livechat/ShowLiveChatActionPanelAction.js new file mode 100644 index 00000000..673c99d0 --- /dev/null +++ b/lib/parser/contents/classes/livechat/ShowLiveChatActionPanelAction.js @@ -0,0 +1,13 @@ +'use strict'; + +const Parser = require('../..'); + +class ShowLiveChatActionPanelAction { + type = 'ShowLiveChatActionPanelAction'; + + constructor(data) { + this.panel_to_show = Parser.parse(data.panelToShow, 'livechat'); + } +} + +module.exports = ShowLiveChatActionPanelAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/ShowLiveChatTooltipCommand.js b/lib/parser/contents/classes/livechat/ShowLiveChatTooltipCommand.js new file mode 100644 index 00000000..8adc9989 --- /dev/null +++ b/lib/parser/contents/classes/livechat/ShowLiveChatTooltipCommand.js @@ -0,0 +1,13 @@ +'use strict'; + +const Parser = require('../..'); + +class ShowLiveChatTooltipCommand { + type = 'ShowLiveChatTooltipCommand'; + + constructor(data) { + this.tooltip = Parser.parse(data.tooltip); + } +} + +module.exports = ShowLiveChatTooltipCommand; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/UpdateDateTextAction.js b/lib/parser/contents/classes/livechat/UpdateDateTextAction.js new file mode 100644 index 00000000..0ff0d1f5 --- /dev/null +++ b/lib/parser/contents/classes/livechat/UpdateDateTextAction.js @@ -0,0 +1,13 @@ +'use strict'; + +const Text = require('../Text'); + +class UpdateDateTextAction { + type = 'UpdateDateTextAction'; + + constructor(data) { + this.date_text = new Text(data.dateText).toString(); + } +} + +module.exports = UpdateDateTextAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/UpdateDescriptionAction.js b/lib/parser/contents/classes/livechat/UpdateDescriptionAction.js new file mode 100644 index 00000000..9a68b10d --- /dev/null +++ b/lib/parser/contents/classes/livechat/UpdateDescriptionAction.js @@ -0,0 +1,13 @@ +'use strict'; + +const Text = require('../Text'); + +class UpdateDescriptionAction { + type = 'UpdateDescriptionAction'; + + constructor(data) { + this.description = new Text(data.description); + } +} + +module.exports = UpdateDescriptionAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/UpdateLiveChatPollAction.js b/lib/parser/contents/classes/livechat/UpdateLiveChatPollAction.js new file mode 100644 index 00000000..54f726bc --- /dev/null +++ b/lib/parser/contents/classes/livechat/UpdateLiveChatPollAction.js @@ -0,0 +1,13 @@ +'use strict'; + +const Parser = require('../..'); + +class UpdateLiveChatPollAction { + type = 'UpdateLiveChatPollAction'; + + constructor(data) { + this.poll_to_update = Parser.parse(data.pollToUpdate, 'livechat/items'); + } +} + +module.exports = UpdateLiveChatPollAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/UpdateTitleAction.js b/lib/parser/contents/classes/livechat/UpdateTitleAction.js new file mode 100644 index 00000000..238623e5 --- /dev/null +++ b/lib/parser/contents/classes/livechat/UpdateTitleAction.js @@ -0,0 +1,13 @@ +'use strict'; + +const Text = require('../Text'); + +class UpdateTitleAction { + type = 'UpdateTitleAction'; + + constructor(data) { + this.title = new Text(data.title); + } +} + +module.exports = UpdateTitleAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/UpdateToggleButtonTextAction.js b/lib/parser/contents/classes/livechat/UpdateToggleButtonTextAction.js new file mode 100644 index 00000000..717994ac --- /dev/null +++ b/lib/parser/contents/classes/livechat/UpdateToggleButtonTextAction.js @@ -0,0 +1,15 @@ +'use strict'; + +const Text = require('../Text'); + +class UpdateToggleButtonTextAction { + type = 'UpdateToggleButtonTextAction'; + + constructor(data) { + this.default_text = new Text(data.defaultText).toString(); + this.toggled_text = new Text(data.toggledText).toString(); + this.button_id = data.buttonId; + } +} + +module.exports = UpdateToggleButtonTextAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/UpdateViewershipAction.js b/lib/parser/contents/classes/livechat/UpdateViewershipAction.js new file mode 100644 index 00000000..8344fca6 --- /dev/null +++ b/lib/parser/contents/classes/livechat/UpdateViewershipAction.js @@ -0,0 +1,17 @@ +'use strict'; + +const Text = require('../Text'); + +class UpdateViewershipAction { + type = 'UpdateViewershipAction'; + + constructor(data) { + const view_count_renderer = data.viewCount.videoViewCountRenderer; + + this.view_count = new Text(view_count_renderer.viewCount); + this.extra_short_view_count = new Text(view_count_renderer.extraShortViewCount); + this.is_live = view_count_renderer.isLive; + } +} + +module.exports = UpdateViewershipAction; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatBanner.js b/lib/parser/contents/classes/livechat/items/LiveChatBanner.js new file mode 100644 index 00000000..c42e598c --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatBanner.js @@ -0,0 +1,19 @@ +'use strict'; + +const Parser = require('../../..'); + +class LiveChatBanner { + type = 'LiveChatBanner'; + + constructor(data) { + this.header = Parser.parse(data.header, 'livechat/items'); + this.contents = Parser.parse(data.contents, 'livechat/items'); + this.action_id = data.actionId; + this.viewer_is_creator = data.viewerIsCreator; + this.target_id = data.targetId; + this.is_stackable = data.isStackable; + this.background_type = data.backgroundType; + } +} + +module.exports = LiveChatBanner; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatBannerHeader.js b/lib/parser/contents/classes/livechat/items/LiveChatBannerHeader.js new file mode 100644 index 00000000..a115cb75 --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatBannerHeader.js @@ -0,0 +1,16 @@ +'use strict'; + +const Parser = require('../../..'); +const Text = require('../../Text'); + +class LiveChatBannerHeader { + type = 'LiveChatBannerHeader'; + + constructor(data) { + this.text = new Text(data.text).toString(); + this.icon_type = data.icon.iconType; + this.context_menu_button = Parser.parse(data.contextMenuButton); + } +} + +module.exports = LiveChatBannerHeader; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatBannerPoll.js b/lib/parser/contents/classes/livechat/items/LiveChatBannerPoll.js new file mode 100644 index 00000000..2bf76bf9 --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatBannerPoll.js @@ -0,0 +1,25 @@ +'use strict'; + +const Parser = require('../../..'); +const Text = require('../../Text'); +const Thumbnail = require('../../Thumbnail'); + +class LiveChatBannerPoll { + type = 'LiveChatBannerPoll'; + + constructor(data) { + this.poll_question = new Text(data.pollQuestion); + this.author_photo = Thumbnail.fromResponse(data.authorPhoto); + + this.choices = data.pollChoices.map((choice) => ({ + option_id: choice.pollOptionId, + text: new Text(choice.text).toString() + })); + + this.collapsed_state_entity_key = data.collapsedStateEntityKey; + this.live_chat_poll_state_entity_key = data.liveChatPollStateEntityKey; + this.context_menu_button = Parser.parse(data.contextMenuButton); + } +} + +module.exports = LiveChatBannerPoll; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatMembershipItem.js b/lib/parser/contents/classes/livechat/items/LiveChatMembershipItem.js new file mode 100644 index 00000000..a95f04fe --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatMembershipItem.js @@ -0,0 +1,27 @@ +'use strict'; + +const Parser = require('../../..'); +const Text = require('../../Text'); +const Thumbnail = require('../../Thumbnail'); +const NavigationEndpoint = require('../../NavigationEndpoint'); + +class LiveChatMembershipItem { + type = 'LiveChatMembershipItem'; + + constructor(data) { + this.id = data.id; + this.timestamp = Math.floor(parseInt(data.timestampUsec) / 1000); + this.header_subtext = new Text(data.headerSubtext); + + this.author = { + id: data.authorExternalChannelId, + name: new Text(data?.authorName), + thumbnails: Thumbnail.fromResponse(data.authorPhoto), + badges: Parser.parse(data.authorBadges) + }; + + this.menu_endpoint = new NavigationEndpoint(data.contextMenuEndpoint); + } +} + +module.exports = LiveChatMembershipItem; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatPaidMessage.js b/lib/parser/contents/classes/livechat/items/LiveChatPaidMessage.js new file mode 100644 index 00000000..cb74a3a7 --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatPaidMessage.js @@ -0,0 +1,37 @@ +'use strict'; + +const Text = require('../../Text'); +const Thumbnail = require('../../Thumbnail'); +const NavigationEndpoint = require('../../NavigationEndpoint'); +const Parser = require('../../..'); + +class LiveChatPaidMessage { + type = 'LiveChatPaidMessage'; + + constructor(data) { + this.message = new Text(data.message); + + this.author = { + id: data.authorExternalChannelId, + name: new Text(data.authorName), + thumbnails: Thumbnail.fromResponse(data.authorPhoto), + badges: Parser.parse(data.authorBadges) + }; + + const badges = Parser.parse(data.authorBadges); + + this.author.badges = badges; + this.author.is_moderator = badges?.some((badge) => badge.icon_type == 'MODERATOR') || null; + this.author.is_verified = badges?.some((badge) => badge.style == 'BADGE_STYLE_TYPE_VERIFIED') || null; + this.author.is_verified_artist = badges?.some((badge) => badge.style == 'BADGE_STYLE_TYPE_VERIFIED_ARTIST') || null; + + this.purchase_amount = new Text(data.purchaseAmountText).toString(); + + this.menu_endpoint = new NavigationEndpoint(data.contextMenuEndpoint); + this.timestamp = Math.floor(parseInt(data.timestampUsec) / 1000); + this.timestamp_text = new Text(data.timestampText).toString(); + this.id = data.id; + } +} + +module.exports = LiveChatPaidMessage; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatPlaceholderItem.js b/lib/parser/contents/classes/livechat/items/LiveChatPlaceholderItem.js new file mode 100644 index 00000000..5c3b6214 --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatPlaceholderItem.js @@ -0,0 +1,12 @@ +'use strict'; + +class LiveChatPlaceholderItem { + type = 'LiveChatPlaceholderItem'; + + constructor(data) { + this.id = data.id; + this.timestamp = Math.floor(parseInt(data.timestampUsec) / 1000); + } +} + +module.exports = LiveChatPlaceholderItem; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatTextMessage.js b/lib/parser/contents/classes/livechat/items/LiveChatTextMessage.js new file mode 100644 index 00000000..9576fe66 --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatTextMessage.js @@ -0,0 +1,34 @@ +'use strict'; + +const Text = require('../../Text'); +const Thumbnail = require('../../Thumbnail'); +const NavigationEndpoint = require('../../NavigationEndpoint'); +const Parser = require('../../..'); + +class LiveChatTextMessage { + type = 'LiveChatTextMessage'; + + constructor(data) { + this.message = new Text(data.message); + + + this.author = { + id: data.authorExternalChannelId, + name: new Text(data.authorName), + thumbnails: Thumbnail.fromResponse(data.authorPhoto), + }; + + const badges = Parser.parse(data.authorBadges); + + this.author.badges = badges; + this.author.is_moderator = badges?.some((badge) => badge.icon_type == 'MODERATOR') || null; + this.author.is_verified = badges?.some((badge) => badge.style == 'BADGE_STYLE_TYPE_VERIFIED') || null; + this.author.is_verified_artist = badges?.some((badge) => badge.style == 'BADGE_STYLE_TYPE_VERIFIED_ARTIST') || null; + + this.menu_endpoint = new NavigationEndpoint(data.contextMenuEndpoint); + this.timestamp = Math.floor(parseInt(data.timestampUsec) / 1000); + this.id = data.id; + } +} + +module.exports = LiveChatTextMessage; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatTickerPaidMessageItem.js b/lib/parser/contents/classes/livechat/items/LiveChatTickerPaidMessageItem.js new file mode 100644 index 00000000..bf2141fa --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatTickerPaidMessageItem.js @@ -0,0 +1,36 @@ +'use strict'; + +const Text = require('../../Text'); +const Thumbnail = require('../../Thumbnail'); +const NavigationEndpoint = require('../../NavigationEndpoint'); +const Parser = require('../../..'); + +class LiveChatTickerPaidMessageItem { + type = 'LiveChatTickerPaidMessageItem'; + + constructor(data) { + this.author = { + id: data.authorExternalChannelId, + thumbnails: Thumbnail.fromResponse(data.authorPhoto), + badges: Parser.parse(data.authorBadges) + }; + + const badges = Parser.parse(data.authorBadges); + + this.author.badges = badges; + this.author.is_moderator = badges?.some((badge) => badge.icon_type == 'MODERATOR') || null; + this.author.is_verified = badges?.some((badge) => badge.style == 'BADGE_STYLE_TYPE_VERIFIED') || null; + this.author.is_verified_artist = badges?.some((badge) => badge.style == 'BADGE_STYLE_TYPE_VERIFIED_ARTIST') || null; + + this.amount = new Text(data.amount); + this.duration_sec = data.durationSec; + this.full_duration_sec = data.fullDurationSec; + + this.show_item = Parser.parse(data.showItemEndpoint.showLiveChatItemEndpoint.renderer, 'livechat/items'); + + this.show_item_endpoint = new NavigationEndpoint(data.showItemEndpoint); + this.id = data.id; + } +} + +module.exports = LiveChatTickerPaidMessageItem; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatTickerSponsorItem.js b/lib/parser/contents/classes/livechat/items/LiveChatTickerSponsorItem.js new file mode 100644 index 00000000..d55796ae --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatTickerSponsorItem.js @@ -0,0 +1,28 @@ +'use strict'; + +// const Parser = require('../../..'); +const Text = require('../../Text'); +const Thumbnail = require('../../Thumbnail'); + +class LiveChatTickerSponsorItem { + type = 'LiveChatTickerSponsorItem'; + + constructor(data) { + this.id = data.id; + this.detail_text = new Text(data.detailText).toString(); + + this.author = { + id: data.authorExternalChannelId, + name: new Text(data?.authorName), + thumbnails: Thumbnail.fromResponse(data.sponsorPhoto), + }; + + this.duration_sec = data.durationSec; + + // TODO: finish this + + // console.log(data) + } +} + +module.exports = LiveChatTickerSponsorItem; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/LiveChatViewerEngagementMessage.js b/lib/parser/contents/classes/livechat/items/LiveChatViewerEngagementMessage.js new file mode 100644 index 00000000..ed90bf18 --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/LiveChatViewerEngagementMessage.js @@ -0,0 +1,20 @@ +'use strict'; + +const LiveChatTextMessage = require('./LiveChatTextMessage'); +const Parser = require('../../..'); + +class LiveChatViewerEngagementMessage extends LiveChatTextMessage { + type = 'LiveChatViewerEngagementMessage'; + + constructor(data) { + super(data); + + delete this.author; + delete this.menu_endpoint; + + this.icon_type = data.icon.iconType; + this.action_button = Parser.parse(data.actionButton); + } +} + +module.exports = LiveChatViewerEngagementMessage; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/Poll.js b/lib/parser/contents/classes/livechat/items/Poll.js new file mode 100644 index 00000000..8d5d8a9e --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/Poll.js @@ -0,0 +1,25 @@ +'use strict'; + +const Parser = require('../../..'); +const Text = require('../../Text'); +const NavigationEndpoint = require('../../NavigationEndpoint'); + +class Poll { + type = 'Poll'; + + constructor(data) { + this.header = Parser.parse(data.header, 'livechat/items'); + + this.choices = data.choices.map((choice) => ({ + text: new Text(choice.text).toString(), + selected: choice.selected, + vote_ratio: choice.voteRatio, + vote_percentage: new Text(choice.votePercentage).toString(), + select_endpoint: new NavigationEndpoint(choice.selectServiceEndpoint) + })); + + this.live_chat_poll_id = data.liveChatPollId; + } +} + +module.exports = Poll; \ No newline at end of file diff --git a/lib/parser/contents/classes/livechat/items/PollHeader.js b/lib/parser/contents/classes/livechat/items/PollHeader.js new file mode 100644 index 00000000..8ca5e72d --- /dev/null +++ b/lib/parser/contents/classes/livechat/items/PollHeader.js @@ -0,0 +1,19 @@ +'use strict'; + +const Text = require('../../Text'); +const Thumbnail = require('../../Thumbnail'); +const Parser = require('../../..'); + +class PollHeader { + type = 'PollHeader'; + + constructor(data) { + this.poll_question = new Text(data.pollQuestion); + this.thumbnails = Thumbnail.fromResponse(data.thumbnail); + this.metadata = new Text(data.metadataText); + this.live_chat_poll_type = data.liveChatPollType; + this.context_menu_button = Parser.parse(data.contextMenuButton); + } +} + +module.exports = PollHeader; \ No newline at end of file diff --git a/lib/parser/contents/index.js b/lib/parser/contents/index.js index c2c93ca8..bf3db6f3 100644 --- a/lib/parser/contents/index.js +++ b/lib/parser/contents/index.js @@ -30,20 +30,74 @@ class SectionListContinuation { } } +class TimedContinuation { + type = 'timedContinuationData'; + + constructor(data) { + this.timeout_ms = data.timeoutMs || data.timeUntilLastMessageMsec; + this.token = data.continuation; + } +} + +class LiveChatContinuation { + type = 'liveChatContinuation'; + + constructor(data) { + this.actions = Parser.parse(data.actions?.map((action) => { + delete action.clickTrackingParams; + return action; + }), 'livechat') || []; + + this.action_panel = Parser.parse(data.actionPanel); + this.item_list = Parser.parse(data.itemList); + this.header = Parser.parse(data.header); + this.participants_list = Parser.parse(data.participantsList); + this.popout_message = Parser.parse(data.popoutMessage); + + this.emojis = data.emojis?.map((emoji) => ({ + emoji_id: emoji.emojiId, + shortcuts: emoji.shortcuts, + search_terms: emoji.searchTerms, + image: emoji.image, + is_custom_emoji: emoji.isCustomEmoji + })) || null; + + this.continuation = new TimedContinuation( + data.continuations?.[0].timedContinuationData || + data.continuations?.[0].invalidationContinuationData || + data.continuations?.[0].liveChatReplayContinuationData); + + this.viewer_name = data.viewerName; + } +} + class Parser { static #memo = new Map(); + static #clearMemo() { Parser.#memo = null; } + static #createMemo() { Parser.#memo = new Map(); } + static #addToMemo(classname, result) { - if (!Parser.#memo) return; - if (!Parser.#memo.has(classname)) return Parser.#memo.set(classname, [result]); + if (!Parser.#memo) + return; + + if (!Parser.#memo.has(classname)) + return Parser.#memo.set(classname, [result]); + Parser.#memo.get(classname).push(result); } + /** + * Parses InnerTube response. + * + * @param {object} data + * @returns {*} + */ static parseResponse(data) { // Memoize the response objects by classname this.#createMemo(); @@ -77,12 +131,17 @@ class Parser { on_response_received_commands, on_response_received_commands_memo, /** @type {*} */ + continuation: data.continuation && Parser.parseC(data.continuation) || null, + /** @type {*} */ continuation_contents: data.continuationContents && Parser.parseLC(data.continuationContents) || null, + actions: data.actions && Parser.parseLA(data.actions), metadata: Parser.parse(data.metadata), header: Parser.parse(data.header), - /** @type {import('./classes/PlayerMicroformat')} **/ + /** @type {import('./classes/PlayerMicroformat')} */ microformat: data.microformat && Parser.parse(data.microformat), + /** @type {import('./classes/PlaylistSidebar')} */ sidebar: Parser.parse(data.sidebar), + /** @type {import('./classes/PlayerOverlay')} */ overlay: Parser.parse(data.overlay), refinements: data.refinements || null, estimated_results: data.estimatedResults || null, @@ -106,6 +165,7 @@ class Parser { dls_manifest_url: data.streamingData?.dashManifestUrl || null, }, captions: Parser.parse(data.captions), + /** @type {import('./classes/VideoDetails')} */ video_details: data.videoDetails && new VideoDetails(data.videoDetails), annotations: Parser.parse(data.annotations), storyboards: Parser.parse(data.storyboards), @@ -116,9 +176,16 @@ class Parser { } } + static parseC(data) { + if (data.timedContinuationData) + return new TimedContinuation(data.timedContinuationData); + } + static parseLC(data) { if (data.sectionListContinuation) return new SectionListContinuation(data.sectionListContinuation); + if (data.liveChatContinuation) + return new LiveChatContinuation(data.liveChatContinuation); } static parseRR(actions) { @@ -130,11 +197,29 @@ class Parser { }).filter((item) => item)); } + static parseLA(data) { + if (Array.isArray(data)) { + return Parser.parse(data.map((action) => { + delete action.clickTrackingParams; + return action; + }), 'livechat'); + } + + return Parser.parse(data) || null; + } + static parseFormats(formats) { return observe(formats?.map((format) => new Format(format)) || []); } - static parse(data) { + /** + * Parses the `contents` property of the response. + * + * @param {object} data + * @param {string} module + * @returns {*} + */ + static parse(data, module) { if (!data) return null; @@ -147,8 +232,11 @@ class Parser { if (!this.shouldIgnore(classname)) { try { - const TargetClass = require('./classes/' + classname); + const path = module && module + '/' || ''; + + const TargetClass = require('./classes/' + path + classname); const result = new TargetClass(item[keys[0]]); + results.push(result); this.#addToMemo(classname, result); } catch (err) { @@ -164,9 +252,13 @@ class Parser { if (!this.shouldIgnore(classname)) { try { - const TargetClass = require('./classes/' + classname); + const path = module && module + '/' || ''; + + const TargetClass = require('./classes/' + path + classname); const result = new TargetClass(data[keys[0]]); + this.#addToMemo(classname, result); + return result; } catch (err) { this.formatError({ classname, classdata: data[keys[0]], err }); @@ -177,18 +269,19 @@ class Parser { } static formatError({ classname, classdata, err }) { - if (err.code == 'MODULE_NOT_FOUND') - console.warn( + if (err.code == 'MODULE_NOT_FOUND') { + return console.warn( new InnertubeError(classname + ' not found!\n' + 'This is a bug, please report it at ' + require('../../../package.json').bugs.url, classdata) ); - else - console.warn( - new InnertubeError('Something went wrong at ' + classname + '!\n' + - 'This is a bug, please report it at ' + require('../../../package.json').bugs.url, - { stack: err.stack }) - ); + } + + console.warn( + new InnertubeError('Something went wrong at ' + classname + '!\n' + + 'This is a bug, please report it at ' + require('../../../package.json').bugs.url, + { stack: err.stack }) + ); } static sanitizeClassName(input) { @@ -201,7 +294,8 @@ class Parser { return [ 'DisplayAd', 'MealbarPromo', - 'PromotedSparklesWeb' + 'PromotedSparklesWeb', + 'RunAttestationCommand' ].includes(classname); } } diff --git a/lib/parser/youtube/LiveChat.js b/lib/parser/youtube/LiveChat.js new file mode 100644 index 00000000..b266003b --- /dev/null +++ b/lib/parser/youtube/LiveChat.js @@ -0,0 +1,164 @@ +'use strict'; + +const Parser = require('../contents'); +const EventEmitter = require('events'); + +class LiveChat { + ev; + + #actions; + #video_info; + #continuation; + #mcontinuation; + + #lc_polling_interval_ms = 1000; + #md_polling_interval_ms = 5000; + + initial_info; + live_metadata; + + running = false; + is_replay = false; + + /** + * @param {import('./VideoInfo')} video_info + */ + constructor(video_info) { + this.#video_info = video_info; + this.#actions = video_info.actions; + this.#continuation = this.#video_info.livechat.continuation; + this.is_replay = this.#video_info.livechat.is_replay; + + this.live_metadata = { + /** @type {import('../contents/classes/livechat/metadata/UpdateTitleAction')} */ + title: null, + /** @type {import('../contents/classes/livechat/metadata/UpdateDescriptionAction')} */ + description: null, + /** @type {import('../contents/classes/livechat/metadata/UpdateViewershipAction')} */ + views: null, + /** @type {import('../contents/classes/livechat/metadata/UpdateTitleAction')} */ + likes: null, + /** @type {import('../contents/classes/livechat/metadata/UpdateDateTextAction')} */ + date: null + }; + + this.ev = new EventEmitter(); + } + + start() { + if (!this.running) { + this.running = true; + this.#pollLivechat(); + this.#pollMetadata(); + } + } + + stop() { + this.running = false; + } + + #pollLivechat() { + const lc_poller = setTimeout(() => { + (async () => { + const endpoint = this.is_replay ? 'live_chat/get_live_chat_replay': 'live_chat/get_live_chat'; + const response = await this.#actions.livechat(endpoint, { ctoken: this.#continuation }); + + const data = Parser.parseResponse(response.data); + const contents = data.continuation_contents; + + this.#continuation = contents.continuation.token; + this.#lc_polling_interval_ms = contents.continuation.timeout_ms; + + // Header only exists in the first request + if (contents.header) { + this.initial_info = contents; + this.ev.emit('start', contents); + } else { + await this.#emitSmoothedActions(contents.actions); + } + + clearTimeout(lc_poller); + + this.running && this.#pollLivechat(); + })().catch((err) => Promise.reject(err)); + }, this.#lc_polling_interval_ms); + } + + /** + * Ensures actions are emitted at the right speed. + * This was adapted from YouTube's compiled code (Android). + * @param {object} actions + */ + async #emitSmoothedActions(actions) { + let base = 1E4; + let delay = actions.length < base / 80 ? 1: 0; + + const emit_delay_ms = + delay == 1 ? ( + delay = base / actions.length, + delay *= Math.random() + 0.5, + delay = Math.min(1E3, delay), + delay = Math.max(80, delay) + ): delay = 80; + + for (const action of actions) { + await this.#wait(emit_delay_ms); + this.ev.emit('chat-update', action); + } + } + + #pollMetadata() { + const md_poller = setTimeout(() => { + (async () => { + const payload = { video_id: this.#video_info.basic_info.id }; + + this.#mcontinuation && + (payload.ctoken = this.#mcontinuation); + + const response = await this.#actions.livechat('updated_metadata', payload); + const data = Parser.parseResponse(response.data); + + this.#mcontinuation = data.continuation.token; + this.#md_polling_interval_ms = data.continuation.timeout_ms; + + this.metadata = { + title: data.actions.get({ type: 'UpdateTitleAction' }) || this.metadata?.title, + description: data.actions.get({ type: 'UpdateDescriptionAction' }) || this.metadata?.description, + views: data.actions.get({ type: 'UpdateViewershipAction' }) || this.metadata?.views, + likes: data.actions.get({ type: 'UpdateToggleButtonTextAction' }) || this.metadata?.likes, + date: data.actions.get({ type: 'UpdateDateTextAction' }) || this.metadata?.date + }; + + this.ev.emit('metadata-update', this.metadata); + + clearTimeout(md_poller); + + this.running && this.#pollMetadata(); + })().catch((err) => Promise.reject(err)); + }, this.#md_polling_interval_ms); + } + + /** + * Sends a message. + * @param {string} text + * @returns {Promise.} + */ + async sendMessage(text) { + const response = await this.#actions.livechat('live_chat/send_message', { + text, + ... { + video_id: this.#video_info.basic_info.id, + channel_id: this.#video_info.basic_info.channel_id + } + }); + + const data = Parser.parseResponse(response.data); + return data.actions; + } + + async #wait(ms) { + return new Promise((resolve) => setTimeout(() => resolve(), ms)); + } +} + +module.exports = LiveChat; \ No newline at end of file diff --git a/lib/parser/youtube/VideoInfo.js b/lib/parser/youtube/VideoInfo.js index 63e000f2..4e46ca0a 100644 --- a/lib/parser/youtube/VideoInfo.js +++ b/lib/parser/youtube/VideoInfo.js @@ -1,9 +1,11 @@ 'use strict'; -const Parser = require('../contents'); const { InnertubeError } = require('../../utils/Utils'); const { PassThrough } = require('stream'); + const Axios = require('axios'); +const Parser = require('../contents'); +const LiveChat = require('./LiveChat'); const Constants = require('../../utils/Constants'); const CancelToken = Axios.CancelToken; @@ -217,12 +219,28 @@ class VideoInfo { return response; } - + + /** + * Retrieves Live Chat if available. + * @param {string} [mode] - livechat mode + * @returns {Promise.} + */ + async getLiveChat(mode) { + if (!this.livechat) + throw new InnertubeError('Live Chat is not available', { video_id: this.id }); + + return new LiveChat(this, mode); + } + /** @type {string[]} */ get filters() { return this.related_chip_cloud?.chips.map((chip) => chip.text.toString()) || []; } - + + get actions() { + return this.#actions; + } + get page() { return this.#page; } @@ -236,11 +254,15 @@ class VideoInfo { */ const metadata = this.secondary_info.metadata; if (!metadata) return []; + const songs = []; + let current_song = {}; let is_music_section = false; + for (let i = 0; i < metadata.rows.length; i++) { const row = metadata.rows[i]; + if (row.type === 'MetadataRowHeader') { if (row.content.toString().toLowerCase().startsWith('music')) { is_music_section = true; @@ -248,14 +270,19 @@ class VideoInfo { } continue; } + if (!is_music_section) continue; + current_song[row.title.toString().toLowerCase().replace(/ /g, '_')] = row.contents; + if (row.has_divider_line) { songs.push(current_song); current_song = {}; } } + if (is_music_section) songs.push(current_song); + return songs; } @@ -267,9 +294,13 @@ class VideoInfo { const requires_audio = options.type.includes('audio'); const requires_video = options.type.includes('video'); + let best_width = -1; + const is_best = ['best','bestefficiency'].includes(options.quality); + const use_most_efficient = options.quality !== 'best'; + let candidates = formats.filter(format => { if (requires_audio && !format.has_audio) return false; @@ -300,12 +331,13 @@ class VideoInfo { } } - if (use_most_efficient) + if (use_most_efficient) { // sort by bitrate (lower is better) candidates.sort((a, b) => a.bitrate - b.bitrate); - else + } else { // sort by bitrate (higher is better) candidates.sort((a, b) => b.bitrate - a.bitrate); + } return candidates[0]; } @@ -356,7 +388,7 @@ class VideoInfo { }).catch((error) => error); if (response instanceof Error) { - stream.emit('error', { message: response.message, type: 'REQUEST_FAILED' }); + stream.emit('error', new InnertubeError(response.message, { type: 'REQUEST_FAILED' })); return stream; } else { stream.emit('start'); @@ -366,6 +398,7 @@ class VideoInfo { response.data.on('data', (chunk) => { downloaded_size += chunk.length; + let size = (response.headers['content-length'] / 1024 / 1024).toFixed(2); let percentage = Math.floor((downloaded_size / response.headers['content-length']) * 100); @@ -384,8 +417,8 @@ class VideoInfo { response.data.on('error', (err) => { cancelled && - stream.emit('error', { message: 'The download was cancelled.', type: 'DOWNLOAD_CANCELLED' }) || - stream.emit('error', { message: err.message, type: 'DOWNLOAD_ABORTED' }); + stream.emit('error', new InnertubeError('The download was cancelled.', { type: 'DOWNLOAD_CANCELLED' })) || + stream.emit('error', new InnertubeError(err.message, { type: 'DOWNLOAD_ABORTED' })); }); response.data.pipe(stream, { end: true }); diff --git a/package-lock.json b/package-lock.json index f2a4d79b..12e8de88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "youtubei.js", - "version": "1.4.3", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "youtubei.js", - "version": "1.4.3", + "version": "2.0.0", "license": "MIT", "dependencies": { "axios": "^0.21.4", @@ -43,42 +43,42 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", - "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.6.tgz", + "integrity": "sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", - "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.6.tgz", + "integrity": "sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-compilation-targets": "^7.18.2", - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helpers": "^7.18.2", - "@babel/parser": "^7.18.5", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.5", - "@babel/types": "^7.18.4", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.6", + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helpers": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -103,13 +103,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", - "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz", + "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==", "dev": true, "dependencies": { - "@babel/types": "^7.18.2", - "@jridgewell/gen-mapping": "^0.3.0", + "@babel/types": "^7.18.7", + "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, "engines": { @@ -117,12 +117,12 @@ } }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", - "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", + "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" }, @@ -131,13 +131,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", - "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz", + "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", + "@babel/compat-data": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.20.2", "semver": "^6.3.0" }, @@ -158,142 +158,142 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", - "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz", + "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz", + "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==", "dev": true, "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", - "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz", + "integrity": "sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.0", - "@babel/types": "^7.18.0" + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", - "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz", + "integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", - "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, "dependencies": { - "@babel/types": "^7.18.2" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", - "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.6.tgz", + "integrity": "sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ==", "dev": true, "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2" + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", - "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -373,9 +373,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", - "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.6.tgz", + "integrity": "sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -532,12 +532,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz", - "integrity": "sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -547,33 +547,33 @@ } }, "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", + "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", - "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz", + "integrity": "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-environment-visitor": "^7.18.2", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.18.5", - "@babel/types": "^7.18.4", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -591,12 +591,12 @@ } }, "node_modules/@babel/types": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", - "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.7.tgz", + "integrity": "sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" }, "engines": { @@ -737,15 +737,15 @@ } }, "node_modules/@jest/core": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.1.tgz", - "integrity": "sha512-3pYsBoZZ42tXMdlcFeCc/0j9kOlK7MYuXs2B1QbvDgMoW1K9NJ4G/VYvIbMb26iqlkTfPHo7SC2JgjDOk/mxXw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.2.tgz", + "integrity": "sha512-Xo4E+Sb/nZODMGOPt2G3cMmCBqL4/W2Ijwr7/mrXlq4jdJwcFQ/9KrrJZT2adQRk2otVBXXOz1GRQ4Z5iOgvRQ==", "dev": true, "dependencies": { "@jest/console": "^28.1.1", - "@jest/reporters": "^28.1.1", + "@jest/reporters": "^28.1.2", "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", "@types/node": "*", "ansi-escapes": "^4.2.1", @@ -754,15 +754,15 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^28.0.2", - "jest-config": "^28.1.1", + "jest-config": "^28.1.2", "jest-haste-map": "^28.1.1", "jest-message-util": "^28.1.1", "jest-regex-util": "^28.0.2", "jest-resolve": "^28.1.1", - "jest-resolve-dependencies": "^28.1.1", - "jest-runner": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-snapshot": "^28.1.1", + "jest-resolve-dependencies": "^28.1.2", + "jest-runner": "^28.1.2", + "jest-runtime": "^28.1.2", + "jest-snapshot": "^28.1.2", "jest-util": "^28.1.1", "jest-validate": "^28.1.1", "jest-watcher": "^28.1.1", @@ -785,12 +785,12 @@ } }, "node_modules/@jest/environment": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.1.tgz", - "integrity": "sha512-9auVQ2GzQ7nrU+lAr8KyY838YahElTX9HVjbQPPS2XjlxQ+na18G113OoBhyBGBtD6ZnO/SrUy5WR8EzOj1/Uw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.2.tgz", + "integrity": "sha512-I0CR1RUMmOzd0tRpz10oUfaChBWs+/Hrvn5xYhMEF/ZqrDaaeHwS8yDBqEWCrEnkH2g+WE/6g90oBv3nKpcm8Q==", "dev": true, "dependencies": { - "@jest/fake-timers": "^28.1.1", + "@jest/fake-timers": "^28.1.2", "@jest/types": "^28.1.1", "@types/node": "*", "jest-mock": "^28.1.1" @@ -800,13 +800,13 @@ } }, "node_modules/@jest/expect": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.1.tgz", - "integrity": "sha512-/+tQprrFoT6lfkMj4mW/mUIfAmmk/+iQPmg7mLDIFOf2lyf7EBHaS+x3RbeR0VZVMe55IvX7QRoT/2aK3AuUXg==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.2.tgz", + "integrity": "sha512-HBzyZBeFBiOelNbBKN0pilWbbrGvwDUwAqMC46NVJmWm8AVkuE58NbG1s7DR4cxFt4U5cVLxofAoHxgvC5MyOw==", "dev": true, "dependencies": { "expect": "^28.1.1", - "jest-snapshot": "^28.1.1" + "jest-snapshot": "^28.1.2" }, "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" @@ -825,13 +825,13 @@ } }, "node_modules/@jest/fake-timers": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.1.tgz", - "integrity": "sha512-BY/3+TyLs5+q87rGWrGUY5f8e8uC3LsVHS9Diz8+FV3ARXL4sNnkLlIB8dvDvRrp+LUCGM+DLqlsYubizGUjIA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.2.tgz", + "integrity": "sha512-xSYEI7Y0D5FbZN2LsCUj/EKRR1zfQYmGuAUVh6xTqhx7V5JhjgMcK5Pa0iR6WIk0GXiHDe0Ke4A+yERKE9saqg==", "dev": true, "dependencies": { "@jest/types": "^28.1.1", - "@sinonjs/fake-timers": "^9.1.1", + "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", "jest-message-util": "^28.1.1", "jest-mock": "^28.1.1", @@ -842,13 +842,13 @@ } }, "node_modules/@jest/globals": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.1.tgz", - "integrity": "sha512-dEgl/6v7ToB4vXItdvcltJBgny0xBE6xy6IYQrPJAJggdEinGxCDMivNv7sFzPcTITGquXD6UJwYxfJ/5ZwDSg==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.2.tgz", + "integrity": "sha512-cz0lkJVDOtDaYhvT3Fv2U1B6FtBnV+OpEyJCzTHM1fdoTsU4QNLAt/H4RkiwEUU+dL4g/MFsoTuHeT2pvbo4Hg==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.1", - "@jest/expect": "^28.1.1", + "@jest/environment": "^28.1.2", + "@jest/expect": "^28.1.2", "@jest/types": "^28.1.1" }, "engines": { @@ -856,17 +856,17 @@ } }, "node_modules/@jest/reporters": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.1.tgz", - "integrity": "sha512-597Zj4D4d88sZrzM4atEGLuO7SdA/YrOv9SRXHXRNC+/FwPCWxZhBAEzhXoiJzfRwn8zes/EjS8Lo6DouGN5Gg==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.2.tgz", + "integrity": "sha512-/whGLhiwAqeCTmQEouSigUZJPVl7sW8V26EiboImL+UyXznnr1a03/YZ2BX8OlFw0n+Zlwu+EZAITZtaeRTxyA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^28.1.1", "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.13", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -885,7 +885,7 @@ "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^9.0.0" + "v8-to-istanbul": "^9.0.1" }, "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" @@ -912,12 +912,12 @@ } }, "node_modules/@jest/source-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.0.2.tgz", - "integrity": "sha512-Y9dxC8ZpN3kImkk0LkK5XCEneYMAXlZ8m5bflmSL5vrwyeUpJfentacCUg6fOb8NOpOO7hz2+l37MV77T6BFPw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", + "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.13", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, @@ -956,14 +956,14 @@ } }, "node_modules/@jest/transform": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.1.tgz", - "integrity": "sha512-PkfaTUuvjUarl1EDr5ZQcCA++oXkFCP9QFUkG0yVKVmNObjhrqDy0kbMpMebfHWm3CCDHjYNem9eUSH8suVNHQ==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.2.tgz", + "integrity": "sha512-3o+lKF6iweLeJFHBlMJysdaPbpoMmtbHEFsjzSv37HIq/wWt5ijTeO2Yf7MO5yyczCopD507cNwNLeX8Y/CuIg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^28.1.1", - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.13", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", @@ -1012,33 +1012,33 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", - "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", + "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", - "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", - "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", - "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -1292,12 +1292,12 @@ } }, "node_modules/babel-jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.1.tgz", - "integrity": "sha512-MEt0263viUdAkTq5D7upHPNxvt4n9uLUGa6pPz3WviNBMtOmStb1lIXS3QobnoqM+qnH+vr4EKlvhe8QcmxIYw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.2.tgz", + "integrity": "sha512-pfmoo6sh4L/+5/G2OOfQrGJgvH7fTa1oChnuYH2G/6gA+JwDvO8PELwvwnofKBMNrQsam0Wy/Rw+QSrBNewq2Q==", "dev": true, "dependencies": { - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^28.1.1", @@ -1411,9 +1411,9 @@ } }, "node_modules/browserslist": { - "version": "4.20.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz", - "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz", + "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==", "dev": true, "funding": [ { @@ -1426,11 +1426,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001349", - "electron-to-chromium": "^1.4.147", - "escalade": "^3.1.1", + "caniuse-lite": "^1.0.30001359", + "electron-to-chromium": "^1.4.172", "node-releases": "^2.0.5", - "picocolors": "^1.0.0" + "update-browserslist-db": "^1.0.4" }, "bin": { "browserslist": "cli.js" @@ -1473,9 +1472,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001358", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001358.tgz", - "integrity": "sha512-hvp8PSRymk85R20bsDra7ZTCpSVGN/PAz9pSAjPSjKC+rNmnUk5vCRgJwiTT/O4feQ/yu/drvZYpKxxhbFuChw==", + "version": "1.0.30001361", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001361.tgz", + "integrity": "sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ==", "dev": true, "funding": [ { @@ -1706,9 +1705,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.163", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.163.tgz", - "integrity": "sha512-c9q94pUVqIdc8hyr7jZDB4bNEoNF3QJ7y35lnddMD+mXtiv5GsL1bT/RmfW/KEOmvlNg5Oy1qioiy4tA7e864Q==", + "version": "1.4.173", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.173.tgz", + "integrity": "sha512-Qo3LnVW6JRNhD32viSdPebxKI7K+3WeBDjU1+Q2yZS83zAh8C2LyPpzTimlciv6U74KpY9n/0ESAhUByRke0jw==", "dev": true }, "node_modules/emittery": { @@ -2084,9 +2083,9 @@ } }, "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", + "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", "dev": true }, "node_modules/follow-redirects": { @@ -2497,15 +2496,15 @@ } }, "node_modules/jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.1.tgz", - "integrity": "sha512-qw9YHBnjt6TCbIDMPMpJZqf9E12rh6869iZaN08/vpOGgHJSAaLLUn6H8W3IAEuy34Ls3rct064mZLETkxJ2XA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.2.tgz", + "integrity": "sha512-Tuf05DwLeCh2cfWCQbcz9UxldoDyiR1E9Igaei5khjonKncYdc6LDfynKCEWozK0oLE3GD+xKAo2u8x/0s6GOg==", "dev": true, "dependencies": { - "@jest/core": "^28.1.1", + "@jest/core": "^28.1.2", "@jest/types": "^28.1.1", "import-local": "^3.0.2", - "jest-cli": "^28.1.1" + "jest-cli": "^28.1.2" }, "bin": { "jest": "bin/jest.js" @@ -2536,13 +2535,13 @@ } }, "node_modules/jest-circus": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.1.tgz", - "integrity": "sha512-75+BBVTsL4+p2w198DQpCeyh1RdaS2lhEG87HkaFX/UG0gJExVq2skG2pT7XZEGBubNj2CytcWSPan4QEPNosw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.2.tgz", + "integrity": "sha512-E2vdPIJG5/69EMpslFhaA46WkcrN74LI5V/cSJ59L7uS8UNoXbzTxmwhpi9XrIL3zqvMt5T0pl5k2l2u2GwBNQ==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.1", - "@jest/expect": "^28.1.1", + "@jest/environment": "^28.1.2", + "@jest/expect": "^28.1.2", "@jest/test-result": "^28.1.1", "@jest/types": "^28.1.1", "@types/node": "*", @@ -2553,8 +2552,8 @@ "jest-each": "^28.1.1", "jest-matcher-utils": "^28.1.1", "jest-message-util": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-snapshot": "^28.1.1", + "jest-runtime": "^28.1.2", + "jest-snapshot": "^28.1.2", "jest-util": "^28.1.1", "pretty-format": "^28.1.1", "slash": "^3.0.0", @@ -2566,19 +2565,19 @@ } }, "node_modules/jest-cli": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.1.tgz", - "integrity": "sha512-+sUfVbJqb1OjBZ0OdBbI6OWfYM1i7bSfzYy6gze1F1w3OKWq8ZTEKkZ8a7ZQPq6G/G1qMh/uKqpdWhgl11NFQQ==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.2.tgz", + "integrity": "sha512-l6eoi5Do/IJUXAFL9qRmDiFpBeEJAnjJb1dcd9i/VWfVWbp3mJhuH50dNtX67Ali4Ecvt4eBkWb4hXhPHkAZTw==", "dev": true, "dependencies": { - "@jest/core": "^28.1.1", + "@jest/core": "^28.1.2", "@jest/test-result": "^28.1.1", "@jest/types": "^28.1.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^28.1.1", + "jest-config": "^28.1.2", "jest-util": "^28.1.1", "jest-validate": "^28.1.1", "prompts": "^2.0.1", @@ -2600,26 +2599,26 @@ } }, "node_modules/jest-config": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.1.tgz", - "integrity": "sha512-tASynMhS+jVV85zKvjfbJ8nUyJS/jUSYZ5KQxLUN2ZCvcQc/OmhQl2j6VEL3ezQkNofxn5pQ3SPYWPHb0unTZA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.2.tgz", + "integrity": "sha512-g6EfeRqddVbjPVBVY4JWpUY4IvQoFRIZcv4V36QkqzE0IGhEC/VkugFeBMAeUE7PRgC8KJF0yvJNDeQRbamEVA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^28.1.1", "@jest/types": "^28.1.1", - "babel-jest": "^28.1.1", + "babel-jest": "^28.1.2", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^28.1.1", - "jest-environment-node": "^28.1.1", + "jest-circus": "^28.1.2", + "jest-environment-node": "^28.1.2", "jest-get-type": "^28.0.2", "jest-regex-util": "^28.0.2", "jest-resolve": "^28.1.1", - "jest-runner": "^28.1.1", + "jest-runner": "^28.1.2", "jest-util": "^28.1.1", "jest-validate": "^28.1.1", "micromatch": "^4.0.4", @@ -2688,13 +2687,13 @@ } }, "node_modules/jest-environment-node": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.1.tgz", - "integrity": "sha512-2aV/eeY/WNgUUJrrkDJ3cFEigjC5fqT1+fCclrY6paqJ5zVPoM//sHmfgUUp7WLYxIdbPwMiVIzejpN56MxnNA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.2.tgz", + "integrity": "sha512-oYsZz9Qw27XKmOgTtnl0jW7VplJkN2oeof+SwAwKFQacq3CLlG9u4kTGuuLWfvu3J7bVutWlrbEQMOCL/jughw==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.1", - "@jest/fake-timers": "^28.1.1", + "@jest/environment": "^28.1.2", + "@jest/fake-timers": "^28.1.2", "@jest/types": "^28.1.1", "@types/node": "*", "jest-mock": "^28.1.1", @@ -2846,40 +2845,40 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.1.tgz", - "integrity": "sha512-p8Y150xYJth4EXhOuB8FzmS9r8IGLEioiaetgdNGb9VHka4fl0zqWlVe4v7mSkYOuEUg2uB61iE+zySDgrOmgQ==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.2.tgz", + "integrity": "sha512-OXw4vbOZuyRTBi3tapWBqdyodU+T33ww5cPZORuTWkg+Y8lmsxQlVu3MWtJh6NMlKRTHQetF96yGPv01Ye7Mbg==", "dev": true, "dependencies": { "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.1.1" + "jest-snapshot": "^28.1.2" }, "engines": { "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, "node_modules/jest-runner": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.1.tgz", - "integrity": "sha512-W5oFUiDBgTsCloTAj6q95wEvYDB0pxIhY6bc5F26OucnwBN+K58xGTGbliSMI4ChQal5eANDF+xvELaYkJxTmA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.2.tgz", + "integrity": "sha512-6/k3DlAsAEr5VcptCMdhtRhOoYClZQmxnVMZvZ/quvPGRpN7OBQYPIC32tWSgOnbgqLXNs5RAniC+nkdFZpD4A==", "dev": true, "dependencies": { "@jest/console": "^28.1.1", - "@jest/environment": "^28.1.1", + "@jest/environment": "^28.1.2", "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.10.2", "graceful-fs": "^4.2.9", "jest-docblock": "^28.1.1", - "jest-environment-node": "^28.1.1", + "jest-environment-node": "^28.1.2", "jest-haste-map": "^28.1.1", "jest-leak-detector": "^28.1.1", "jest-message-util": "^28.1.1", "jest-resolve": "^28.1.1", - "jest-runtime": "^28.1.1", + "jest-runtime": "^28.1.2", "jest-util": "^28.1.1", "jest-watcher": "^28.1.1", "jest-worker": "^28.1.1", @@ -2891,17 +2890,17 @@ } }, "node_modules/jest-runtime": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.1.tgz", - "integrity": "sha512-J89qEJWW0leOsqyi0D9zHpFEYHwwafFdS9xgvhFHtIdRghbadodI0eA+DrthK/1PebBv3Px8mFSMGKrtaVnleg==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.2.tgz", + "integrity": "sha512-i4w93OsWzLOeMXSi9epmakb2+3z0AchZtUQVF1hesBmcQQy4vtaql5YdVe9KexdJaVRyPDw8DoBR0j3lYsZVYw==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.1", - "@jest/fake-timers": "^28.1.1", - "@jest/globals": "^28.1.1", - "@jest/source-map": "^28.0.2", + "@jest/environment": "^28.1.2", + "@jest/fake-timers": "^28.1.2", + "@jest/globals": "^28.1.2", + "@jest/source-map": "^28.1.2", "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", @@ -2914,7 +2913,7 @@ "jest-mock": "^28.1.1", "jest-regex-util": "^28.0.2", "jest-resolve": "^28.1.1", - "jest-snapshot": "^28.1.1", + "jest-snapshot": "^28.1.2", "jest-util": "^28.1.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" @@ -2924,9 +2923,9 @@ } }, "node_modules/jest-snapshot": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.1.tgz", - "integrity": "sha512-1KjqHJ98adRcbIdMizjF5DipwZFbvxym/kFO4g4fVZCZRxH/dqV8TiBFCa6rqic3p0karsy8RWS1y4E07b7P0A==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.2.tgz", + "integrity": "sha512-wzrieFttZYfLvrCVRJxX+jwML2YTArOUqFpCoSVy1QUapx+LlV9uLbV/mMEhYj4t7aMeE9aSQFHSvV/oNoDAMA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -2935,7 +2934,7 @@ "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", "@jest/expect-utils": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", @@ -4027,6 +4026,32 @@ "underscore": "*" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4037,9 +4062,9 @@ } }, "node_modules/user-agents": { - "version": "1.0.1054", - "resolved": "https://registry.npmjs.org/user-agents/-/user-agents-1.0.1054.tgz", - "integrity": "sha512-dx1LbJEysVY/W4nPdIPnYlQTHMaJHKhtTGRzD46FrgzwwjzioFMb2dcHGKCyoH76Tp7alsgu4YcMDAZLNCd1qg==", + "version": "1.0.1062", + "resolved": "https://registry.npmjs.org/user-agents/-/user-agents-1.0.1062.tgz", + "integrity": "sha512-dVlTNLHEaw+s/s+ysHo+eX7vackyQDBiunzA7soAI2gbaWMRlOjLZoy4mfhrb+fJo5kYD183glY91H7vUrowzg==", "dependencies": { "dot-json": "^1.2.2", "lodash.clonedeep": "^4.5.0" @@ -4202,36 +4227,36 @@ } }, "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "requires": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", - "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.6.tgz", + "integrity": "sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ==", "dev": true }, "@babel/core": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", - "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.6.tgz", + "integrity": "sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-compilation-targets": "^7.18.2", - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helpers": "^7.18.2", - "@babel/parser": "^7.18.5", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.5", - "@babel/types": "^7.18.4", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.6", + "@babel/helper-compilation-targets": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helpers": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -4248,23 +4273,23 @@ } }, "@babel/generator": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", - "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz", + "integrity": "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==", "dev": true, "requires": { - "@babel/types": "^7.18.2", - "@jridgewell/gen-mapping": "^0.3.0", + "@babel/types": "^7.18.7", + "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, "dependencies": { "@jridgewell/gen-mapping": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", - "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.0", + "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.9" } @@ -4272,13 +4297,13 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", - "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz", + "integrity": "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==", "dev": true, "requires": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", + "@babel/compat-data": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.20.2", "semver": "^6.3.0" }, @@ -4292,109 +4317,109 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", - "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz", + "integrity": "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==", "dev": true }, "@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz", + "integrity": "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==", "dev": true, "requires": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.6" } }, "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-module-transforms": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", - "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz", + "integrity": "sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.0", - "@babel/types": "^7.18.0" + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" } }, "@babel/helper-plugin-utils": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", - "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz", + "integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==", "dev": true }, "@babel/helper-simple-access": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", - "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, "requires": { - "@babel/types": "^7.18.2" + "@babel/types": "^7.18.6" } }, "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true }, "@babel/helpers": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", - "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.6.tgz", + "integrity": "sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ==", "dev": true, "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2" + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.6", + "@babel/types": "^7.18.6" } }, "@babel/highlight": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", - "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -4458,9 +4483,9 @@ } }, "@babel/parser": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", - "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.6.tgz", + "integrity": "sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -4572,39 +4597,39 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz", - "integrity": "sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.17.12" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", + "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", "dev": true, "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6" } }, "@babel/traverse": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", - "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz", + "integrity": "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==", "dev": true, "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-environment-visitor": "^7.18.2", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.18.5", - "@babel/types": "^7.18.4", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-function-name": "^7.18.6", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -4618,12 +4643,12 @@ } }, "@babel/types": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", - "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "version": "7.18.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.7.tgz", + "integrity": "sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" } }, @@ -4739,15 +4764,15 @@ } }, "@jest/core": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.1.tgz", - "integrity": "sha512-3pYsBoZZ42tXMdlcFeCc/0j9kOlK7MYuXs2B1QbvDgMoW1K9NJ4G/VYvIbMb26iqlkTfPHo7SC2JgjDOk/mxXw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.2.tgz", + "integrity": "sha512-Xo4E+Sb/nZODMGOPt2G3cMmCBqL4/W2Ijwr7/mrXlq4jdJwcFQ/9KrrJZT2adQRk2otVBXXOz1GRQ4Z5iOgvRQ==", "dev": true, "requires": { "@jest/console": "^28.1.1", - "@jest/reporters": "^28.1.1", + "@jest/reporters": "^28.1.2", "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", "@types/node": "*", "ansi-escapes": "^4.2.1", @@ -4756,15 +4781,15 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^28.0.2", - "jest-config": "^28.1.1", + "jest-config": "^28.1.2", "jest-haste-map": "^28.1.1", "jest-message-util": "^28.1.1", "jest-regex-util": "^28.0.2", "jest-resolve": "^28.1.1", - "jest-resolve-dependencies": "^28.1.1", - "jest-runner": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-snapshot": "^28.1.1", + "jest-resolve-dependencies": "^28.1.2", + "jest-runner": "^28.1.2", + "jest-runtime": "^28.1.2", + "jest-snapshot": "^28.1.2", "jest-util": "^28.1.1", "jest-validate": "^28.1.1", "jest-watcher": "^28.1.1", @@ -4776,25 +4801,25 @@ } }, "@jest/environment": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.1.tgz", - "integrity": "sha512-9auVQ2GzQ7nrU+lAr8KyY838YahElTX9HVjbQPPS2XjlxQ+na18G113OoBhyBGBtD6ZnO/SrUy5WR8EzOj1/Uw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.2.tgz", + "integrity": "sha512-I0CR1RUMmOzd0tRpz10oUfaChBWs+/Hrvn5xYhMEF/ZqrDaaeHwS8yDBqEWCrEnkH2g+WE/6g90oBv3nKpcm8Q==", "dev": true, "requires": { - "@jest/fake-timers": "^28.1.1", + "@jest/fake-timers": "^28.1.2", "@jest/types": "^28.1.1", "@types/node": "*", "jest-mock": "^28.1.1" } }, "@jest/expect": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.1.tgz", - "integrity": "sha512-/+tQprrFoT6lfkMj4mW/mUIfAmmk/+iQPmg7mLDIFOf2lyf7EBHaS+x3RbeR0VZVMe55IvX7QRoT/2aK3AuUXg==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.2.tgz", + "integrity": "sha512-HBzyZBeFBiOelNbBKN0pilWbbrGvwDUwAqMC46NVJmWm8AVkuE58NbG1s7DR4cxFt4U5cVLxofAoHxgvC5MyOw==", "dev": true, "requires": { "expect": "^28.1.1", - "jest-snapshot": "^28.1.1" + "jest-snapshot": "^28.1.2" } }, "@jest/expect-utils": { @@ -4807,13 +4832,13 @@ } }, "@jest/fake-timers": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.1.tgz", - "integrity": "sha512-BY/3+TyLs5+q87rGWrGUY5f8e8uC3LsVHS9Diz8+FV3ARXL4sNnkLlIB8dvDvRrp+LUCGM+DLqlsYubizGUjIA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.2.tgz", + "integrity": "sha512-xSYEI7Y0D5FbZN2LsCUj/EKRR1zfQYmGuAUVh6xTqhx7V5JhjgMcK5Pa0iR6WIk0GXiHDe0Ke4A+yERKE9saqg==", "dev": true, "requires": { "@jest/types": "^28.1.1", - "@sinonjs/fake-timers": "^9.1.1", + "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", "jest-message-util": "^28.1.1", "jest-mock": "^28.1.1", @@ -4821,28 +4846,28 @@ } }, "@jest/globals": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.1.tgz", - "integrity": "sha512-dEgl/6v7ToB4vXItdvcltJBgny0xBE6xy6IYQrPJAJggdEinGxCDMivNv7sFzPcTITGquXD6UJwYxfJ/5ZwDSg==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.2.tgz", + "integrity": "sha512-cz0lkJVDOtDaYhvT3Fv2U1B6FtBnV+OpEyJCzTHM1fdoTsU4QNLAt/H4RkiwEUU+dL4g/MFsoTuHeT2pvbo4Hg==", "dev": true, "requires": { - "@jest/environment": "^28.1.1", - "@jest/expect": "^28.1.1", + "@jest/environment": "^28.1.2", + "@jest/expect": "^28.1.2", "@jest/types": "^28.1.1" } }, "@jest/reporters": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.1.tgz", - "integrity": "sha512-597Zj4D4d88sZrzM4atEGLuO7SdA/YrOv9SRXHXRNC+/FwPCWxZhBAEzhXoiJzfRwn8zes/EjS8Lo6DouGN5Gg==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.2.tgz", + "integrity": "sha512-/whGLhiwAqeCTmQEouSigUZJPVl7sW8V26EiboImL+UyXznnr1a03/YZ2BX8OlFw0n+Zlwu+EZAITZtaeRTxyA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^28.1.1", "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.13", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -4861,7 +4886,7 @@ "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^9.0.0" + "v8-to-istanbul": "^9.0.1" } }, "@jest/schemas": { @@ -4874,12 +4899,12 @@ } }, "@jest/source-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.0.2.tgz", - "integrity": "sha512-Y9dxC8ZpN3kImkk0LkK5XCEneYMAXlZ8m5bflmSL5vrwyeUpJfentacCUg6fOb8NOpOO7hz2+l37MV77T6BFPw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", + "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.13", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } @@ -4909,14 +4934,14 @@ } }, "@jest/transform": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.1.tgz", - "integrity": "sha512-PkfaTUuvjUarl1EDr5ZQcCA++oXkFCP9QFUkG0yVKVmNObjhrqDy0kbMpMebfHWm3CCDHjYNem9eUSH8suVNHQ==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.2.tgz", + "integrity": "sha512-3o+lKF6iweLeJFHBlMJysdaPbpoMmtbHEFsjzSv37HIq/wWt5ijTeO2Yf7MO5yyczCopD507cNwNLeX8Y/CuIg==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@jest/types": "^28.1.1", - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.13", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", @@ -4956,27 +4981,27 @@ } }, "@jridgewell/resolve-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", - "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", + "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", "dev": true }, "@jridgewell/set-array": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", - "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true }, "@jridgewell/sourcemap-codec": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", - "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", - "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", @@ -5196,12 +5221,12 @@ } }, "babel-jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.1.tgz", - "integrity": "sha512-MEt0263viUdAkTq5D7upHPNxvt4n9uLUGa6pPz3WviNBMtOmStb1lIXS3QobnoqM+qnH+vr4EKlvhe8QcmxIYw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.2.tgz", + "integrity": "sha512-pfmoo6sh4L/+5/G2OOfQrGJgvH7fTa1oChnuYH2G/6gA+JwDvO8PELwvwnofKBMNrQsam0Wy/Rw+QSrBNewq2Q==", "dev": true, "requires": { - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^28.1.1", @@ -5291,16 +5316,15 @@ } }, "browserslist": { - "version": "4.20.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz", - "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz", + "integrity": "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001349", - "electron-to-chromium": "^1.4.147", - "escalade": "^3.1.1", + "caniuse-lite": "^1.0.30001359", + "electron-to-chromium": "^1.4.172", "node-releases": "^2.0.5", - "picocolors": "^1.0.0" + "update-browserslist-db": "^1.0.4" } }, "bser": { @@ -5331,9 +5355,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001358", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001358.tgz", - "integrity": "sha512-hvp8PSRymk85R20bsDra7ZTCpSVGN/PAz9pSAjPSjKC+rNmnUk5vCRgJwiTT/O4feQ/yu/drvZYpKxxhbFuChw==", + "version": "1.0.30001361", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001361.tgz", + "integrity": "sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ==", "dev": true }, "chalk": { @@ -5503,9 +5527,9 @@ } }, "electron-to-chromium": { - "version": "1.4.163", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.163.tgz", - "integrity": "sha512-c9q94pUVqIdc8hyr7jZDB4bNEoNF3QJ7y35lnddMD+mXtiv5GsL1bT/RmfW/KEOmvlNg5Oy1qioiy4tA7e864Q==", + "version": "1.4.173", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.173.tgz", + "integrity": "sha512-Qo3LnVW6JRNhD32viSdPebxKI7K+3WeBDjU1+Q2yZS83zAh8C2LyPpzTimlciv6U74KpY9n/0ESAhUByRke0jw==", "dev": true }, "emittery": { @@ -5786,9 +5810,9 @@ } }, "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", + "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", "dev": true }, "follow-redirects": { @@ -6078,15 +6102,15 @@ } }, "jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.1.tgz", - "integrity": "sha512-qw9YHBnjt6TCbIDMPMpJZqf9E12rh6869iZaN08/vpOGgHJSAaLLUn6H8W3IAEuy34Ls3rct064mZLETkxJ2XA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.2.tgz", + "integrity": "sha512-Tuf05DwLeCh2cfWCQbcz9UxldoDyiR1E9Igaei5khjonKncYdc6LDfynKCEWozK0oLE3GD+xKAo2u8x/0s6GOg==", "dev": true, "requires": { - "@jest/core": "^28.1.1", + "@jest/core": "^28.1.2", "@jest/types": "^28.1.1", "import-local": "^3.0.2", - "jest-cli": "^28.1.1" + "jest-cli": "^28.1.2" } }, "jest-changed-files": { @@ -6100,13 +6124,13 @@ } }, "jest-circus": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.1.tgz", - "integrity": "sha512-75+BBVTsL4+p2w198DQpCeyh1RdaS2lhEG87HkaFX/UG0gJExVq2skG2pT7XZEGBubNj2CytcWSPan4QEPNosw==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.2.tgz", + "integrity": "sha512-E2vdPIJG5/69EMpslFhaA46WkcrN74LI5V/cSJ59L7uS8UNoXbzTxmwhpi9XrIL3zqvMt5T0pl5k2l2u2GwBNQ==", "dev": true, "requires": { - "@jest/environment": "^28.1.1", - "@jest/expect": "^28.1.1", + "@jest/environment": "^28.1.2", + "@jest/expect": "^28.1.2", "@jest/test-result": "^28.1.1", "@jest/types": "^28.1.1", "@types/node": "*", @@ -6117,8 +6141,8 @@ "jest-each": "^28.1.1", "jest-matcher-utils": "^28.1.1", "jest-message-util": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-snapshot": "^28.1.1", + "jest-runtime": "^28.1.2", + "jest-snapshot": "^28.1.2", "jest-util": "^28.1.1", "pretty-format": "^28.1.1", "slash": "^3.0.0", @@ -6127,19 +6151,19 @@ } }, "jest-cli": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.1.tgz", - "integrity": "sha512-+sUfVbJqb1OjBZ0OdBbI6OWfYM1i7bSfzYy6gze1F1w3OKWq8ZTEKkZ8a7ZQPq6G/G1qMh/uKqpdWhgl11NFQQ==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.2.tgz", + "integrity": "sha512-l6eoi5Do/IJUXAFL9qRmDiFpBeEJAnjJb1dcd9i/VWfVWbp3mJhuH50dNtX67Ali4Ecvt4eBkWb4hXhPHkAZTw==", "dev": true, "requires": { - "@jest/core": "^28.1.1", + "@jest/core": "^28.1.2", "@jest/test-result": "^28.1.1", "@jest/types": "^28.1.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^28.1.1", + "jest-config": "^28.1.2", "jest-util": "^28.1.1", "jest-validate": "^28.1.1", "prompts": "^2.0.1", @@ -6147,26 +6171,26 @@ } }, "jest-config": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.1.tgz", - "integrity": "sha512-tASynMhS+jVV85zKvjfbJ8nUyJS/jUSYZ5KQxLUN2ZCvcQc/OmhQl2j6VEL3ezQkNofxn5pQ3SPYWPHb0unTZA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.2.tgz", + "integrity": "sha512-g6EfeRqddVbjPVBVY4JWpUY4IvQoFRIZcv4V36QkqzE0IGhEC/VkugFeBMAeUE7PRgC8KJF0yvJNDeQRbamEVA==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^28.1.1", "@jest/types": "^28.1.1", - "babel-jest": "^28.1.1", + "babel-jest": "^28.1.2", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^28.1.1", - "jest-environment-node": "^28.1.1", + "jest-circus": "^28.1.2", + "jest-environment-node": "^28.1.2", "jest-get-type": "^28.0.2", "jest-regex-util": "^28.0.2", "jest-resolve": "^28.1.1", - "jest-runner": "^28.1.1", + "jest-runner": "^28.1.2", "jest-util": "^28.1.1", "jest-validate": "^28.1.1", "micromatch": "^4.0.4", @@ -6211,13 +6235,13 @@ } }, "jest-environment-node": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.1.tgz", - "integrity": "sha512-2aV/eeY/WNgUUJrrkDJ3cFEigjC5fqT1+fCclrY6paqJ5zVPoM//sHmfgUUp7WLYxIdbPwMiVIzejpN56MxnNA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.2.tgz", + "integrity": "sha512-oYsZz9Qw27XKmOgTtnl0jW7VplJkN2oeof+SwAwKFQacq3CLlG9u4kTGuuLWfvu3J7bVutWlrbEQMOCL/jughw==", "dev": true, "requires": { - "@jest/environment": "^28.1.1", - "@jest/fake-timers": "^28.1.1", + "@jest/environment": "^28.1.2", + "@jest/fake-timers": "^28.1.2", "@jest/types": "^28.1.1", "@types/node": "*", "jest-mock": "^28.1.1", @@ -6330,37 +6354,37 @@ } }, "jest-resolve-dependencies": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.1.tgz", - "integrity": "sha512-p8Y150xYJth4EXhOuB8FzmS9r8IGLEioiaetgdNGb9VHka4fl0zqWlVe4v7mSkYOuEUg2uB61iE+zySDgrOmgQ==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.2.tgz", + "integrity": "sha512-OXw4vbOZuyRTBi3tapWBqdyodU+T33ww5cPZORuTWkg+Y8lmsxQlVu3MWtJh6NMlKRTHQetF96yGPv01Ye7Mbg==", "dev": true, "requires": { "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.1.1" + "jest-snapshot": "^28.1.2" } }, "jest-runner": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.1.tgz", - "integrity": "sha512-W5oFUiDBgTsCloTAj6q95wEvYDB0pxIhY6bc5F26OucnwBN+K58xGTGbliSMI4ChQal5eANDF+xvELaYkJxTmA==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.2.tgz", + "integrity": "sha512-6/k3DlAsAEr5VcptCMdhtRhOoYClZQmxnVMZvZ/quvPGRpN7OBQYPIC32tWSgOnbgqLXNs5RAniC+nkdFZpD4A==", "dev": true, "requires": { "@jest/console": "^28.1.1", - "@jest/environment": "^28.1.1", + "@jest/environment": "^28.1.2", "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.10.2", "graceful-fs": "^4.2.9", "jest-docblock": "^28.1.1", - "jest-environment-node": "^28.1.1", + "jest-environment-node": "^28.1.2", "jest-haste-map": "^28.1.1", "jest-leak-detector": "^28.1.1", "jest-message-util": "^28.1.1", "jest-resolve": "^28.1.1", - "jest-runtime": "^28.1.1", + "jest-runtime": "^28.1.2", "jest-util": "^28.1.1", "jest-watcher": "^28.1.1", "jest-worker": "^28.1.1", @@ -6369,17 +6393,17 @@ } }, "jest-runtime": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.1.tgz", - "integrity": "sha512-J89qEJWW0leOsqyi0D9zHpFEYHwwafFdS9xgvhFHtIdRghbadodI0eA+DrthK/1PebBv3Px8mFSMGKrtaVnleg==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.2.tgz", + "integrity": "sha512-i4w93OsWzLOeMXSi9epmakb2+3z0AchZtUQVF1hesBmcQQy4vtaql5YdVe9KexdJaVRyPDw8DoBR0j3lYsZVYw==", "dev": true, "requires": { - "@jest/environment": "^28.1.1", - "@jest/fake-timers": "^28.1.1", - "@jest/globals": "^28.1.1", - "@jest/source-map": "^28.0.2", + "@jest/environment": "^28.1.2", + "@jest/fake-timers": "^28.1.2", + "@jest/globals": "^28.1.2", + "@jest/source-map": "^28.1.2", "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", @@ -6392,16 +6416,16 @@ "jest-mock": "^28.1.1", "jest-regex-util": "^28.0.2", "jest-resolve": "^28.1.1", - "jest-snapshot": "^28.1.1", + "jest-snapshot": "^28.1.2", "jest-util": "^28.1.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.1.tgz", - "integrity": "sha512-1KjqHJ98adRcbIdMizjF5DipwZFbvxym/kFO4g4fVZCZRxH/dqV8TiBFCa6rqic3p0karsy8RWS1y4E07b7P0A==", + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.2.tgz", + "integrity": "sha512-wzrieFttZYfLvrCVRJxX+jwML2YTArOUqFpCoSVy1QUapx+LlV9uLbV/mMEhYj4t7aMeE9aSQFHSvV/oNoDAMA==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -6410,7 +6434,7 @@ "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", "@jest/expect-utils": "^28.1.1", - "@jest/transform": "^28.1.1", + "@jest/transform": "^28.1.2", "@jest/types": "^28.1.1", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", @@ -7237,6 +7261,16 @@ "underscore": "*" } }, + "update-browserslist-db": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", + "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -7247,9 +7281,9 @@ } }, "user-agents": { - "version": "1.0.1054", - "resolved": "https://registry.npmjs.org/user-agents/-/user-agents-1.0.1054.tgz", - "integrity": "sha512-dx1LbJEysVY/W4nPdIPnYlQTHMaJHKhtTGRzD46FrgzwwjzioFMb2dcHGKCyoH76Tp7alsgu4YcMDAZLNCd1qg==", + "version": "1.0.1062", + "resolved": "https://registry.npmjs.org/user-agents/-/user-agents-1.0.1062.tgz", + "integrity": "sha512-dVlTNLHEaw+s/s+ysHo+eX7vackyQDBiunzA7soAI2gbaWMRlOjLZoy4mfhrb+fJo5kYD183glY91H7vUrowzg==", "requires": { "dot-json": "^1.2.2", "lodash.clonedeep": "^4.5.0" diff --git a/package.json b/package.json index 69bb7208..a4ecf2ff 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,12 @@ { "name": "youtubei.js", - "version": "1.4.3", + "version": "2.0.0", "description": "A full-featured wrapper around YouTube's private API. Allows you to retrieve info about any video, subscribe, unsubscribe, like, dislike, comment, search, download videos/music and much more!", "main": "index.js", "author": "LuanRT (https://github.com/LuanRT)", + "contributors": [ + "Wykerd (https://github.com/wykerd/)" + ], "funding": "https://ko-fi.com/luanrt", "license": "MIT", "engines": { @@ -11,8 +14,8 @@ }, "scripts": { "test": "jest", - "lint": "eslint ./", - "lint:fix": "eslint --fix ./", + "lint": "eslint ./lib", + "lint:fix": "eslint --fix ./lib", "build:types": "npx tsc" }, "types": "./typings/index.d.ts", diff --git a/test/main.test.js b/test/main.test.js index 8af5448b..483fbcd8 100644 --- a/test/main.test.js +++ b/test/main.test.js @@ -53,22 +53,15 @@ describe('YouTube.js Tests', () => { }); }); - describe('Playlists', () => { + describe('General', () => { it('Should retrieve playlist with YouTube', async () => { const playlist = await this.session.getPlaylist('PLLw0AzOz95FU7w2juhPECP9NyGhbZmz_t', { client: 'YOUTUBE' }); expect(playlist.items.length).toBeLessThanOrEqual(100); }); - it('Should retrieve playlist with YouTube Music', async () => { - const playlist = await this.session.getPlaylist('PLLw0AzOz95FU7w2juhPECP9NyGhbZmz_t', { client: 'YTMUSIC' }); - expect(playlist.items.length).toBeLessThanOrEqual(100); - }); - }); - - describe('General', () => { it('Should retrieve home feed', async () => { const homefeed = await this.session.getHomeFeed(); - expect(homefeed.videos.length).toBeLessThanOrEqual(40); + expect(homefeed.videos.length).toBeGreaterThan(0); }); it('Should retrieve trending content', async () => { @@ -77,8 +70,8 @@ describe('YouTube.js Tests', () => { }); it('Should retrieve video info', async () => { - const details = await this.session.getDetails(Constants.VIDEOS[0].ID); - expect(details.id).toBe(Constants.VIDEOS[0].ID); + const info = await this.session.getInfo(Constants.VIDEOS[0].ID); + expect(info.basic_info.id).toBe(Constants.VIDEOS[0].ID); }); it('Should download video', async () => { diff --git a/typings/lib/Innertube.d.ts b/typings/lib/Innertube.d.ts index 6cc1fa39..e5ab654c 100644 --- a/typings/lib/Innertube.d.ts +++ b/typings/lib/Innertube.d.ts @@ -120,20 +120,6 @@ declare class Innertube { query: string; results: string[]; }>; - /** - * Retrieves video info. - * - * @deprecated do not use this, it is slow and inefficient. - * Use {@link getInfo} instead. - * @param {string} video_id - the video id. - * @returns {Promise.<{ title: string, description: string, thumbnail: any[], metadata: object }>} - */ - getDetails(video_id: string): Promise<{ - title: string; - description: string; - thumbnail: any[]; - metadata: object; - }>; /** * Retrieves comments for a video. * diff --git a/typings/lib/core/Livechat.d.ts b/typings/lib/core/Livechat.d.ts deleted file mode 100644 index 42e45afe..00000000 --- a/typings/lib/core/Livechat.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -export = Livechat; -/** @namespace */ -declare class Livechat extends EventEmitter { - constructor(session: any, token: any, channel_id: any, video_id: any); - ctoken: any; - session: any; - video_id: any; - channel_id: any; - message_queue: any[]; - id_cache: any[]; - poll_intervals_ms: number; - running: boolean; - metadata_ctoken: any; - livechat_poller: NodeJS.Timeout; - sendMessage(text: any): Promise; - /** - * Blocks a user. - * - * @todo Implement this method - */ - blockUser(): Promise; - stop(): void; - #private; -} -import EventEmitter = require("events"); diff --git a/typings/lib/core/Player.d.ts b/typings/lib/core/Player.d.ts index 501c31bc..13ba40e3 100644 --- a/typings/lib/core/Player.d.ts +++ b/typings/lib/core/Player.d.ts @@ -1,6 +1,7 @@ export = Player; /** @namespace */ declare class Player { + static get LIBRARY_VERSION(): number; /** * Represents the YouTube Web player script. * @@ -9,6 +10,7 @@ declare class Player { */ constructor(id: string, axios: AxiosInstance); init(): Promise; + decipher(url: any, signature_cipher: any, cipher: any): string; /** * Js player url. * @@ -23,20 +25,6 @@ declare class Player { * @returns {string} */ readonly get sts(): string; - /** - * N-Token decipher algorithm. - * - * @readonly - * @returns {string} - */ - readonly get ntoken_decipher(): string; - /** - * Signature decipher algorithm. - * - * @readonly - * @returns {string} - */ - readonly get signature_decipher(): string; /** * Checks if the player script is cached. * diff --git a/typings/lib/deciphers/NToken.d.ts b/typings/lib/deciphers/NToken.d.ts index ad695b97..f2b6ac47 100644 --- a/typings/lib/deciphers/NToken.d.ts +++ b/typings/lib/deciphers/NToken.d.ts @@ -1,13 +1,81 @@ -export = NToken; -declare class NToken { - constructor(raw_code: any, n: any); - n: any; - raw_code: any; - /** - * Solves throttling challange by transforming the n token. - * - * @returns {string} - */ - transform(): string; - #private; +export namespace NTokenTransformOperation { + const NO_OP: number; + const PUSH: number; + const REVERSE_1: number; + const REVERSE_2: number; + const SPLICE: number; + const SWAP0_1: number; + const SWAP0_2: number; + const ROTATE_1: number; + const ROTATE_2: number; + const BASE64_DIA: number; + const TRANSLATE_1: number; + const TRANSLATE_2: number; +} +export namespace NTokenTransformOpType { + const FUNC: number; + const N_ARR: number; + const LITERAL: number; + const REF: number; +} +export default NToken; +export class NTokenTransforms { + /** + * Gets a base64 alphabet and uses it as a lookup table to modify n. + * + * @param {any[]} arr + * @param {string} token + * @param {boolean} is_reverse_base64 + * @returns {void} + */ + static translate1(arr: any[], token: string, is_reverse_base64: boolean): void; + static translate2(arr: any, token: any, characters: any): void; + /** + * Returns the requested base64 dialect, currently this is only used by 'translate2'. + * + * @param {boolean} is_reverse_base64 + * @returns {string[]} + */ + static getBase64Dia(is_reverse_base64: boolean): string[]; + /** + * Swaps the first element with the one at the given index. + * + * @param {any[]} arr + * @param {number} index + * @returns {void} + */ + static swap0(arr: any[], index: number): void; + /** + * Rotates elements of the array. + * + * @param {any[]} arr + * @param {number} index + * @returns {void} + */ + static rotate(arr: any[], index: number): void; + /** + * Deletes one element at the given index. + * + * @param {any[]} arr + * @param {number} index + * @returns {void} + */ + static splice(arr: any[], index: number): void; + static reverse(arr: any): void; + static push(arr: any, item: any): void; +} +declare class NToken { + static fromSourceCode(raw: any): NToken; + static fromArrayBuffer(buffer: any): NToken; + static get LIBRARY_VERSION(): number; + static getFunc(el: any): any; + static getTransformationData(raw: any): any; + static refineNTokenData(data: any): any; + constructor(transformer: any); + transformer: any; + evaluate(i: any, n_token: any, transformer: any): any; + transform(n: any): any; + getTransformerClone(): any[][]; + toJSON(): any[][]; + toArrayBuffer(): ArrayBuffer; } diff --git a/typings/lib/deciphers/Signature.d.ts b/typings/lib/deciphers/Signature.d.ts index 699d9629..150a575b 100644 --- a/typings/lib/deciphers/Signature.d.ts +++ b/typings/lib/deciphers/Signature.d.ts @@ -1,14 +1,24 @@ -export = Signature; -declare class Signature { - constructor(url: any, sig_decipher_sc: any); - url: any; - sig_decipher_sc: any; - decipherBeta(): any; - /** - * Deciphers signature. - * - * @returns {string} - */ - decipher(): string; - #private; +export namespace SignatureOperation { + const REVERSE: number; + const SPLICE: number; + const SWAP: number; +} +export default Signature; +declare class Signature { + static fromSourceCode(sig_decipher_sc: any): Signature; + static fromArrayBuffer(buffer: any): Signature; + /** + * Extracts the functions used to modify the signature + * and returns them in the correct order. + * + * @param {string} sc + * @returns {Array.} + */ + static getFunctions(sc: string): Array; + static get LIBRARY_VERSION(): number; + constructor(action_sequence: any); + action_sequence: any; + decipher(url: any): string; + toJSON(): any[]; + toArrayBuffer(): ArrayBuffer; } diff --git a/typings/lib/parser/contents/classes/EmojiRun.d.ts b/typings/lib/parser/contents/classes/EmojiRun.d.ts new file mode 100644 index 00000000..c60d05b0 --- /dev/null +++ b/typings/lib/parser/contents/classes/EmojiRun.d.ts @@ -0,0 +1,12 @@ +export = EmojiRun; +declare class EmojiRun { + constructor(data: any); + text: any; + emoji: { + emoji_id: any; + shortcuts: any; + search_terms: any; + image: Thumbnail[]; + }; +} +import Thumbnail = require("./Thumbnail"); diff --git a/typings/lib/parser/contents/classes/Format.d.ts b/typings/lib/parser/contents/classes/Format.d.ts index 40bfa931..5abec3c9 100644 --- a/typings/lib/parser/contents/classes/Format.d.ts +++ b/typings/lib/parser/contents/classes/Format.d.ts @@ -30,5 +30,11 @@ declare class Format { loudness_db: any; has_audio: boolean; has_video: boolean; - decipher(player: any): string; + /** + * Decipher the streaming url of the format. + * + * @param {import('../../../core/Player')} player + * @returns {string} Deciphered URL for downloading + */ + decipher(player: import('../../../core/Player')): string; } diff --git a/typings/lib/parser/contents/classes/LiveChat.d.ts b/typings/lib/parser/contents/classes/LiveChat.d.ts new file mode 100644 index 00000000..8979bc6c --- /dev/null +++ b/typings/lib/parser/contents/classes/LiveChat.d.ts @@ -0,0 +1,17 @@ +export = LiveChat; +declare class LiveChat { + constructor(data: any); + type: string; + header: any; + initial_display_state: any; + continuation: any; + client_messages: { + reconnect_message: Text; + unable_to_reconnect_message: Text; + fatal_error: Text; + reconnected_message: Text; + generic_error: Text; + }; + is_replay: any; +} +import Text = require("./Text"); diff --git a/typings/lib/parser/contents/classes/LiveChatAuthorBadge.d.ts b/typings/lib/parser/contents/classes/LiveChatAuthorBadge.d.ts new file mode 100644 index 00000000..44a268fd --- /dev/null +++ b/typings/lib/parser/contents/classes/LiveChatAuthorBadge.d.ts @@ -0,0 +1,6 @@ +export = LiveChatAuthorBadge; +declare class LiveChatAuthorBadge extends MetadataBadge { + custom_thumbnail: Thumbnail[]; +} +import MetadataBadge = require("./MetadataBadge"); +import Thumbnail = require("./Thumbnail"); diff --git a/typings/lib/parser/contents/classes/LiveChatHeader.d.ts b/typings/lib/parser/contents/classes/LiveChatHeader.d.ts new file mode 100644 index 00000000..c363d3b7 --- /dev/null +++ b/typings/lib/parser/contents/classes/LiveChatHeader.d.ts @@ -0,0 +1,8 @@ +export = LiveChatHeader; +declare class LiveChatHeader { + constructor(data: any); + type: string; + overflow_menu: any; + collapse_button: any; + view_selector: any; +} diff --git a/typings/lib/parser/contents/classes/LiveChatItemList.d.ts b/typings/lib/parser/contents/classes/LiveChatItemList.d.ts new file mode 100644 index 00000000..452a0a30 --- /dev/null +++ b/typings/lib/parser/contents/classes/LiveChatItemList.d.ts @@ -0,0 +1,7 @@ +export = LiveChatItemList; +declare class LiveChatItemList { + constructor(data: any); + type: string; + max_items_to_display: any; + more_comments_below_button: any; +} diff --git a/typings/lib/parser/contents/classes/LiveChatMessageInput.d.ts b/typings/lib/parser/contents/classes/LiveChatMessageInput.d.ts new file mode 100644 index 00000000..d6a09b2c --- /dev/null +++ b/typings/lib/parser/contents/classes/LiveChatMessageInput.d.ts @@ -0,0 +1,10 @@ +export = LiveChatMessageInput; +declare class LiveChatMessageInput { + constructor(data: any); + author_name: Text; + author_photo: Thumbnail[]; + send_button: any; + target_id: any; +} +import Text = require("./Text"); +import Thumbnail = require("./Thumbnail"); diff --git a/typings/lib/parser/contents/classes/LiveChatParticipant.d.ts b/typings/lib/parser/contents/classes/LiveChatParticipant.d.ts new file mode 100644 index 00000000..c025ef24 --- /dev/null +++ b/typings/lib/parser/contents/classes/LiveChatParticipant.d.ts @@ -0,0 +1,10 @@ +export = LiveChatParticipant; +declare class LiveChatParticipant { + constructor(data: any); + type: string; + name: Text; + photo: Thumbnail[]; + badges: any; +} +import Text = require("./Text"); +import Thumbnail = require("./Thumbnail"); diff --git a/typings/lib/parser/contents/classes/LiveChatParticipantsList.d.ts b/typings/lib/parser/contents/classes/LiveChatParticipantsList.d.ts new file mode 100644 index 00000000..f42772a0 --- /dev/null +++ b/typings/lib/parser/contents/classes/LiveChatParticipantsList.d.ts @@ -0,0 +1,8 @@ +export = LiveChatParticipantsList; +declare class LiveChatParticipantsList { + constructor(data: any); + type: string; + title: Text; + participants: any; +} +import Text = require("./Text"); diff --git a/typings/lib/parser/contents/classes/NavigationEndpoint.d.ts b/typings/lib/parser/contents/classes/NavigationEndpoint.d.ts index 62c8afda..2fdf420b 100644 --- a/typings/lib/parser/contents/classes/NavigationEndpoint.d.ts +++ b/typings/lib/parser/contents/classes/NavigationEndpoint.d.ts @@ -69,5 +69,11 @@ declare class NavigationEndpoint { get_report_form: { params: any; }; + live_chat_item_context_menu: { + params: any; + }; + send_live_chat_vote: { + params: any; + }; call(actions: any, client: any): Promise; } diff --git a/typings/lib/parser/contents/classes/PlaylistHeader.d.ts b/typings/lib/parser/contents/classes/PlaylistHeader.d.ts new file mode 100644 index 00000000..88682d59 --- /dev/null +++ b/typings/lib/parser/contents/classes/PlaylistHeader.d.ts @@ -0,0 +1,22 @@ +export = PlaylistHeader; +declare class PlaylistHeader { + constructor(data: any); + type: string; + id: any; + title: Text; + stats: any; + brief_stats: any; + author: PlaylistAuthor; + description: Text; + num_videos: Text; + view_count: Text; + can_share: any; + can_delete: any; + is_editable: any; + privacy: any; + save_button: any; + shuffle_play_button: any; + menu: any; +} +import Text = require("./Text"); +import PlaylistAuthor = require("./PlaylistAuthor"); diff --git a/typings/lib/parser/contents/classes/SortFilterSubMenu.d.ts b/typings/lib/parser/contents/classes/SortFilterSubMenu.d.ts new file mode 100644 index 00000000..f8895fdd --- /dev/null +++ b/typings/lib/parser/contents/classes/SortFilterSubMenu.d.ts @@ -0,0 +1,7 @@ +export = SortFilterSubMenu; +declare class SortFilterSubMenu { + constructor(data: any); + type: string; + sub_menu_items: any; + label: any; +} diff --git a/typings/lib/parser/contents/classes/Thumbnail.d.ts b/typings/lib/parser/contents/classes/Thumbnail.d.ts index 433d3a26..ff031cbc 100644 --- a/typings/lib/parser/contents/classes/Thumbnail.d.ts +++ b/typings/lib/parser/contents/classes/Thumbnail.d.ts @@ -3,10 +3,10 @@ declare class Thumbnail { /** * Get thumbnails from response object * - * @param {*} response response object + * @param {object} data - response object * @returns {Thumbnail[]} sorted array of thumbnails */ - static fromResponse({ thumbnails }: any): Thumbnail[]; + static fromResponse(data: object): Thumbnail[]; constructor({ url, width, height }: { url: any; width: any; diff --git a/typings/lib/parser/contents/classes/livechat/AddBannerToLiveChatCommand.d.ts b/typings/lib/parser/contents/classes/livechat/AddBannerToLiveChatCommand.d.ts new file mode 100644 index 00000000..a77c3173 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/AddBannerToLiveChatCommand.d.ts @@ -0,0 +1,4 @@ +export = AddBannerToLiveChatCommand; +declare class AddBannerToLiveChatCommand { + constructor(data: any); +} diff --git a/typings/lib/parser/contents/classes/livechat/AddChatItemAction.d.ts b/typings/lib/parser/contents/classes/livechat/AddChatItemAction.d.ts new file mode 100644 index 00000000..893f5662 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/AddChatItemAction.d.ts @@ -0,0 +1,7 @@ +export = AddChatItemAction; +declare class AddChatItemAction { + constructor(data: any); + type: string; + item: any; + client_id: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/AddLiveChatTickerItemAction.d.ts b/typings/lib/parser/contents/classes/livechat/AddLiveChatTickerItemAction.d.ts new file mode 100644 index 00000000..1df16562 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/AddLiveChatTickerItemAction.d.ts @@ -0,0 +1,7 @@ +export = AddLiveChatTickerItemAction; +declare class AddLiveChatTickerItemAction { + constructor(data: any); + type: string; + item: any; + duration_sec: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/LiveChatActionPanel.d.ts b/typings/lib/parser/contents/classes/livechat/LiveChatActionPanel.d.ts new file mode 100644 index 00000000..6676fbf2 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/LiveChatActionPanel.d.ts @@ -0,0 +1,8 @@ +export = LiveChatActionPanel; +declare class LiveChatActionPanel { + constructor(data: any); + type: string; + id: any; + contents: any; + target_id: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/MarkChatItemAsDeletedAction.d.ts b/typings/lib/parser/contents/classes/livechat/MarkChatItemAsDeletedAction.d.ts new file mode 100644 index 00000000..b44df5dc --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/MarkChatItemAsDeletedAction.d.ts @@ -0,0 +1,8 @@ +export = MarkChatItemAsDeletedAction; +declare class MarkChatItemAsDeletedAction { + constructor(data: any); + type: string; + deleted_state_message: Text; + target_item_id: any; +} +import Text = require("../Text"); diff --git a/typings/lib/parser/contents/classes/livechat/MarkChatItemsByAuthorAsDeletedAction.d.ts b/typings/lib/parser/contents/classes/livechat/MarkChatItemsByAuthorAsDeletedAction.d.ts new file mode 100644 index 00000000..b5d8631a --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/MarkChatItemsByAuthorAsDeletedAction.d.ts @@ -0,0 +1,8 @@ +export = MarkChatItemsByAuthorAsDeletedAction; +declare class MarkChatItemsByAuthorAsDeletedAction { + constructor(data: any); + type: string; + deleted_state_message: Text; + channel_id: any; +} +import Text = require("../Text"); diff --git a/typings/lib/parser/contents/classes/livechat/ReplaceChatItemAction.d.ts b/typings/lib/parser/contents/classes/livechat/ReplaceChatItemAction.d.ts new file mode 100644 index 00000000..4d33dadf --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/ReplaceChatItemAction.d.ts @@ -0,0 +1,6 @@ +export = ReplaceChatItemAction; +declare class ReplaceChatItemAction { + constructor(data: any); + target_item_id: any; + replacement_item: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/ReplayChatItemAction.d.ts b/typings/lib/parser/contents/classes/livechat/ReplayChatItemAction.d.ts new file mode 100644 index 00000000..4141c4f8 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/ReplayChatItemAction.d.ts @@ -0,0 +1,7 @@ +export = ReplayChatItemAction; +declare class ReplayChatItemAction { + constructor(data: any); + type: string; + actions: any; + video_offset_time_msec: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/ShowLiveChatActionPanelAction.d.ts b/typings/lib/parser/contents/classes/livechat/ShowLiveChatActionPanelAction.d.ts new file mode 100644 index 00000000..e71623ab --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/ShowLiveChatActionPanelAction.d.ts @@ -0,0 +1,6 @@ +export = ShowLiveChatActionPanelAction; +declare class ShowLiveChatActionPanelAction { + constructor(data: any); + type: string; + panel_to_show: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/ShowLiveChatTooltipCommand.d.ts b/typings/lib/parser/contents/classes/livechat/ShowLiveChatTooltipCommand.d.ts new file mode 100644 index 00000000..6d7e99d2 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/ShowLiveChatTooltipCommand.d.ts @@ -0,0 +1,6 @@ +export = ShowLiveChatTooltipCommand; +declare class ShowLiveChatTooltipCommand { + constructor(data: any); + type: string; + tooltip: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/UpdateDateTextAction.d.ts b/typings/lib/parser/contents/classes/livechat/UpdateDateTextAction.d.ts new file mode 100644 index 00000000..093b2f54 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/UpdateDateTextAction.d.ts @@ -0,0 +1,6 @@ +export = UpdateDateTextAction; +declare class UpdateDateTextAction { + constructor(data: any); + type: string; + date_text: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/UpdateDescriptionAction.d.ts b/typings/lib/parser/contents/classes/livechat/UpdateDescriptionAction.d.ts new file mode 100644 index 00000000..a44290a2 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/UpdateDescriptionAction.d.ts @@ -0,0 +1,7 @@ +export = UpdateDescriptionAction; +declare class UpdateDescriptionAction { + constructor(data: any); + type: string; + description: Text; +} +import Text = require("../Text"); diff --git a/typings/lib/parser/contents/classes/livechat/UpdateLiveChatPollAction.d.ts b/typings/lib/parser/contents/classes/livechat/UpdateLiveChatPollAction.d.ts new file mode 100644 index 00000000..923ade5c --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/UpdateLiveChatPollAction.d.ts @@ -0,0 +1,6 @@ +export = UpdateLiveChatPollAction; +declare class UpdateLiveChatPollAction { + constructor(data: any); + type: string; + poll_to_update: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/UpdateTitleAction.d.ts b/typings/lib/parser/contents/classes/livechat/UpdateTitleAction.d.ts new file mode 100644 index 00000000..4ccc5153 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/UpdateTitleAction.d.ts @@ -0,0 +1,7 @@ +export = UpdateTitleAction; +declare class UpdateTitleAction { + constructor(data: any); + type: string; + title: Text; +} +import Text = require("../Text"); diff --git a/typings/lib/parser/contents/classes/livechat/UpdateToggleButtonTextAction.d.ts b/typings/lib/parser/contents/classes/livechat/UpdateToggleButtonTextAction.d.ts new file mode 100644 index 00000000..024f74ec --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/UpdateToggleButtonTextAction.d.ts @@ -0,0 +1,8 @@ +export = UpdateToggleButtonTextAction; +declare class UpdateToggleButtonTextAction { + constructor(data: any); + type: string; + default_text: any; + toggled_text: any; + button_id: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/UpdateViewershipAction.d.ts b/typings/lib/parser/contents/classes/livechat/UpdateViewershipAction.d.ts new file mode 100644 index 00000000..c237eac8 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/UpdateViewershipAction.d.ts @@ -0,0 +1,9 @@ +export = UpdateViewershipAction; +declare class UpdateViewershipAction { + constructor(data: any); + type: string; + view_count: Text; + extra_short_view_count: Text; + is_live: any; +} +import Text = require("../Text"); diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatBanner.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatBanner.d.ts new file mode 100644 index 00000000..d4bbd20c --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatBanner.d.ts @@ -0,0 +1,12 @@ +export = LiveChatBanner; +declare class LiveChatBanner { + constructor(data: any); + type: string; + header: any; + contents: any; + action_id: any; + viewer_is_creator: any; + target_id: any; + is_stackable: any; + background_type: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatBannerHeader.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatBannerHeader.d.ts new file mode 100644 index 00000000..5d83cf6d --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatBannerHeader.d.ts @@ -0,0 +1,8 @@ +export = LiveChatBannerHeader; +declare class LiveChatBannerHeader { + constructor(data: any); + type: string; + text: any; + icon_type: any; + context_menu_button: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatBannerPoll.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatBannerPoll.d.ts new file mode 100644 index 00000000..cbb6ef69 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatBannerPoll.d.ts @@ -0,0 +1,13 @@ +export = LiveChatBannerPoll; +declare class LiveChatBannerPoll { + constructor(data: any); + type: string; + poll_question: Text; + author_photo: Thumbnail[]; + choices: any; + collapsed_state_entity_key: any; + live_chat_poll_state_entity_key: any; + context_menu_button: any; +} +import Text = require("../../Text"); +import Thumbnail = require("../../Thumbnail"); diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatMembershipItem.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatMembershipItem.d.ts new file mode 100644 index 00000000..d6554465 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatMembershipItem.d.ts @@ -0,0 +1,18 @@ +export = LiveChatMembershipItem; +declare class LiveChatMembershipItem { + constructor(data: any); + type: string; + id: any; + timestamp: number; + header_subtext: Text; + author: { + id: any; + name: Text; + thumbnails: Thumbnail[]; + badges: any; + }; + menu_endpoint: NavigationEndpoint; +} +import Text = require("../../Text"); +import Thumbnail = require("../../Thumbnail"); +import NavigationEndpoint = require("../../NavigationEndpoint"); diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatPaidMessage.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatPaidMessage.d.ts new file mode 100644 index 00000000..c63b72e4 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatPaidMessage.d.ts @@ -0,0 +1,20 @@ +export = LiveChatPaidMessage; +declare class LiveChatPaidMessage { + constructor(data: any); + type: string; + message: Text; + author: { + id: any; + name: Text; + thumbnails: Thumbnail[]; + badges: any; + }; + purchase_amount: any; + menu_endpoint: NavigationEndpoint; + timestamp: number; + timestamp_text: any; + id: any; +} +import Text = require("../../Text"); +import Thumbnail = require("../../Thumbnail"); +import NavigationEndpoint = require("../../NavigationEndpoint"); diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatPlaceholderItem.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatPlaceholderItem.d.ts new file mode 100644 index 00000000..379aebd8 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatPlaceholderItem.d.ts @@ -0,0 +1,7 @@ +export = LiveChatPlaceholderItem; +declare class LiveChatPlaceholderItem { + constructor(data: any); + type: string; + id: any; + timestamp: number; +} diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatTextMessage.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatTextMessage.d.ts new file mode 100644 index 00000000..f768b5ae --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatTextMessage.d.ts @@ -0,0 +1,17 @@ +export = LiveChatTextMessage; +declare class LiveChatTextMessage { + constructor(data: any); + type: string; + message: Text; + author: { + id: any; + name: Text; + thumbnails: Thumbnail[]; + }; + menu_endpoint: NavigationEndpoint; + timestamp: number; + id: any; +} +import Text = require("../../Text"); +import Thumbnail = require("../../Thumbnail"); +import NavigationEndpoint = require("../../NavigationEndpoint"); diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatTickerPaidMessageItem.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatTickerPaidMessageItem.d.ts new file mode 100644 index 00000000..ddb89b6b --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatTickerPaidMessageItem.d.ts @@ -0,0 +1,19 @@ +export = LiveChatTickerPaidMessageItem; +declare class LiveChatTickerPaidMessageItem { + constructor(data: any); + type: string; + author: { + id: any; + thumbnails: Thumbnail[]; + badges: any; + }; + amount: Text; + duration_sec: any; + full_duration_sec: any; + show_item: any; + show_item_endpoint: NavigationEndpoint; + id: any; +} +import Thumbnail = require("../../Thumbnail"); +import Text = require("../../Text"); +import NavigationEndpoint = require("../../NavigationEndpoint"); diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatTickerSponsorItem.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatTickerSponsorItem.d.ts new file mode 100644 index 00000000..beafb5a8 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatTickerSponsorItem.d.ts @@ -0,0 +1,15 @@ +export = LiveChatTickerSponsorItem; +declare class LiveChatTickerSponsorItem { + constructor(data: any); + type: string; + id: any; + detail_text: any; + author: { + id: any; + name: Text; + thumbnails: Thumbnail[]; + }; + duration_sec: any; +} +import Text = require("../../Text"); +import Thumbnail = require("../../Thumbnail"); diff --git a/typings/lib/parser/contents/classes/livechat/items/LiveChatViewerEngagementMessage.d.ts b/typings/lib/parser/contents/classes/livechat/items/LiveChatViewerEngagementMessage.d.ts new file mode 100644 index 00000000..5943e951 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/LiveChatViewerEngagementMessage.d.ts @@ -0,0 +1,6 @@ +export = LiveChatViewerEngagementMessage; +declare class LiveChatViewerEngagementMessage extends LiveChatTextMessage { + icon_type: any; + action_button: any; +} +import LiveChatTextMessage = require("./LiveChatTextMessage"); diff --git a/typings/lib/parser/contents/classes/livechat/items/Poll.d.ts b/typings/lib/parser/contents/classes/livechat/items/Poll.d.ts new file mode 100644 index 00000000..1a683f5e --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/Poll.d.ts @@ -0,0 +1,8 @@ +export = Poll; +declare class Poll { + constructor(data: any); + type: string; + header: any; + choices: any; + live_chat_poll_id: any; +} diff --git a/typings/lib/parser/contents/classes/livechat/items/PollHeader.d.ts b/typings/lib/parser/contents/classes/livechat/items/PollHeader.d.ts new file mode 100644 index 00000000..ef3f5213 --- /dev/null +++ b/typings/lib/parser/contents/classes/livechat/items/PollHeader.d.ts @@ -0,0 +1,12 @@ +export = PollHeader; +declare class PollHeader { + constructor(data: any); + type: string; + poll_question: Text; + thumbnails: Thumbnail[]; + metadata: Text; + live_chat_poll_type: any; + context_menu_button: any; +} +import Text = require("../../Text"); +import Thumbnail = require("../../Thumbnail"); diff --git a/typings/lib/parser/contents/index.d.ts b/typings/lib/parser/contents/index.d.ts index 8f454e1f..5f17060f 100644 --- a/typings/lib/parser/contents/index.d.ts +++ b/typings/lib/parser/contents/index.d.ts @@ -1,60 +1,29 @@ export = Parser; declare class Parser { - static "__#8@#memo": Map; - static "__#8@#clearMemo"(): void; - static "__#8@#createMemo"(): void; - static "__#8@#addToMemo"(classname: any, result: any): Map; - static parseResponse(data: any): { - contents: any; - contents_memo: Map; - on_response_received_actions: any; - on_response_received_actions_memo: Map; - on_response_received_endpoints: any; - on_response_received_endpoints_memo: Map; - on_response_received_commands: any; - on_response_received_commands_memo: Map; - /** @type {*} */ - continuation_contents: any; - metadata: any; - header: any; - /** @type {import('./classes/PlayerMicroformat')} **/ - microformat: import('./classes/PlayerMicroformat'); - sidebar: any; - overlay: any; - refinements: any; - estimated_results: any; - player_overlays: any; - playability_status: { - /** @type {number} */ - status: number; - error_screen: any; - /** @type {boolean} */ - embeddable: boolean; - /** @type {string} */ - reason: string; - }; - streaming_data: { - expires: Date; - /** @type {import('./classes/Format')[]} */ - formats: import('./classes/Format')[]; - /** @type {import('./classes/Format')[]} */ - adaptive_formats: import('./classes/Format')[]; - dash_manifest_url: any; - dls_manifest_url: any; - }; - captions: any; - video_details: VideoDetails; - annotations: any; - storyboards: any; - /** @type {import('./classes/Endscreen')} */ - endscreen: import('./classes/Endscreen'); - /** @type {import('./classes/CardCollection')} */ - cards: import('./classes/CardCollection'); - }; - static parseLC(data: any): SectionListContinuation; + static "__#5@#memo": Map; + static "__#5@#clearMemo"(): void; + static "__#5@#createMemo"(): void; + static "__#5@#addToMemo"(classname: any, result: any): Map; + /** + * Parses InnerTube response. + * + * @param {object} data + * @returns {*} + */ + static parseResponse(data: object): any; + static parseC(data: any): TimedContinuation; + static parseLC(data: any): SectionListContinuation | LiveChatContinuation; static parseRR(actions: any): any; + static parseLA(data: any): any; static parseFormats(formats: any): any; - static parse(data: any): any; + /** + * Parses the `contents` property of the response. + * + * @param {object} data + * @param {string} module + * @returns {*} + */ + static parse(data: object, module: string): any; static formatError({ classname, classdata, err }: { classname: any; classdata: any; @@ -63,10 +32,28 @@ declare class Parser { static sanitizeClassName(input: any): any; static shouldIgnore(classname: any): boolean; } -import VideoDetails = require("./classes/VideoDetails"); +declare class TimedContinuation { + constructor(data: any); + type: string; + timeout_ms: any; + token: any; +} declare class SectionListContinuation { constructor(data: any); type: string; contents: any; continuation: any; } +declare class LiveChatContinuation { + constructor(data: any); + type: string; + actions: any; + action_panel: any; + item_list: any; + header: any; + participants_list: any; + popout_message: any; + emojis: any; + continuation: TimedContinuation; + viewer_name: any; +} diff --git a/typings/lib/parser/youtube/Analytics.d.ts b/typings/lib/parser/youtube/Analytics.d.ts index bdea769c..c60ac0c8 100644 --- a/typings/lib/parser/youtube/Analytics.d.ts +++ b/typings/lib/parser/youtube/Analytics.d.ts @@ -6,43 +6,6 @@ declare class Analytics { */ constructor(response: object); sections: any; - get page(): { - contents: any; - contents_memo: Map; - on_response_received_actions: any; - on_response_received_actions_memo: Map; - on_response_received_endpoints: any; - on_response_received_endpoints_memo: Map; - on_response_received_commands: any; - on_response_received_commands_memo: Map; - continuation_contents: any; - metadata: any; - header: any; - microformat: import("../contents/classes/PlayerMicroformat"); - sidebar: any; - overlay: any; - refinements: any; - estimated_results: any; - player_overlays: any; - playability_status: { - status: number; - error_screen: any; - embeddable: boolean; - reason: string; - }; - streaming_data: { - expires: Date; - formats: import("../contents/classes/Format")[]; - adaptive_formats: import("../contents/classes/Format")[]; - dash_manifest_url: any; - dls_manifest_url: any; - }; - captions: any; - video_details: import("../contents/classes/VideoDetails"); - annotations: any; - storyboards: any; - endscreen: import("../contents/classes/Endscreen"); - cards: import("../contents/classes/CardCollection"); - }; + get page(): any; #private; } diff --git a/typings/lib/parser/youtube/Library.d.ts b/typings/lib/parser/youtube/Library.d.ts index e8114448..2bf1fed9 100644 --- a/typings/lib/parser/youtube/Library.d.ts +++ b/typings/lib/parser/youtube/Library.d.ts @@ -22,44 +22,7 @@ declare class Library { get liked_videos(): any; get playlists(): any; get clips(): any; - get page(): { - contents: any; - contents_memo: Map; - on_response_received_actions: any; - on_response_received_actions_memo: Map; - on_response_received_endpoints: any; - on_response_received_endpoints_memo: Map; - on_response_received_commands: any; - on_response_received_commands_memo: Map; - continuation_contents: any; - metadata: any; - header: any; - microformat: import("../contents/classes/PlayerMicroformat"); - sidebar: any; - overlay: any; - refinements: any; - estimated_results: any; - player_overlays: any; - playability_status: { - status: number; - error_screen: any; - embeddable: boolean; - reason: string; - }; - streaming_data: { - expires: Date; - formats: import("../contents/classes/Format")[]; - adaptive_formats: import("../contents/classes/Format")[]; - dash_manifest_url: any; - dls_manifest_url: any; - }; - captions: any; - video_details: import("../contents/classes/VideoDetails"); - annotations: any; - storyboards: any; - endscreen: import("../contents/classes/Endscreen"); - cards: import("../contents/classes/CardCollection"); - }; + get page(): any; #private; } import Playlist = require("./Playlist"); diff --git a/typings/lib/parser/youtube/LiveChat.d.ts b/typings/lib/parser/youtube/LiveChat.d.ts new file mode 100644 index 00000000..66c803c7 --- /dev/null +++ b/typings/lib/parser/youtube/LiveChat.d.ts @@ -0,0 +1,34 @@ +export = LiveChat; +declare class LiveChat { + /** + * @param {import('./VideoInfo')} video_info + */ + constructor(video_info: import('./VideoInfo')); + ev: EventEmitter; + initial_info: any; + live_metadata: { + /** @type {import('../contents/classes/livechat/metadata/UpdateTitleAction')} */ + title: any; + /** @type {import('../contents/classes/livechat/metadata/UpdateDescriptionAction')} */ + description: any; + /** @type {import('../contents/classes/livechat/metadata/UpdateViewershipAction')} */ + views: any; + /** @type {import('../contents/classes/livechat/metadata/UpdateTitleAction')} */ + likes: any; + /** @type {import('../contents/classes/livechat/metadata/UpdateDateTextAction')} */ + date: any; + }; + running: boolean; + is_replay: boolean; + start(): void; + stop(): void; + metadata: any; + /** + * Sends a message. + * @param {string} text + * @returns {Promise.} + */ + sendMessage(text: string): Promise; + #private; +} +import EventEmitter = require("events"); diff --git a/typings/lib/parser/youtube/VideoInfo.d.ts b/typings/lib/parser/youtube/VideoInfo.d.ts index 1616c4c2..12ebf247 100644 --- a/typings/lib/parser/youtube/VideoInfo.d.ts +++ b/typings/lib/parser/youtube/VideoInfo.d.ts @@ -12,19 +12,8 @@ declare class VideoInfo { * @type {import('../contents/classes/VideoDetails')} */ basic_info: import('../contents/classes/VideoDetails'); - streaming_data: { - expires: Date; - formats: import("../contents/classes/Format")[]; - adaptive_formats: import("../contents/classes/Format")[]; - dash_manifest_url: any; - dls_manifest_url: any; - }; - playability_status: { - status: number; - error_screen: any; - embeddable: boolean; - reason: string; - }; + streaming_data: any; + playability_status: any; /** * @type {import('../contents/classes/PlayerAnnotationsExpanded')[]} */ @@ -70,6 +59,10 @@ declare class VideoInfo { * @type {import('../contents/classes/CommentsEntryPointHeader')} */ comments_entry_point_header: import('../contents/classes/CommentsEntryPointHeader'); + /** + * @type {import('../contents/classes/LiveChat')} + */ + livechat: import('../contents/classes/LiveChat'); /** * Applies given filter to the watch next feed. * @@ -120,55 +113,22 @@ declare class VideoInfo { status_code: number; data: object; }>; + /** + * Retrieves Live Chat if available. + * + * @param {string} [mode] - livechat mode + * @returns {Promise.} + */ + getLiveChat(mode?: string): Promise; /** @type {string[]} */ get filters(): string[]; - get page(): { - contents: any; - contents_memo: Map; - on_response_received_actions: any; - on_response_received_actions_memo: Map; - on_response_received_endpoints: any; - on_response_received_endpoints_memo: Map; - on_response_received_commands: any; /** - * @type {import('../contents/classes/VideoPrimaryInfo')} - */ - on_response_received_commands_memo: Map; - continuation_contents: any; - metadata: any; - header: any; - microformat: import("../contents/classes/PlayerMicroformat"); - sidebar: any; - overlay: any; /** - * @type {import('../contents/classes/ChipCloud')} - */ - refinements: any; - estimated_results: any; - player_overlays: any; - playability_status: { - status: number; - error_screen: any; - embeddable: boolean; - reason: string; - }; - streaming_data: { - expires: Date; - formats: import("../contents/classes/Format")[]; - adaptive_formats: import("../contents/classes/Format")[]; - dash_manifest_url: any; - dls_manifest_url: any; - }; - captions: any; - video_details: import("../contents/classes/VideoDetails"); - annotations: any; - storyboards: any; - endscreen: import("../contents/classes/Endscreen"); - cards: import("../contents/classes/CardCollection"); - }[]; + get actions(): import("../../core/Actions"); + get page(): any[]; /** * Get songs used in the video. */ get music_tracks(): {}[]; - chooseFormat(options: any): import("../contents/classes/Format"); + chooseFormat(options: any): any; /** * * @param {object} options - download options. @@ -192,4 +152,5 @@ declare class VideoInfo { }, _stream?: PassThrough): PassThrough; #private; } +import LiveChat = require("./LiveChat"); import { PassThrough } from "stream"; diff --git a/typings/lib/parser/ytmusic/Album.d.ts b/typings/lib/parser/ytmusic/Album.d.ts index 3371936a..0249c86c 100644 --- a/typings/lib/parser/ytmusic/Album.d.ts +++ b/typings/lib/parser/ytmusic/Album.d.ts @@ -12,43 +12,7 @@ declare class Album { url: string; /** @type {import('../contents/classes/MusicResponsiveListItem')[]} */ contents: import('../contents/classes/MusicResponsiveListItem')[]; - get page(): { - contents: any; - contents_memo: Map; - on_response_received_actions: any; - on_response_received_actions_memo: Map; - on_response_received_endpoints: any; - on_response_received_endpoints_memo: Map; - on_response_received_commands: any; - on_response_received_commands_memo: Map; - continuation_contents: any; - metadata: any; - header: any; - microformat: import("../contents/classes/PlayerMicroformat"); - sidebar: any; - overlay: any; - refinements: any; - estimated_results: any; - player_overlays: any; - playability_status: { - status: number; - error_screen: any; - embeddable: boolean; - reason: string; - }; - streaming_data: { - expires: Date; - formats: import("../contents/classes/Format")[]; - adaptive_formats: import("../contents/classes/Format")[]; - dash_manifest_url: any; - dls_manifest_url: any; - }; - captions: any; - video_details: import("../contents/classes/VideoDetails"); - annotations: any; - storyboards: any; - endscreen: import("../contents/classes/Endscreen"); - cards: import("../contents/classes/CardCollection"); - }; + sections: any; + get page(): any; #private; } diff --git a/typings/lib/parser/ytmusic/Artist.d.ts b/typings/lib/parser/ytmusic/Artist.d.ts index 2b2d897d..b19ad03a 100644 --- a/typings/lib/parser/ytmusic/Artist.d.ts +++ b/typings/lib/parser/ytmusic/Artist.d.ts @@ -10,43 +10,6 @@ declare class Artist { /** @type {import('../contents/classes/MusicShelf')[] | import('../contents/classes/MusicCarouselShelf')[]} */ sections: import('../contents/classes/MusicShelf')[] | import('../contents/classes/MusicCarouselShelf')[]; getAllSongs(): Promise; - get page(): { - contents: any; - contents_memo: Map; - on_response_received_actions: any; - on_response_received_actions_memo: Map; - on_response_received_endpoints: any; - on_response_received_endpoints_memo: Map; - on_response_received_commands: any; - on_response_received_commands_memo: Map; - continuation_contents: any; - metadata: any; - header: any; - microformat: import("../contents/classes/PlayerMicroformat"); - sidebar: any; - overlay: any; - refinements: any; - estimated_results: any; - player_overlays: any; - playability_status: { - status: number; - error_screen: any; - embeddable: boolean; - reason: string; - }; - streaming_data: { - expires: Date; - formats: import("../contents/classes/Format")[]; - adaptive_formats: import("../contents/classes/Format")[]; - dash_manifest_url: any; - dls_manifest_url: any; - }; - captions: any; - video_details: import("../contents/classes/VideoDetails"); - annotations: any; - storyboards: any; - endscreen: import("../contents/classes/Endscreen"); - cards: import("../contents/classes/CardCollection"); - }; + get page(): any; #private; } diff --git a/typings/lib/parser/ytmusic/Explore.d.ts b/typings/lib/parser/ytmusic/Explore.d.ts index a856c591..84edcd47 100644 --- a/typings/lib/parser/ytmusic/Explore.d.ts +++ b/typings/lib/parser/ytmusic/Explore.d.ts @@ -7,43 +7,6 @@ declare class Explore { constructor(response: object); top_buttons: any; sections: any; - get page(): { - contents: any; - contents_memo: Map; - on_response_received_actions: any; - on_response_received_actions_memo: Map; - on_response_received_endpoints: any; - on_response_received_endpoints_memo: Map; - on_response_received_commands: any; - on_response_received_commands_memo: Map; - continuation_contents: any; - metadata: any; - header: any; - microformat: import("../contents/classes/PlayerMicroformat"); - sidebar: any; - overlay: any; - refinements: any; - estimated_results: any; - player_overlays: any; - playability_status: { - status: number; - error_screen: any; - embeddable: boolean; - reason: string; - }; - streaming_data: { - expires: Date; - formats: import("../contents/classes/Format")[]; - adaptive_formats: import("../contents/classes/Format")[]; - dash_manifest_url: any; - dls_manifest_url: any; - }; - captions: any; - video_details: import("../contents/classes/VideoDetails"); - annotations: any; - storyboards: any; - endscreen: import("../contents/classes/Endscreen"); - cards: import("../contents/classes/CardCollection"); - }; + get page(): any; #private; } diff --git a/typings/lib/parser/ytmusic/Library.d.ts b/typings/lib/parser/ytmusic/Library.d.ts index 7b9012a2..cd81e305 100644 --- a/typings/lib/parser/ytmusic/Library.d.ts +++ b/typings/lib/parser/ytmusic/Library.d.ts @@ -5,43 +5,6 @@ declare class Library { * @param {object} response - API response. */ constructor(response: object); - get page(): { - contents: any; - contents_memo: Map; - on_response_received_actions: any; - on_response_received_actions_memo: Map; - on_response_received_endpoints: any; - on_response_received_endpoints_memo: Map; - on_response_received_commands: any; - on_response_received_commands_memo: Map; - continuation_contents: any; - metadata: any; - header: any; - microformat: import("../contents/classes/PlayerMicroformat"); - sidebar: any; - overlay: any; - refinements: any; - estimated_results: any; - player_overlays: any; - playability_status: { - status: number; - error_screen: any; - embeddable: boolean; - reason: string; - }; - streaming_data: { - expires: Date; - formats: import("../contents/classes/Format")[]; - adaptive_formats: import("../contents/classes/Format")[]; - dash_manifest_url: any; - dls_manifest_url: any; - }; - captions: any; - video_details: import("../contents/classes/VideoDetails"); - annotations: any; - storyboards: any; - endscreen: import("../contents/classes/Endscreen"); - cards: import("../contents/classes/CardCollection"); - }; + get page(): any; #private; }