diff --git a/src/Innertube.ts b/src/Innertube.ts index a6b376d55..4ee845b3a 100644 --- a/src/Innertube.ts +++ b/src/Innertube.ts @@ -1,29 +1,8 @@ -import type { SessionOptions } from './core/Session.js'; import Session from './core/Session.js'; - -import NavigationEndpoint from './parser/classes/NavigationEndpoint.js'; -import type Format from './parser/classes/misc/Format.js'; -import Channel from './parser/youtube/Channel.js'; -import Comments from './parser/youtube/Comments.js'; -import Guide from './parser/youtube/Guide.js'; -import HashtagFeed from './parser/youtube/HashtagFeed.js'; -import History from './parser/youtube/History.js'; -import HomeFeed from './parser/youtube/HomeFeed.js'; -import Library from './parser/youtube/Library.js'; -import NotificationsMenu from './parser/youtube/NotificationsMenu.js'; -import Playlist from './parser/youtube/Playlist.js'; -import Search from './parser/youtube/Search.js'; -import VideoInfo from './parser/youtube/VideoInfo.js'; -import ShortsVideoInfo from './parser/ytshorts/VideoInfo.js'; - import { Kids, Music, Studio } from './core/clients/index.js'; import { AccountManager, InteractionManager, PlaylistManager } from './core/managers/index.js'; import { Feed, TabbedFeed } from './core/mixins/index.js'; -import * as Proto from './proto/index.js'; -import * as Constants from './utils/Constants.js'; -import { InnertubeError, generateRandomString, throwIfMissing } from './utils/Utils.js'; - import { BrowseEndpoint, GetNotificationMenuEndpoint, @@ -32,16 +11,39 @@ import { PlayerEndpoint, ResolveURLEndpoint, SearchEndpoint, - Reel + Reel, + Notification } from './core/endpoints/index.js'; -import { GetUnseenCountEndpoint } from './core/endpoints/notification/index.js'; +import { + Channel, + Comments, + Guide, + HashtagFeed, + History, + HomeFeed, + Library, + NotificationsMenu, + Playlist, + Search, + VideoInfo +} from './parser/youtube/index.js'; + +import { VideoInfo as ShortsVideoInfo } from './parser/ytshorts/index.js'; + +import NavigationEndpoint from './parser/classes/NavigationEndpoint.js'; + +import * as Proto from './proto/index.js'; +import * as Constants from './utils/Constants.js'; +import { InnertubeError, generateRandomString, throwIfMissing } from './utils/Utils.js'; + import type { ApiResponse } from './core/Actions.js'; -import { type IBrowseResponse, type IParsedResponse } from './parser/types/index.js'; import type { INextRequest } from './types/index.js'; +import type { IBrowseResponse, IParsedResponse } from './parser/types/index.js'; import type { DownloadOptions, FormatOptions } from './types/FormatUtils.js'; -import { encodeReelSequence } from './proto/index.js'; +import type { SessionOptions } from './core/Session.js'; +import type Format from './parser/classes/misc/Format.js'; export type InnertubeConfig = SessionOptions; @@ -151,7 +153,7 @@ export default class Innertube { const sequenceResponse = this.actions.execute( Reel.WatchSequenceEndpoint.PATH, Reel.WatchSequenceEndpoint.build({ - sequenceParams: encodeReelSequence(short_id) + sequenceParams: Proto.encodeReelSequence(short_id) }) ); @@ -261,7 +263,7 @@ export default class Innertube { } /** - * Retrieves trending content. + * Retrieves Trending content. */ async getTrending(): Promise> { const response = await this.actions.execute( @@ -271,7 +273,7 @@ export default class Innertube { } /** - * Retrieves subscriptions feed. + * Retrieves Subscriptions feed. */ async getSubscriptionsFeed(): Promise> { const response = await this.actions.execute( @@ -281,7 +283,7 @@ export default class Innertube { } /** - * Retrieves channels feed. + * Retrieves Channels feed. */ async getChannelsFeed(): Promise> { const response = await this.actions.execute( @@ -318,7 +320,7 @@ export default class Innertube { * Retrieves unseen notifications count. */ async getUnseenNotificationsCount(): Promise { - const response = await this.actions.execute(GetUnseenCountEndpoint.PATH); + const response = await this.actions.execute(Notification.GetUnseenCountEndpoint.PATH); // TODO: properly parse this return response.data?.unseenCount || response.data?.actions?.[0].updateNotificationsUnseenCountAction?.unseenCount || 0; } diff --git a/src/core/Actions.ts b/src/core/Actions.ts index 30461675d..fda837a7d 100644 --- a/src/core/Actions.ts +++ b/src/core/Actions.ts @@ -1,7 +1,7 @@ import { Parser, NavigateAction } from '../parser/index.js'; import { InnertubeError } from '../utils/Utils.js'; -import type Session from './Session.js'; +import type { Session } from './index.js'; import type { IBrowseResponse, IGetNotificationsMenuResponse, diff --git a/src/core/OAuth.ts b/src/core/OAuth.ts index 3b973c167..a6e02e771 100644 --- a/src/core/OAuth.ts +++ b/src/core/OAuth.ts @@ -1,4 +1,4 @@ -import * as Constants from '../utils/Constants.js'; +import { Log, Constants } from '../utils/index.js'; import { OAuthError, Platform } from '../utils/Utils.js'; import type Session from './Session.js'; @@ -45,6 +45,8 @@ export type OAuthClientIdentity = { }; export default class OAuth { + static TAG = 'OAuth'; + #identity?: Record; #session: Session; #credentials?: Credentials; @@ -250,6 +252,7 @@ export default class OAuth { */ async #getClientIdentity(): Promise { if (this.#credentials?.client_id && this.credentials?.client_secret) { + Log.info(OAuth.TAG, 'Using custom OAuth2 credentials.\n'); return { client_id: this.#credentials.client_id, client_secret: this.credentials.client_secret @@ -264,6 +267,8 @@ export default class OAuth { if (!url_body) throw new OAuthError('Could not obtain script url.', { status: 'FAILED' }); + Log.info(OAuth.TAG, `Got YouTubeTV script URL (${url_body})`); + const script = await this.#session.http.fetch(url_body, { baseURL: Constants.URLS.YT_BASE }); const client_identity = (await script.text()) @@ -275,6 +280,8 @@ export default class OAuth { if (!groups) throw new OAuthError('Could not obtain client identity.', { status: 'FAILED' }); + Log.info(OAuth.TAG, 'OAuth2 credentials retrieved.\n', groups); + return groups; } diff --git a/src/core/Player.ts b/src/core/Player.ts index bb2dd3117..4df4b8189 100644 --- a/src/core/Player.ts +++ b/src/core/Player.ts @@ -1,14 +1,13 @@ +import { Log, Constants } from '../utils/index.js'; import { Platform, getRandomUserAgent, getStringBetweenStrings, PlayerError } from '../utils/Utils.js'; - -import * as Constants from '../utils/Constants.js'; - -import type { ICache } from '../types/Cache.js'; -import type { FetchFunction } from '../types/PlatformShim.js'; +import type { ICache, FetchFunction } from '../types/index.js'; /** * Represents YouTube's player script. This is required to decipher signatures. */ export default class Player { + static TAG = 'Player'; + #nsig_sc; #sig_sc; #sig_sc_timestamp; @@ -17,9 +16,7 @@ export default class Player { constructor(signature_timestamp: number, sig_sc: string, nsig_sc: string, player_id: string) { this.#nsig_sc = nsig_sc; this.#sig_sc = sig_sc; - this.#sig_sc_timestamp = signature_timestamp; - this.#player_id = player_id; } @@ -34,11 +31,14 @@ export default class Player { const player_id = getStringBetweenStrings(js, 'player\\/', '\\/'); + Log.info(Player.TAG, `Got player id (${player_id}). Checking for cached players..`); + if (!player_id) throw new PlayerError('Failed to get player id'); - // We have the playerID now we can check if we have a cached player + // We have the player id, now we can check if we have a cached player. if (cache) { + Log.info(Player.TAG, 'Found a cached player.'); const cached_player = await Player.fromCache(cache, player_id); if (cached_player) return cached_player; @@ -46,6 +46,8 @@ export default class Player { const player_url = new URL(`/s/player/${player_id}/player_ias.vflset/en_US/base.js`, Constants.URLS.YT_BASE); + Log.info(Player.TAG, `Could not find any cached player. Will download a new player from ${player_url}.`); + const player_res = await fetch(player_url, { headers: { 'user-agent': getRandomUserAgent('desktop') @@ -59,10 +61,11 @@ export default class Player { const player_js = await player_res.text(); const sig_timestamp = this.extractSigTimestamp(player_js); - const sig_sc = this.extractSigSourceCode(player_js); const nsig_sc = this.extractNSigSourceCode(player_js); + Log.info(Player.TAG, `Got signature timestamp (${sig_timestamp}) and algorithms needed to decipher signatures.`); + return await Player.fromSource(cache, sig_timestamp, sig_sc, nsig_sc, player_id); } @@ -80,6 +83,8 @@ export default class Player { sig: args.get('s') }); + Log.info(Player.TAG, `Transformed signature ${args.get('s')} to ${signature}.`); + if (typeof signature !== 'string') throw new PlayerError('Failed to decipher signature'); @@ -102,11 +107,13 @@ export default class Player { nsig: n }); + Log.info(Player.TAG, `Transformed nsig ${n} to ${nsig}.`); + if (typeof nsig !== 'string') throw new PlayerError('Failed to decipher nsig'); if (nsig.startsWith('enhanced_except_')) { - console.warn('Warning:\nCould not transform nsig, download may be throttled.\nChanging the InnerTube client to "ANDROID" might help!'); + Log.warn(Player.TAG, 'Could not transform nsig, download may be throttled.\nChanging the InnerTube client to "ANDROID" might help!'); } else if (this_response_nsig_cache) { this_response_nsig_cache.set(n, nsig); } @@ -138,6 +145,10 @@ export default class Player { break; } + const result = url_components.toString(); + + Log.info(Player.TAG, `Full deciphered URL: ${result}`); + return url_components.toString(); } @@ -204,7 +215,7 @@ export default class Player { const functions = getStringBetweenStrings(data, `var ${obj_name}={`, '};'); if (!functions || !calls) - console.warn(new PlayerError('Failed to extract signature decipher algorithm')); + Log.warn(Player.TAG, 'Failed to extract signature decipher algorithm.'); return `function descramble_sig(a) { a = a.split(""); let ${obj_name}={${functions}}${calls} return a.join("") } descramble_sig(sig);`; } @@ -213,7 +224,7 @@ export default class Player { const sc = `function descramble_nsig(a) { let b=a.split("")${getStringBetweenStrings(data, 'b=a.split("")', '}return b.join("")}')}} return b.join(""); } descramble_nsig(nsig)`; if (!sc) - console.warn(new PlayerError('Failed to extract n-token decipher algorithm')); + Log.warn(Player.TAG, 'Failed to extract n-token decipher algorithm'); return sc; } diff --git a/src/core/Session.ts b/src/core/Session.ts index f0e49e827..e3d7bea47 100644 --- a/src/core/Session.ts +++ b/src/core/Session.ts @@ -1,16 +1,19 @@ +import { Player, OAuth, Actions } from './index.js'; +import { Log, EventEmitter, HTTPClient } from '../utils/index.js'; import * as Constants from '../utils/Constants.js'; -import EventEmitterLike from '../utils/EventEmitterLike.js'; -import Actions from './Actions.js'; -import Player from './Player.js'; - import * as Proto from '../proto/index.js'; -import type { ICache } from '../types/Cache.js'; -import type { FetchFunction } from '../types/PlatformShim.js'; -import HTTPClient from '../utils/HTTPClient.js'; + +import { + generateRandomString, getRandomUserAgent, + InnertubeError, Platform, SessionError +} from '../utils/Utils.js'; + import type { DeviceCategory } from '../utils/Utils.js'; -import { generateRandomString, getRandomUserAgent, InnertubeError, Platform, SessionError } from '../utils/Utils.js'; -import type { Credentials, OAuthAuthErrorEventHandler, OAuthAuthEventHandler, OAuthAuthPendingEventHandler } from './OAuth.js'; -import OAuth from './OAuth.js'; +import type { FetchFunction, ICache } from '../types/index.js'; +import type { + Credentials, OAuthAuthErrorEventHandler, + OAuthAuthEventHandler, OAuthAuthPendingEventHandler +} from './OAuth.js'; export enum ClientType { WEB = 'WEB', @@ -140,10 +143,23 @@ export interface SessionData { api_version: string; } +export type SessionArgs = { + lang: string; + location: string; + time_zone: string; + device_category: DeviceCategory; + client_name: ClientType; + enable_safety_mode: boolean; + visitor_data: string; + on_behalf_of_user: string | undefined; +} + /** * Represents an InnerTube session. This holds all the data needed to make requests to YouTube. */ -export default class Session extends EventEmitterLike { +export default class Session extends EventEmitter { + static TAG = 'Session'; + #api_version: string; #key: string; #context: Context; @@ -226,6 +242,8 @@ export default class Session extends EventEmitterLike { const session_args = { lang, location, time_zone: tz, device_category, client_name, enable_safety_mode, visitor_data, on_behalf_of_user }; + Log.info(Session.TAG, 'Retrieving InnerTube session.'); + if (generate_session_locally) { session_data = this.#generateSessionData(session_args); } else { @@ -233,30 +251,29 @@ export default class Session extends EventEmitterLike { // This can fail if the data changes or the request is blocked for some reason. session_data = await this.#retrieveSessionData(session_args, fetch); } catch (err) { + Log.error(Session.TAG, 'Failed to retrieve session data from server. Will try to generate it locally.'); session_data = this.#generateSessionData(session_args); } } + Log.info(Session.TAG, 'Got session data.\n', session_data); + return { ...session_data, account_index }; } - static async #retrieveSessionData(options: { - lang: string; - location: string; - time_zone: string; - device_category: string; - client_name: string; - enable_safety_mode: boolean; - visitor_data: string; - on_behalf_of_user?: string; - }, fetch: FetchFunction = Platform.shim.fetch): Promise { + static #getVisitorID(visitor_data: string) { + const decoded_visitor_data = Proto.decodeVisitorData(visitor_data); + Log.info(Session.TAG, 'Custom visitor data decoded successfully.\n', decoded_visitor_data); + return decoded_visitor_data.id; + } + + static async #retrieveSessionData(options: SessionArgs, fetch: FetchFunction = Platform.shim.fetch): Promise { const url = new URL('/sw.js_data', Constants.URLS.YT_BASE); let visitor_id = generateRandomString(11); if (options.visitor_data) { - const decoded_visitor_data = Proto.decodeVisitorData(options.visitor_data); - visitor_id = decoded_visitor_data.id; + visitor_id = this.#getVisitorID(options.visitor_data); } const res = await fetch(url, { @@ -316,21 +333,11 @@ export default class Session extends EventEmitterLike { return { context, api_key, api_version }; } - static #generateSessionData(options: { - lang: string; - location: string; - time_zone: string; - device_category: DeviceCategory; - client_name: string; - enable_safety_mode: boolean; - visitor_data: string; - on_behalf_of_user?: string; - }): SessionData { + static #generateSessionData(options: SessionArgs): SessionData { let visitor_id = generateRandomString(11); if (options.visitor_data) { - const decoded_visitor_data = Proto.decodeVisitorData(options.visitor_data); - visitor_id = decoded_visitor_data.id; + visitor_id = this.#getVisitorID(options.visitor_data); } const context: Context = { diff --git a/src/core/clients/Kids.ts b/src/core/clients/Kids.ts index ab9d53cb9..43caedc36 100644 --- a/src/core/clients/Kids.ts +++ b/src/core/clients/Kids.ts @@ -1,12 +1,7 @@ import { Parser } from '../../parser/index.js'; -import Channel from '../../parser/ytkids/Channel.js'; -import HomeFeed from '../../parser/ytkids/HomeFeed.js'; -import Search from '../../parser/ytkids/Search.js'; -import VideoInfo from '../../parser/ytkids/VideoInfo.js'; -import type Session from '../Session.js'; -import { type ApiResponse } from '../Actions.js'; - +import { Channel, HomeFeed, Search, VideoInfo } from '../../parser/ytkids/index.js'; import { InnertubeError, generateRandomString } from '../../utils/Utils.js'; +import KidsBlocklistPickerItem from '../../parser/classes/ytkids/KidsBlocklistPickerItem.js'; import { BrowseEndpoint, NextEndpoint, @@ -15,7 +10,7 @@ import { import { BlocklistPickerEndpoint } from '../endpoints/kids/index.js'; -import KidsBlocklistPickerItem from '../../parser/classes/ytkids/KidsBlocklistPickerItem.js'; +import type { Session, ApiResponse } from '../index.js'; export default class Kids { #session: Session; diff --git a/src/core/clients/Music.ts b/src/core/clients/Music.ts index 5bc20040d..9820bf9f4 100644 --- a/src/core/clients/Music.ts +++ b/src/core/clients/Music.ts @@ -1,12 +1,11 @@ -import Album from '../../parser/ytmusic/Album.js'; -import Artist from '../../parser/ytmusic/Artist.js'; -import Explore from '../../parser/ytmusic/Explore.js'; -import HomeFeed from '../../parser/ytmusic/HomeFeed.js'; -import Library from '../../parser/ytmusic/Library.js'; -import Playlist from '../../parser/ytmusic/Playlist.js'; -import Recap from '../../parser/ytmusic/Recap.js'; -import Search from '../../parser/ytmusic/Search.js'; -import TrackInfo from '../../parser/ytmusic/TrackInfo.js'; +import * as Proto from '../../proto/index.js'; +import { InnertubeError, generateRandomString, throwIfMissing } from '../../utils/Utils.js'; + +import { + Album, Artist, Explore, + HomeFeed, Library, Playlist, + Recap, Search, TrackInfo +} from '../../parser/ytmusic/index.js'; import AutomixPreviewVideo from '../../parser/classes/AutomixPreviewVideo.js'; import Message from '../../parser/classes/Message.js'; @@ -18,13 +17,6 @@ import PlaylistPanel from '../../parser/classes/PlaylistPanel.js'; import SearchSuggestionsSection from '../../parser/classes/SearchSuggestionsSection.js'; import SectionList from '../../parser/classes/SectionList.js'; import Tab from '../../parser/classes/Tab.js'; -import * as Proto from '../../proto/index.js'; - -import type { ObservedArray } from '../../parser/helpers.js'; -import type { MusicSearchFilters } from '../../types/index.js'; -import { InnertubeError, generateRandomString, throwIfMissing } from '../../utils/Utils.js'; -import type Actions from '../Actions.js'; -import type Session from '../Session.js'; import { BrowseEndpoint, @@ -35,6 +27,10 @@ import { import { GetSearchSuggestionsEndpoint } from '../endpoints/music/index.js'; +import type { ObservedArray } from '../../parser/helpers.js'; +import type { MusicSearchFilters } from '../../types/index.js'; +import type { Actions, Session } from '../index.js'; + export default class Music { #session: Session; #actions: Actions; diff --git a/src/core/clients/Studio.ts b/src/core/clients/Studio.ts index ceaa70ed3..81ebd31c2 100644 --- a/src/core/clients/Studio.ts +++ b/src/core/clients/Studio.ts @@ -1,12 +1,10 @@ import * as Proto from '../../proto/index.js'; -import * as Constants from '../../utils/Constants.js'; +import { Constants } from '../../utils/index.js'; import { InnertubeError, MissingParamError, Platform } from '../../utils/Utils.js'; +import { CreateVideoEndpoint } from '../endpoints/upload/index.js'; import type { UpdateVideoMetadataOptions, UploadedVideoMetadataOptions } from '../../types/Clients.js'; -import type { ApiResponse } from '../Actions.js'; -import type Session from '../Session.js'; - -import { CreateVideoEndpoint } from '../endpoints/upload/index.js'; +import type { ApiResponse, Session } from '../index.js'; interface UploadResult { status: string; diff --git a/src/core/managers/AccountManager.ts b/src/core/managers/AccountManager.ts index 9ae8c8ea5..a5bf551dc 100644 --- a/src/core/managers/AccountManager.ts +++ b/src/core/managers/AccountManager.ts @@ -1,3 +1,5 @@ +import type { Actions, ApiResponse } from '../index.js'; + import AccountInfo from '../../parser/youtube/AccountInfo.js'; import Analytics from '../../parser/youtube/Analytics.js'; import Settings from '../../parser/youtube/Settings.js'; @@ -7,9 +9,6 @@ import * as Proto from '../../proto/index.js'; import { InnertubeError } from '../../utils/Utils.js'; import { Account, BrowseEndpoint, Channel } from '../endpoints/index.js'; -import type Actions from '../Actions.js'; -import type { ApiResponse } from '../Actions.js'; - export default class AccountManager { #actions: Actions; diff --git a/src/core/managers/InteractionManager.ts b/src/core/managers/InteractionManager.ts index 8859ae4f2..adfadfbe7 100644 --- a/src/core/managers/InteractionManager.ts +++ b/src/core/managers/InteractionManager.ts @@ -1,6 +1,4 @@ import * as Proto from '../../proto/index.js'; -import type Actions from '../Actions.js'; -import type { ApiResponse } from '../Actions.js'; import { throwIfMissing } from '../../utils/Utils.js'; import { LikeEndpoint, DislikeEndpoint, RemoveLikeEndpoint } from '../endpoints/like/index.js'; @@ -8,6 +6,8 @@ import { SubscribeEndpoint, UnsubscribeEndpoint } from '../endpoints/subscriptio import { CreateCommentEndpoint, PerformCommentActionEndpoint } from '../endpoints/comment/index.js'; import { ModifyChannelPreferenceEndpoint } from '../endpoints/notification/index.js'; +import type { Actions, ApiResponse } from '../index.js'; + export default class InteractionManager { #actions: Actions; diff --git a/src/core/managers/PlaylistManager.ts b/src/core/managers/PlaylistManager.ts index e9d5ff6d7..7c1cc8f16 100644 --- a/src/core/managers/PlaylistManager.ts +++ b/src/core/managers/PlaylistManager.ts @@ -1,12 +1,12 @@ -import Playlist from '../../parser/youtube/Playlist.js'; -import type Actions from '../Actions.js'; -import type Feed from '../mixins/Feed.js'; - -import type { EditPlaylistEndpointOptions } from '../../types/index.js'; import { InnertubeError, throwIfMissing } from '../../utils/Utils.js'; import { EditPlaylistEndpoint } from '../endpoints/browse/index.js'; import { BrowseEndpoint } from '../endpoints/index.js'; import { CreateEndpoint, DeleteEndpoint } from '../endpoints/playlist/index.js'; +import Playlist from '../../parser/youtube/Playlist.js'; + +import type { Actions } from '../index.js'; +import type { Feed } from '../mixins/index.js'; +import type { EditPlaylistEndpointOptions } from '../../types/index.js'; export default class PlaylistManager { #actions: Actions; diff --git a/src/core/mixins/Feed.ts b/src/core/mixins/Feed.ts index 4f995a264..5c4906521 100644 --- a/src/core/mixins/Feed.ts +++ b/src/core/mixins/Feed.ts @@ -1,7 +1,5 @@ -import type { Memo, ObservedArray, SuperParsedResult, YTNode } from '../../parser/helpers.js'; import { Parser, ReloadContinuationItemsCommand } from '../../parser/index.js'; import { concatMemos, InnertubeError } from '../../utils/Utils.js'; -import type Actions from '../Actions.js'; import BackstagePost from '../../parser/classes/BackstagePost.js'; import SharedPost from '../../parser/classes/SharedPost.js'; @@ -27,12 +25,15 @@ import TwoColumnBrowseResults from '../../parser/classes/TwoColumnBrowseResults. import TwoColumnSearchResults from '../../parser/classes/TwoColumnSearchResults.js'; import WatchCardCompactVideo from '../../parser/classes/WatchCardCompactVideo.js'; +import type { ApiResponse, Actions } from '../index.js'; +import type { + Memo, ObservedArray, + SuperParsedResult, YTNode +} from '../../parser/helpers.js'; import type MusicQueue from '../../parser/classes/MusicQueue.js'; import type RichGrid from '../../parser/classes/RichGrid.js'; import type SectionList from '../../parser/classes/SectionList.js'; - import type { IParsedResponse } from '../../parser/types/index.js'; -import type { ApiResponse } from '../Actions.js'; export default class Feed { #page: T; @@ -212,10 +213,10 @@ export default class Feed { #getBodyContinuations(): ObservedArray { if (this.#page.header_memo) { const header_continuations = this.#page.header_memo.getType(ContinuationItem); - - return this.#memo.getType(ContinuationItem).filter((continuation) => !header_continuations.includes(continuation)) as ObservedArray; + return this.#memo.getType(ContinuationItem).filter( + (continuation) => !header_continuations.includes(continuation) + ) as ObservedArray; } - return this.#memo.getType(ContinuationItem); } } \ No newline at end of file diff --git a/src/core/mixins/FilterableFeed.ts b/src/core/mixins/FilterableFeed.ts index 0f57d6a4a..1ca892467 100644 --- a/src/core/mixins/FilterableFeed.ts +++ b/src/core/mixins/FilterableFeed.ts @@ -1,12 +1,11 @@ +import Feed from './Feed.js'; import ChipCloudChip from '../../parser/classes/ChipCloudChip.js'; import FeedFilterChipBar from '../../parser/classes/FeedFilterChipBar.js'; import { InnertubeError } from '../../utils/Utils.js'; -import Feed from './Feed.js'; import type { ObservedArray } from '../../parser/helpers.js'; -import type { IParsedResponse } from '../../parser/types/ParsedResponse.js'; -import type Actions from '../Actions.js'; -import type { ApiResponse } from '../Actions.js'; +import type { IParsedResponse } from '../../parser/types/index.js'; +import type { ApiResponse, Actions } from '../index.js'; export default class FilterableFeed extends Feed { #chips?: ObservedArray; diff --git a/src/core/mixins/MediaInfo.ts b/src/core/mixins/MediaInfo.ts index a34a3dc33..2dac69191 100644 --- a/src/core/mixins/MediaInfo.ts +++ b/src/core/mixins/MediaInfo.ts @@ -1,16 +1,17 @@ -import type { ApiResponse } from '../Actions.js'; -import type Actions from '../Actions.js'; -import * as Constants from '../../utils/Constants.js'; -import type { DownloadOptions, FormatFilter, FormatOptions, URLTransformer } from '../../types/FormatUtils.js'; -import * as FormatUtils from '../../utils/FormatUtils.js'; +import { Constants, FormatUtils } from '../../utils/index.js'; import { InnertubeError } from '../../utils/Utils.js'; -import type Format from '../../parser/classes/misc/Format.js'; -import type { INextResponse, IPlayerConfig, IPlayerResponse } from '../../parser/index.js'; -import { Parser } from '../../parser/index.js'; -import type { DashOptions } from '../../types/DashOptions.js'; import { getStreamingInfo } from '../../utils/StreamingInfo.js'; + +import { Parser } from '../../parser/index.js'; +import { TranscriptInfo } from '../../parser/youtube/index.js'; +import PlayerStoryboardSpec from '../../parser/classes/PlayerStoryboardSpec.js'; import ContinuationItem from '../../parser/classes/ContinuationItem.js'; -import TranscriptInfo from '../../parser/youtube/TranscriptInfo.js'; + +import type { ApiResponse, Actions } from '../index.js'; +import type { INextResponse, IPlayerConfig, IPlayerResponse } from '../../parser/index.js'; +import type { DownloadOptions, FormatFilter, FormatOptions, URLTransformer } from '../../types/FormatUtils.js'; +import type Format from '../../parser/classes/misc/Format.js'; +import type { DashOptions } from '../../types/DashOptions.js'; export default class MediaInfo { #page: [IPlayerResponse, INextResponse?]; diff --git a/src/core/mixins/TabbedFeed.ts b/src/core/mixins/TabbedFeed.ts index 9cc67e2a5..3a509f011 100644 --- a/src/core/mixins/TabbedFeed.ts +++ b/src/core/mixins/TabbedFeed.ts @@ -1,11 +1,10 @@ -import Tab from '../../parser/classes/Tab.js'; -import Feed from './Feed.js'; +import { Feed } from './index.js'; import { InnertubeError } from '../../utils/Utils.js'; +import Tab from '../../parser/classes/Tab.js'; -import type Actions from '../Actions.js'; +import type { Actions, ApiResponse } from '../index.js'; import type { ObservedArray } from '../../parser/helpers.js'; import type { IParsedResponse } from '../../parser/types/ParsedResponse.js'; -import type { ApiResponse } from '../Actions.js'; export default class TabbedFeed extends Feed { #tabs?: ObservedArray; diff --git a/src/parser/classes/Channel.ts b/src/parser/classes/Channel.ts index a9db9430f..d1a236eac 100644 --- a/src/parser/classes/Channel.ts +++ b/src/parser/classes/Channel.ts @@ -1,3 +1,4 @@ +import { Log } from '../../utils/index.js'; import { YTNode } from '../helpers.js'; import { Parser, type RawNode } from '../index.js'; import Button from './Button.js'; @@ -44,6 +45,7 @@ export default class Channel extends YTNode { * Please use {@link Channel.subscriber_count} instead. */ get subscribers(): Text { + Log.warnOnce(Channel.type, 'Channel#subscribers is deprecated. Please use Channel#subscriber_count instead.'); return this.subscriber_count; } @@ -53,6 +55,7 @@ export default class Channel extends YTNode { * Please use {@link Channel.video_count} instead. */ get videos(): Text { + Log.warnOnce(Channel.type, 'Channel#videos is deprecated. Please use Channel#video_count instead.'); return this.video_count; } } \ No newline at end of file diff --git a/src/parser/classes/ChannelAboutFullMetadata.ts b/src/parser/classes/ChannelAboutFullMetadata.ts index 699996cb6..e7a133ee1 100644 --- a/src/parser/classes/ChannelAboutFullMetadata.ts +++ b/src/parser/classes/ChannelAboutFullMetadata.ts @@ -1,3 +1,4 @@ +import { Log } from '../../utils/index.js'; import { YTNode, type ObservedArray } from '../helpers.js'; import { Parser, type RawNode } from '../index.js'; import Button from './Button.js'; @@ -55,6 +56,7 @@ export default class ChannelAboutFullMetadata extends YTNode { * Please use {@link Channel.view_count} instead. */ get views() { + Log.warnOnce(ChannelAboutFullMetadata.type, 'ChannelAboutFullMetadata#views is deprecated. Please use ChannelAboutFullMetadata#view_count instead.'); return this.view_count; } @@ -64,6 +66,7 @@ export default class ChannelAboutFullMetadata extends YTNode { * Please use {@link Channel.joined_date} instead. */ get joined(): Text { + Log.warnOnce(ChannelAboutFullMetadata.type, 'ChannelAboutFullMetadata#joined is deprecated. Please use ChannelAboutFullMetadata#joined_date instead.'); return this.joined_date; } } \ No newline at end of file diff --git a/src/parser/classes/ChannelVideoPlayer.ts b/src/parser/classes/ChannelVideoPlayer.ts index a93c875ed..d59cdb66f 100644 --- a/src/parser/classes/ChannelVideoPlayer.ts +++ b/src/parser/classes/ChannelVideoPlayer.ts @@ -1,6 +1,7 @@ import Text from './misc/Text.js'; import { YTNode } from '../helpers.js'; import type { RawNode } from '../index.js'; +import { Log } from '../../utils/index.js'; export default class ChannelVideoPlayer extends YTNode { static type = 'ChannelVideoPlayer'; @@ -26,6 +27,7 @@ export default class ChannelVideoPlayer extends YTNode { * Please use {@link ChannelVideoPlayer.view_count} instead. */ get views(): Text { + Log.warnOnce(ChannelVideoPlayer.type, 'ChannelVideoPlayer#views is deprecated. Please use ChannelVideoPlayer#view_count instead.'); return this.view_count; } @@ -35,6 +37,7 @@ export default class ChannelVideoPlayer extends YTNode { * Please use {@link ChannelVideoPlayer.published_time} instead. */ get published(): Text { + Log.warnOnce(ChannelVideoPlayer.type, 'ChannelVideoPlayer#published is deprecated. Please use ChannelVideoPlayer#published_time instead.'); return this.published_time; } } \ No newline at end of file diff --git a/src/parser/continuations.ts b/src/parser/continuations.ts index 2af988122..fb48c3b1d 100644 --- a/src/parser/continuations.ts +++ b/src/parser/continuations.ts @@ -1,10 +1,11 @@ -import type { ObservedArray } from './helpers.js'; import { YTNode, observe } from './helpers.js'; -import type { RawNode } from './index.js'; import { Thumbnail } from './misc.js'; import { NavigationEndpoint, LiveChatItemList, LiveChatHeader, LiveChatParticipantsList, Message } from './nodes.js'; import * as Parser from './parser.js'; +import type { RawNode } from './index.js'; +import type { ObservedArray } from './helpers.js'; + export class ItemSectionContinuation extends YTNode { static readonly type = 'itemSectionContinuation'; diff --git a/src/parser/generator.ts b/src/parser/generator.ts index 7a3a5b580..b0da05b54 100644 --- a/src/parser/generator.ts +++ b/src/parser/generator.ts @@ -1,12 +1,14 @@ /* eslint-disable no-cond-assign */ +import { YTNode } from './helpers.js'; +import { Parser } from './index.js'; import { InnertubeError } from '../utils/Utils.js'; + import Author from './classes/misc/Author.js'; import Text from './classes/misc/Text.js'; import Thumbnail from './classes/misc/Thumbnail.js'; import NavigationEndpoint from './classes/NavigationEndpoint.js'; + import type { YTNodeConstructor } from './helpers.js'; -import { YTNode } from './helpers.js'; -import * as Parser from './parser.js'; export type MiscInferenceType = { type: 'misc', diff --git a/src/parser/helpers.ts b/src/parser/helpers.ts index 75050085b..a49da0adc 100644 --- a/src/parser/helpers.ts +++ b/src/parser/helpers.ts @@ -1,3 +1,4 @@ +import Log from '../utils/Log.js'; import { deepCompare, ParsingError } from '../utils/Utils.js'; const isObserved = Symbol('ObservedArray.isObserved'); @@ -62,6 +63,7 @@ export class YTNode { } export class Maybe { + #TAG = 'Maybe'; #value; constructor (value: any) { @@ -275,10 +277,11 @@ export class Maybe { } /** - * @deprecated This call is not meant to be used outside of debugging. Please use the specific type getter instead. + * @deprecated + * This call is not meant to be used outside of debugging. Please use the specific type getter instead. */ any(): any { - console.warn('This call is not meant to be used outside of debugging. Please use the specific type getter instead.'); + Log.warn(this.#TAG, 'This call is not meant to be used outside of debugging. Please use the specific type getter instead.'); return this.#value; } diff --git a/src/parser/parser.ts b/src/parser/parser.ts index 0c0ee4ddb..9f2bb4d46 100644 --- a/src/parser/parser.ts +++ b/src/parser/parser.ts @@ -1,3 +1,16 @@ +import { YTNodes } from './index.js'; +import { InnertubeError, ParsingError, Platform } from '../utils/Utils.js'; +import { Memo, observe, SuperParsedResult } from './helpers.js'; +import { camelToSnake, generateRuntimeClass, generateTypescriptClass } from './generator.js'; +import { Log } from '../utils/index.js'; + +import { + Continuation, ItemSectionContinuation, SectionListContinuation, + LiveChatContinuation, MusicPlaylistShelfContinuation, MusicShelfContinuation, + GridContinuation, PlaylistPanelContinuation, NavigateAction, ShowMiniplayerCommand, + ReloadContinuationItemsCommand, ContinuationCommand +} from './continuations.js'; + import AudioOnlyPlayability from './classes/AudioOnlyPlayability.js'; import CardCollection from './classes/CardCollection.js'; import Endscreen from './classes/Endscreen.js'; @@ -8,27 +21,16 @@ import PlayerStoryboardSpec from './classes/PlayerStoryboardSpec.js'; import Alert from './classes/Alert.js'; import AlertWithButton from './classes/AlertWithButton.js'; import EngagementPanelSectionList from './classes/EngagementPanelSectionList.js'; - -import type { IParsedResponse, IRawResponse, RawData, RawNode } from './types/index.js'; - import MusicMultiSelectMenuItem from './classes/menus/MusicMultiSelectMenuItem.js'; import Format from './classes/misc/Format.js'; import VideoDetails from './classes/misc/VideoDetails.js'; import NavigationEndpoint from './classes/NavigationEndpoint.js'; -import { InnertubeError, ParsingError, Platform } from '../utils/Utils.js'; -import type { ObservedArray, YTNodeConstructor, YTNode } from './helpers.js'; -import { Memo, observe, SuperParsedResult } from './helpers.js'; -import * as YTNodes from './nodes.js'; import type { KeyInfo } from './generator.js'; -import { camelToSnake, generateRuntimeClass, generateTypescriptClass } from './generator.js'; +import type { ObservedArray, YTNodeConstructor, YTNode } from './helpers.js'; +import type { IParsedResponse, IRawResponse, RawData, RawNode } from './types/index.js'; -import { - Continuation, ItemSectionContinuation, SectionListContinuation, - LiveChatContinuation, MusicPlaylistShelfContinuation, MusicShelfContinuation, - GridContinuation, PlaylistPanelContinuation, NavigateAction, ShowMiniplayerCommand, - ReloadContinuationItemsCommand, ContinuationCommand -} from './continuations.js'; +const TAG = 'Parser'; export type ParserError = { classname: string, @@ -85,7 +87,7 @@ let ERROR_HANDLER: ParserErrorHandler = ({ classname, ...context }: ParserError) switch (context.error_type) { case 'parse': if (context.error instanceof Error) { - console.warn( + Log.warn(TAG, new InnertubeError( `Something went wrong at ${classname}!\n` + `This is a bug, please report it at ${Platform.shim.info.bugs_url}`, { @@ -96,7 +98,7 @@ let ERROR_HANDLER: ParserErrorHandler = ({ classname, ...context }: ParserError) } break; case 'typecheck': - console.warn( + Log.warn(TAG, new ParsingError( `Type mismatch, got ${classname} expected ${Array.isArray(context.expected) ? context.expected.join(' | ') : context.expected}.`, context.classdata @@ -104,7 +106,7 @@ let ERROR_HANDLER: ParserErrorHandler = ({ classname, ...context }: ParserError) ); break; case 'mutation_data_missing': - console.warn( + Log.warn(TAG, new InnertubeError( 'Mutation data required for processing MusicMultiSelectMenuItems, but none found.\n' + `This is a bug, please report it at ${Platform.shim.info.bugs_url}` @@ -112,7 +114,7 @@ let ERROR_HANDLER: ParserErrorHandler = ({ classname, ...context }: ParserError) ); break; case 'mutation_data_invalid': - console.warn( + Log.warn(TAG, new InnertubeError( `Mutation data missing or invalid for ${context.failed} out of ${context.total} MusicMultiSelectMenuItems. ` + `The titles of the failed items are: ${context.titles.join(', ')}.\n` + @@ -121,7 +123,7 @@ let ERROR_HANDLER: ParserErrorHandler = ({ classname, ...context }: ParserError) ); break; case 'class_not_found': - console.warn( + Log.warn(TAG, new InnertubeError( `${classname} not found!\n` + `This is a bug, want to help us fix it? Follow the instructions at ${Platform.shim.info.repo_url}/blob/main/docs/updating-the-parser.md or report it at ${Platform.shim.info.bugs_url}!\n` + @@ -130,14 +132,14 @@ let ERROR_HANDLER: ParserErrorHandler = ({ classname, ...context }: ParserError) ); break; case 'class_changed': - console.warn( + Log.warn(TAG, `${classname} changed!\n` + `The following keys where altered: ${context.changed_keys.map(([ key ]) => camelToSnake(key)).join(', ')}\n` + `The class has changed to:\n${generateTypescriptClass(classname, context.key_info)}` ); break; default: - console.warn( + Log.warn(TAG, 'Unreachable code reached at ParserErrorHandler' ); break; @@ -319,9 +321,9 @@ export function parseResponse(data: parsed_data.continuation = continuation; } - const continuationEndpoint = data.continuationEndpoint ? parseLC(data.continuationEndpoint) : null; - if (continuationEndpoint) { - parsed_data.continuationEndpoint = continuationEndpoint; + const continuation_endpoint = data.continuationEndpoint ? parseLC(data.continuationEndpoint) : null; + if (continuation_endpoint) { + parsed_data.continuation_endpoint = continuation_endpoint; } const metadata = parse(data.metadata); diff --git a/src/parser/types/ParsedResponse.ts b/src/parser/types/ParsedResponse.ts index 1fcde9969..2fc6e83a4 100644 --- a/src/parser/types/ParsedResponse.ts +++ b/src/parser/types/ParsedResponse.ts @@ -69,7 +69,7 @@ export interface IParsedResponse { items?: SuperParsedResult; entries?: SuperParsedResult; entries_memo?: Memo; - continuationEndpoint?: YTNode; + continuation_endpoint?: YTNode; } export interface IPlayerConfig { diff --git a/src/parser/youtube/AccountInfo.ts b/src/parser/youtube/AccountInfo.ts index 2da2b2574..fa41466ae 100644 --- a/src/parser/youtube/AccountInfo.ts +++ b/src/parser/youtube/AccountInfo.ts @@ -1,13 +1,12 @@ import { Parser } from '../index.js'; -import type { ApiResponse } from '../../core/Actions.js'; -import type { IParsedResponse } from '../types/ParsedResponse.js'; - +import { InnertubeError } from '../../utils/Utils.js'; import AccountSectionList from '../classes/AccountSectionList.js'; + +import type { ApiResponse } from '../../core/index.js'; +import type { IParsedResponse } from '../types/index.js'; import type AccountItemSection from '../classes/AccountItemSection.js'; import type AccountChannel from '../classes/AccountChannel.js'; -import { InnertubeError } from '../../utils/Utils.js'; - class AccountInfo { #page: IParsedResponse; diff --git a/src/parser/youtube/Analytics.ts b/src/parser/youtube/Analytics.ts index 95c512a10..8d4bd45ed 100644 --- a/src/parser/youtube/Analytics.ts +++ b/src/parser/youtube/Analytics.ts @@ -1,7 +1,7 @@ import { Parser } from '../index.js'; import Element from '../classes/Element.js'; -import type { ApiResponse } from '../../core/Actions.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; +import type { ApiResponse } from '../../core/index.js'; +import type { IBrowseResponse } from '../types/index.js'; class Analytics { #page: IBrowseResponse; diff --git a/src/parser/youtube/Channel.ts b/src/parser/youtube/Channel.ts index f7ce7babc..b18e11b1e 100644 --- a/src/parser/youtube/Channel.ts +++ b/src/parser/youtube/Channel.ts @@ -1,3 +1,7 @@ +import Feed from '../../core/mixins/Feed.js'; +import FilterableFeed from '../../core/mixins/FilterableFeed.js'; +import { ChannelError, InnertubeError } from '../../utils/Utils.js'; + import TabbedFeed from '../../core/mixins/TabbedFeed.js'; import C4TabbedHeader from '../classes/C4TabbedHeader.js'; import CarouselHeader from '../classes/CarouselHeader.js'; @@ -12,9 +16,6 @@ import SectionList from '../classes/SectionList.js'; import Tab from '../classes/Tab.js'; import PageHeader from '../classes/PageHeader.js'; import TwoColumnBrowseResults from '../classes/TwoColumnBrowseResults.js'; - -import Feed from '../../core/mixins/Feed.js'; -import FilterableFeed from '../../core/mixins/FilterableFeed.js'; import ChipCloudChip from '../classes/ChipCloudChip.js'; import FeedFilterChipBar from '../classes/FeedFilterChipBar.js'; import ChannelSubMenu from '../classes/ChannelSubMenu.js'; @@ -22,11 +23,8 @@ import SortFilterSubMenu from '../classes/SortFilterSubMenu.js'; import ContinuationItem from '../classes/ContinuationItem.js'; import NavigationEndpoint from '../classes/NavigationEndpoint.js'; -import { ChannelError, InnertubeError } from '../../utils/Utils.js'; - import type { AppendContinuationItemsAction, ReloadContinuationItemsCommand } from '../index.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; import type { IBrowseResponse } from '../types/index.js'; export default class Channel extends TabbedFeed { diff --git a/src/parser/youtube/Comments.ts b/src/parser/youtube/Comments.ts index 6e771847d..7bcc9928c 100644 --- a/src/parser/youtube/Comments.ts +++ b/src/parser/youtube/Comments.ts @@ -1,16 +1,16 @@ import { Parser } from '../index.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; import { InnertubeError } from '../../utils/Utils.js'; -import type { ObservedArray } from '../helpers.js'; import { observe } from '../helpers.js'; -import type { INextResponse } from '../types/ParsedResponse.js'; import CommentsHeader from '../classes/comments/CommentsHeader.js'; import CommentSimplebox from '../classes/comments/CommentSimplebox.js'; import CommentThread from '../classes/comments/CommentThread.js'; import ContinuationItem from '../classes/ContinuationItem.js'; +import type { Actions, ApiResponse } from '../../core/index.js'; +import type { ObservedArray } from '../helpers.js'; +import type { INextResponse } from '../types/index.js'; + class Comments { #page: INextResponse; #actions: Actions; diff --git a/src/parser/youtube/Guide.ts b/src/parser/youtube/Guide.ts index 8d088d8bd..7e068474a 100644 --- a/src/parser/youtube/Guide.ts +++ b/src/parser/youtube/Guide.ts @@ -1,10 +1,11 @@ -import type { IGuideResponse } from '../types/ParsedResponse.js'; -import type { IRawResponse } from '../index.js'; import { Parser } from '../index.js'; -import type { ObservedArray } from '../helpers.js'; import GuideSection from '../classes/GuideSection.js'; import GuideSubscriptionsSection from '../classes/GuideSubscriptionsSection.js'; +import type { ObservedArray } from '../helpers.js'; +import type { IGuideResponse } from '../types/index.js'; +import type { IRawResponse } from '../index.js'; + export default class Guide { #page: IGuideResponse; diff --git a/src/parser/youtube/HashtagFeed.ts b/src/parser/youtube/HashtagFeed.ts index 7a6d278b5..fc201aa86 100644 --- a/src/parser/youtube/HashtagFeed.ts +++ b/src/parser/youtube/HashtagFeed.ts @@ -1,14 +1,13 @@ -import FilterableFeed from '../../core/mixins/FilterableFeed.js'; import { InnertubeError } from '../../utils/Utils.js'; +import FilterableFeed from '../../core/mixins/FilterableFeed.js'; import HashtagHeader from '../classes/HashtagHeader.js'; import RichGrid from '../classes/RichGrid.js'; +import PageHeader from '../classes/PageHeader.js'; import Tab from '../classes/Tab.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; -import type ChipCloudChip from '../classes/ChipCloudChip.js'; +import type { Actions, ApiResponse } from '../../core/index.js'; import type { IBrowseResponse } from '../index.js'; -import { PageHeader } from '../nodes.js'; +import type ChipCloudChip from '../classes/ChipCloudChip.js'; export default class HashtagFeed extends FilterableFeed { header?: HashtagHeader | PageHeader; diff --git a/src/parser/youtube/History.ts b/src/parser/youtube/History.ts index faf81f8ce..17e96fea0 100644 --- a/src/parser/youtube/History.ts +++ b/src/parser/youtube/History.ts @@ -1,9 +1,9 @@ -import type Actions from '../../core/Actions.js'; import Feed from '../../core/mixins/Feed.js'; import ItemSection from '../classes/ItemSection.js'; import BrowseFeedActions from '../classes/BrowseFeedActions.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; -import type { ApiResponse } from '../../core/Actions.js'; + +import type { Actions, ApiResponse } from '../../core/index.js'; +import type { IBrowseResponse } from '../types/index.js'; // TODO: make feed actions usable class History extends Feed { diff --git a/src/parser/youtube/HomeFeed.ts b/src/parser/youtube/HomeFeed.ts index 9d0cd60ad..0ef160e2e 100644 --- a/src/parser/youtube/HomeFeed.ts +++ b/src/parser/youtube/HomeFeed.ts @@ -1,12 +1,11 @@ -import type Actions from '../../core/Actions.js'; import FilterableFeed from '../../core/mixins/FilterableFeed.js'; -import type ChipCloudChip from '../classes/ChipCloudChip.js'; import FeedTabbedHeader from '../classes/FeedTabbedHeader.js'; import RichGrid from '../classes/RichGrid.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; +import type { IBrowseResponse } from '../types/index.js'; import type { AppendContinuationItemsAction, ReloadContinuationItemsCommand } from '../index.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; +import type ChipCloudChip from '../classes/ChipCloudChip.js'; export default class HomeFeed extends FilterableFeed { contents: RichGrid | AppendContinuationItemsAction | ReloadContinuationItemsCommand; diff --git a/src/parser/youtube/ItemMenu.ts b/src/parser/youtube/ItemMenu.ts index 405232b52..f927ff7e3 100644 --- a/src/parser/youtube/ItemMenu.ts +++ b/src/parser/youtube/ItemMenu.ts @@ -1,12 +1,12 @@ -import Button from '../classes/Button.js'; import Menu from '../classes/menus/Menu.js'; +import Button from '../classes/Button.js'; import MenuServiceItem from '../classes/menus/MenuServiceItem.js'; -import type NavigationEndpoint from '../classes/NavigationEndpoint.js'; -import type Actions from '../../core/Actions.js'; +import type { Actions } from '../../core/index.js'; import { InnertubeError } from '../../utils/Utils.js'; import type { ObservedArray, YTNode } from '../helpers.js'; -import type { IParsedResponse } from '../types/ParsedResponse.js'; +import type { IParsedResponse } from '../types/index.js'; +import type NavigationEndpoint from '../classes/NavigationEndpoint.js'; class ItemMenu { #page: IParsedResponse; diff --git a/src/parser/youtube/Library.ts b/src/parser/youtube/Library.ts index 8aeca574c..1f0f3e0d5 100644 --- a/src/parser/youtube/Library.ts +++ b/src/parser/youtube/Library.ts @@ -1,6 +1,4 @@ -import type Actions from '../../core/Actions.js'; import { InnertubeError } from '../../utils/Utils.js'; - import Feed from '../../core/mixins/Feed.js'; import History from './History.js'; import Playlist from './Playlist.js'; @@ -9,8 +7,8 @@ import Shelf from '../classes/Shelf.js'; import Button from '../classes/Button.js'; import PageHeader from '../classes/PageHeader.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { Actions, ApiResponse } from '../../core/index.js'; +import type { IBrowseResponse } from '../types/index.js'; class Library extends Feed { header: PageHeader | null; diff --git a/src/parser/youtube/LiveChat.ts b/src/parser/youtube/LiveChat.ts index bf8e2612b..4ba91f749 100644 --- a/src/parser/youtube/LiveChat.ts +++ b/src/parser/youtube/LiveChat.ts @@ -1,42 +1,40 @@ -import EventEmitter from '../../utils/EventEmitterLike.js'; +import * as Proto from '../../proto/index.js'; +import { EventEmitter } from '../../utils/index.js'; +import { InnertubeError, Platform } from '../../utils/Utils.js'; import { Parser, LiveChatContinuation } from '../index.js'; -import type VideoInfo from './VideoInfo.js'; import SmoothedQueue from './SmoothedQueue.js'; import AddChatItemAction from '../classes/livechat/AddChatItemAction.js'; -import type AddLiveChatTickerItemAction from '../classes/livechat/AddLiveChatTickerItemAction.js'; -import type MarkChatItemAsDeletedAction from '../classes/livechat/MarkChatItemAsDeletedAction.js'; -import type MarkChatItemsByAuthorAsDeletedAction from '../classes/livechat/MarkChatItemsByAuthorAsDeletedAction.js'; -import type ReplaceChatItemAction from '../classes/livechat/ReplaceChatItemAction.js'; -import type ReplayChatItemAction from '../classes/livechat/ReplayChatItemAction.js'; -import type ShowLiveChatActionPanelAction from '../classes/livechat/ShowLiveChatActionPanelAction.js'; - import UpdateDateTextAction from '../classes/livechat/UpdateDateTextAction.js'; import UpdateDescriptionAction from '../classes/livechat/UpdateDescriptionAction.js'; import UpdateTitleAction from '../classes/livechat/UpdateTitleAction.js'; import UpdateToggleButtonTextAction from '../classes/livechat/UpdateToggleButtonTextAction.js'; import UpdateViewershipAction from '../classes/livechat/UpdateViewershipAction.js'; +import NavigationEndpoint from '../classes/NavigationEndpoint.js'; +import ItemMenu from './ItemMenu.js'; +import type { ObservedArray, YTNode } from '../helpers.js'; + +import type VideoInfo from './VideoInfo.js'; import type AddBannerToLiveChatCommand from '../classes/livechat/AddBannerToLiveChatCommand.js'; import type RemoveBannerForLiveChatCommand from '../classes/livechat/RemoveBannerForLiveChatCommand.js'; import type ShowLiveChatTooltipCommand from '../classes/livechat/ShowLiveChatTooltipCommand.js'; - -import * as Proto from '../../proto/index.js'; -import { InnertubeError, Platform } from '../../utils/Utils.js'; -import type { ObservedArray, YTNode } from '../helpers.js'; - -import type Button from '../classes/Button.js'; import type LiveChatAutoModMessage from '../classes/livechat/items/LiveChatAutoModMessage.js'; import type LiveChatMembershipItem from '../classes/livechat/items/LiveChatMembershipItem.js'; import type LiveChatPaidMessage from '../classes/livechat/items/LiveChatPaidMessage.js'; import type LiveChatPaidSticker from '../classes/livechat/items/LiveChatPaidSticker.js'; import type LiveChatTextMessage from '../classes/livechat/items/LiveChatTextMessage.js'; import type LiveChatViewerEngagementMessage from '../classes/livechat/items/LiveChatViewerEngagementMessage.js'; -import ItemMenu from './ItemMenu.js'; +import type AddLiveChatTickerItemAction from '../classes/livechat/AddLiveChatTickerItemAction.js'; +import type MarkChatItemAsDeletedAction from '../classes/livechat/MarkChatItemAsDeletedAction.js'; +import type MarkChatItemsByAuthorAsDeletedAction from '../classes/livechat/MarkChatItemsByAuthorAsDeletedAction.js'; +import type ReplaceChatItemAction from '../classes/livechat/ReplaceChatItemAction.js'; +import type ReplayChatItemAction from '../classes/livechat/ReplayChatItemAction.js'; +import type ShowLiveChatActionPanelAction from '../classes/livechat/ShowLiveChatActionPanelAction.js'; +import type Button from '../classes/Button.js'; -import type Actions from '../../core/Actions.js'; -import type { IParsedResponse, IUpdatedMetadataResponse } from '../types/ParsedResponse.js'; -import { NavigationEndpoint } from '../nodes.js'; +import type { Actions } from '../../core/index.js'; +import type { IParsedResponse, IUpdatedMetadataResponse } from '../types/index.js'; export type ChatAction = AddChatItemAction | AddBannerToLiveChatCommand | AddLiveChatTickerItemAction | diff --git a/src/parser/youtube/NotificationsMenu.ts b/src/parser/youtube/NotificationsMenu.ts index c1344cdef..8180e3c79 100644 --- a/src/parser/youtube/NotificationsMenu.ts +++ b/src/parser/youtube/NotificationsMenu.ts @@ -1,13 +1,12 @@ import { Parser } from '../index.js'; +import { InnertubeError } from '../../utils/Utils.js'; import ContinuationItem from '../classes/ContinuationItem.js'; import SimpleMenuHeader from '../classes/menus/SimpleMenuHeader.js'; import Notification from '../classes/Notification.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; -import type { IGetNotificationsMenuResponse } from '../types/ParsedResponse.js'; -import { InnertubeError } from '../../utils/Utils.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; +import type { IGetNotificationsMenuResponse } from '../types/index.js'; class NotificationsMenu { #page: IGetNotificationsMenuResponse; diff --git a/src/parser/youtube/Playlist.ts b/src/parser/youtube/Playlist.ts index 6c6868ef4..ee699d33e 100644 --- a/src/parser/youtube/Playlist.ts +++ b/src/parser/youtube/Playlist.ts @@ -1,7 +1,7 @@ +import { InnertubeError } from '../../utils/Utils.js'; + import Feed from '../../core/mixins/Feed.js'; import Message from '../classes/Message.js'; -import type Thumbnail from '../classes/misc/Thumbnail.js'; -import type NavigationEndpoint from '../classes/NavigationEndpoint.js'; import PlaylistCustomThumbnail from '../classes/PlaylistCustomThumbnail.js'; import PlaylistHeader from '../classes/PlaylistHeader.js'; import PlaylistMetadata from '../classes/PlaylistMetadata.js'; @@ -13,13 +13,12 @@ import Alert from '../classes/Alert.js'; import ContinuationItem from '../classes/ContinuationItem.js'; import PlaylistVideo from '../classes/PlaylistVideo.js'; import SectionList from '../classes/SectionList.js'; - -import { InnertubeError } from '../../utils/Utils.js'; import { observe, type ObservedArray } from '../helpers.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; import type { IBrowseResponse } from '../types/ParsedResponse.js'; +import type Thumbnail from '../classes/misc/Thumbnail.js'; +import type NavigationEndpoint from '../classes/NavigationEndpoint.js'; export default class Playlist extends Feed { info; diff --git a/src/parser/youtube/Search.ts b/src/parser/youtube/Search.ts index f083323c2..ac43e096a 100644 --- a/src/parser/youtube/Search.ts +++ b/src/parser/youtube/Search.ts @@ -8,10 +8,10 @@ import SearchSubMenu from '../classes/SearchSubMenu.js'; import SectionList from '../classes/SectionList.js'; import UniversalWatchCard from '../classes/UniversalWatchCard.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; import type { ObservedArray, YTNode } from '../helpers.js'; -import type { ISearchResponse } from '../types/ParsedResponse.js'; +import type { ISearchResponse } from '../types/index.js'; + class Search extends Feed { header?: SearchHeader; results?: ObservedArray | null; diff --git a/src/parser/youtube/Settings.ts b/src/parser/youtube/Settings.ts index 96d1ea18d..816f8b032 100644 --- a/src/parser/youtube/Settings.ts +++ b/src/parser/youtube/Settings.ts @@ -13,9 +13,9 @@ import ItemSectionHeader from '../classes/ItemSectionHeader.js'; import ItemSectionTabbedHeader from '../classes/ItemSectionTabbedHeader.js'; import Tab from '../classes/Tab.js'; import TwoColumnBrowseResults from '../classes/TwoColumnBrowseResults.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; + +import type { ApiResponse, Actions } from '../../core/index.js'; +import type { IBrowseResponse } from '../types/index.js'; class Settings { #page: IBrowseResponse; diff --git a/src/parser/youtube/TimeWatched.ts b/src/parser/youtube/TimeWatched.ts index 39c7c417f..d996fc493 100644 --- a/src/parser/youtube/TimeWatched.ts +++ b/src/parser/youtube/TimeWatched.ts @@ -4,9 +4,9 @@ import SectionList from '../classes/SectionList.js'; import SingleColumnBrowseResults from '../classes/SingleColumnBrowseResults.js'; import { InnertubeError } from '../../utils/Utils.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse } from '../../core/index.js'; import type { ObservedArray } from '../helpers.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; +import type { IBrowseResponse } from '../types/index.js'; class TimeWatched { #page: IBrowseResponse; diff --git a/src/parser/youtube/TranscriptInfo.ts b/src/parser/youtube/TranscriptInfo.ts index c2f73180b..f1244ae79 100644 --- a/src/parser/youtube/TranscriptInfo.ts +++ b/src/parser/youtube/TranscriptInfo.ts @@ -1,9 +1,9 @@ -import type Actions from '../../core/Actions.js'; -import { type ApiResponse } from '../../core/Actions.js'; -import type { IGetTranscriptResponse } from '../index.js'; import { Parser } from '../index.js'; import Transcript from '../classes/Transcript.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; +import type { IGetTranscriptResponse } from '../index.js'; + export default class TranscriptInfo { #page: IGetTranscriptResponse; #actions: Actions; diff --git a/src/parser/youtube/VideoInfo.ts b/src/parser/youtube/VideoInfo.ts index c01aedc43..bc4bf3668 100644 --- a/src/parser/youtube/VideoInfo.ts +++ b/src/parser/youtube/VideoInfo.ts @@ -1,3 +1,6 @@ +import { InnertubeError } from '../../utils/Utils.js'; +import { MediaInfo } from '../../core/mixins/index.js'; + import ChipCloud from '../classes/ChipCloud.js'; import ChipCloudChip from '../classes/ChipCloudChip.js'; import CommentsEntryPointHeader from '../classes/comments/CommentsEntryPointHeader.js'; @@ -19,8 +22,11 @@ import VideoPrimaryInfo from '../classes/VideoPrimaryInfo.js'; import VideoSecondaryInfo from '../classes/VideoSecondaryInfo.js'; import NavigationEndpoint from '../classes/NavigationEndpoint.js'; import PlayerLegacyDesktopYpcTrailer from '../classes/PlayerLegacyDesktopYpcTrailer.js'; +import StructuredDescriptionContent from '../classes/StructuredDescriptionContent.js'; +import VideoDescriptionMusicSection from '../classes/VideoDescriptionMusicSection.js'; import LiveChatWrap from './LiveChat.js'; +import type { RawNode } from '../index.js'; import type CardCollection from '../classes/CardCollection.js'; import type Endscreen from '../classes/Endscreen.js'; import type PlayerAnnotationsExpanded from '../classes/PlayerAnnotationsExpanded.js'; @@ -28,16 +34,9 @@ import type PlayerCaptionsTracklist from '../classes/PlayerCaptionsTracklist.js' import type PlayerLiveStoryboardSpec from '../classes/PlayerLiveStoryboardSpec.js'; import type PlayerStoryboardSpec from '../classes/PlayerStoryboardSpec.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; import type { ObservedArray, YTNode } from '../helpers.js'; -import { InnertubeError } from '../../utils/Utils.js'; -import { MediaInfo } from '../../core/mixins/index.js'; -import StructuredDescriptionContent from '../classes/StructuredDescriptionContent.js'; -import { VideoDescriptionMusicSection } from '../nodes.js'; -import type { RawNode } from '../index.js'; - class VideoInfo extends MediaInfo { #watch_next_continuation?: ContinuationItem; @@ -224,7 +223,6 @@ class VideoInfo extends MediaInfo { return super.addToWatchHistory(); } - /** * Retrieves watch next feed continuation. */ diff --git a/src/parser/youtube/index.ts b/src/parser/youtube/index.ts index df475c60b..278afcf4b 100644 --- a/src/parser/youtube/index.ts +++ b/src/parser/youtube/index.ts @@ -17,3 +17,4 @@ export { default as Settings } from './Settings.js'; export { default as SmoothedQueue } from './SmoothedQueue.js'; export { default as TimeWatched } from './TimeWatched.js'; export { default as VideoInfo } from './VideoInfo.js'; +export { default as TranscriptInfo } from './TranscriptInfo.js'; \ No newline at end of file diff --git a/src/parser/ytkids/Channel.ts b/src/parser/ytkids/Channel.ts index 644577cf8..08cc2a088 100644 --- a/src/parser/ytkids/Channel.ts +++ b/src/parser/ytkids/Channel.ts @@ -2,9 +2,9 @@ import Feed from '../../core/mixins/Feed.js'; import C4TabbedHeader from '../classes/C4TabbedHeader.js'; import ItemSection from '../classes/ItemSection.js'; import { ItemSectionContinuation } from '../index.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; + +import type { IBrowseResponse } from '../types/index.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; class Channel extends Feed { header?: C4TabbedHeader; diff --git a/src/parser/ytkids/HomeFeed.ts b/src/parser/ytkids/HomeFeed.ts index 09e7bf699..f67181007 100644 --- a/src/parser/ytkids/HomeFeed.ts +++ b/src/parser/ytkids/HomeFeed.ts @@ -1,11 +1,11 @@ +import { InnertubeError } from '../../utils/Utils.js'; + import Feed from '../../core/mixins/Feed.js'; import KidsCategoriesHeader from '../classes/ytkids/KidsCategoriesHeader.js'; import KidsCategoryTab from '../classes/ytkids/KidsCategoryTab.js'; import KidsHomeScreen from '../classes/ytkids/KidsHomeScreen.js'; -import { InnertubeError } from '../../utils/Utils.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; import type { IBrowseResponse } from '../types/ParsedResponse.js'; class HomeFeed extends Feed { diff --git a/src/parser/ytkids/Search.ts b/src/parser/ytkids/Search.ts index e758adfed..7907d86ec 100644 --- a/src/parser/ytkids/Search.ts +++ b/src/parser/ytkids/Search.ts @@ -1,10 +1,10 @@ import Feed from '../../core/mixins/Feed.js'; import ItemSection from '../classes/ItemSection.js'; import { InnertubeError } from '../../utils/Utils.js'; -import type Actions from '../../core/Actions.js'; + +import type { ApiResponse, Actions } from '../../core/index.js'; import type { ObservedArray, YTNode } from '../helpers.js'; -import type { ISearchResponse } from '../types/ParsedResponse.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ISearchResponse } from '../types/index.js'; class Search extends Feed { estimated_results: number; diff --git a/src/parser/ytkids/VideoInfo.ts b/src/parser/ytkids/VideoInfo.ts index f34a79e83..ce51bcb8f 100644 --- a/src/parser/ytkids/VideoInfo.ts +++ b/src/parser/ytkids/VideoInfo.ts @@ -1,13 +1,12 @@ +import { MediaInfo } from '../../core/mixins/index.js'; import ItemSection from '../classes/ItemSection.js'; -import type NavigationEndpoint from '../classes/NavigationEndpoint.js'; import PlayerOverlay from '../classes/PlayerOverlay.js'; import SlimVideoMetadata from '../classes/SlimVideoMetadata.js'; import TwoColumnWatchNextResults from '../classes/TwoColumnWatchNextResults.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; import type { ObservedArray, YTNode } from '../helpers.js'; -import { MediaInfo } from '../../core/mixins/index.js'; +import type NavigationEndpoint from '../classes/NavigationEndpoint.js'; class VideoInfo extends MediaInfo { basic_info; diff --git a/src/parser/ytmusic/Album.ts b/src/parser/ytmusic/Album.ts index 92775ed2e..93f9483b3 100644 --- a/src/parser/ytmusic/Album.ts +++ b/src/parser/ytmusic/Album.ts @@ -1,5 +1,3 @@ -import type { ApiResponse } from '../../core/Actions.js'; -import type { ObservedArray } from '../helpers.js'; import { Parser } from '../index.js'; import MicroformatData from '../classes/MicroformatData.js'; @@ -7,8 +5,10 @@ import MusicCarouselShelf from '../classes/MusicCarouselShelf.js'; import MusicDetailHeader from '../classes/MusicDetailHeader.js'; import MusicShelf from '../classes/MusicShelf.js'; +import type { ApiResponse } from '../../core/index.js'; +import type { ObservedArray } from '../helpers.js'; +import type { IBrowseResponse } from '../types/index.js'; import type MusicResponsiveListItem from '../classes/MusicResponsiveListItem.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; class Album { #page: IBrowseResponse; diff --git a/src/parser/ytmusic/Artist.ts b/src/parser/ytmusic/Artist.ts index 0625dd3f3..696337277 100644 --- a/src/parser/ytmusic/Artist.ts +++ b/src/parser/ytmusic/Artist.ts @@ -1,6 +1,4 @@ import { Parser } from '../index.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; import { InnertubeError } from '../../utils/Utils.js'; import MusicShelf from '../classes/MusicShelf.js'; @@ -9,6 +7,8 @@ import MusicPlaylistShelf from '../classes/MusicPlaylistShelf.js'; import MusicImmersiveHeader from '../classes/MusicImmersiveHeader.js'; import MusicVisualHeader from '../classes/MusicVisualHeader.js'; import MusicHeader from '../classes/MusicHeader.js'; + +import type { ApiResponse, Actions } from '../../core/index.js'; import type { IBrowseResponse } from '../types/ParsedResponse.js'; class Artist { diff --git a/src/parser/ytmusic/Explore.ts b/src/parser/ytmusic/Explore.ts index 6d8466cd3..302442e91 100644 --- a/src/parser/ytmusic/Explore.ts +++ b/src/parser/ytmusic/Explore.ts @@ -1,4 +1,5 @@ import { Parser } from '../index.js'; +import { InnertubeError } from '../../utils/Utils.js'; import Grid from '../classes/Grid.js'; import MusicCarouselShelf from '../classes/MusicCarouselShelf.js'; @@ -6,10 +7,9 @@ import MusicNavigationButton from '../classes/MusicNavigationButton.js'; import SectionList from '../classes/SectionList.js'; import SingleColumnBrowseResults from '../classes/SingleColumnBrowseResults.js'; -import type { ApiResponse } from '../../core/Actions.js'; -import { InnertubeError } from '../../utils/Utils.js'; +import type { ApiResponse } from '../../core/index.js'; import type { ObservedArray } from '../helpers.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; +import type { IBrowseResponse } from '../types/index.js'; class Explore { #page: IBrowseResponse; diff --git a/src/parser/ytmusic/HomeFeed.ts b/src/parser/ytmusic/HomeFeed.ts index a7f0201d2..d26ae049c 100644 --- a/src/parser/ytmusic/HomeFeed.ts +++ b/src/parser/ytmusic/HomeFeed.ts @@ -1,17 +1,16 @@ +import { InnertubeError } from '../../utils/Utils.js'; import { Parser, SectionListContinuation } from '../index.js'; import MusicCarouselShelf from '../classes/MusicCarouselShelf.js'; import SectionList from '../classes/SectionList.js'; import SingleColumnBrowseResults from '../classes/SingleColumnBrowseResults.js'; import MusicTastebuilderShelf from '../classes/MusicTastebuilderShelf.js'; - -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; -import type { ObservedArray } from '../helpers.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; -import { InnertubeError } from '../../utils/Utils.js'; import ChipCloud from '../classes/ChipCloud.js'; import ChipCloudChip from '../classes/ChipCloudChip.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; +import type { ObservedArray } from '../helpers.js'; +import type { IBrowseResponse } from '../types/index.js'; + class HomeFeed { #page: IBrowseResponse; #actions: Actions; diff --git a/src/parser/ytmusic/Library.ts b/src/parser/ytmusic/Library.ts index a0d148ea8..656f2a5e4 100644 --- a/src/parser/ytmusic/Library.ts +++ b/src/parser/ytmusic/Library.ts @@ -1,6 +1,4 @@ import { Parser, GridContinuation, MusicShelfContinuation, SectionListContinuation } from '../index.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; import Grid from '../classes/Grid.js'; import MusicShelf from '../classes/MusicShelf.js'; @@ -12,11 +10,12 @@ import ChipCloud from '../classes/ChipCloud.js'; import ChipCloudChip from '../classes/ChipCloudChip.js'; import MusicMultiSelectMenuItem from '../classes/menus/MusicMultiSelectMenuItem.js'; import MusicSortFilterButton from '../classes/MusicSortFilterButton.js'; -import type MusicMenuItemDivider from '../classes/menus/MusicMenuItemDivider.js'; import { InnertubeError } from '../../utils/Utils.js'; import type { ObservedArray } from '../helpers.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; +import type { IBrowseResponse } from '../types/index.js'; +import type MusicMenuItemDivider from '../classes/menus/MusicMenuItemDivider.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; class Library { #page: IBrowseResponse; diff --git a/src/parser/ytmusic/Playlist.ts b/src/parser/ytmusic/Playlist.ts index cf2d76756..ccbab14ea 100644 --- a/src/parser/ytmusic/Playlist.ts +++ b/src/parser/ytmusic/Playlist.ts @@ -4,15 +4,14 @@ import MusicCarouselShelf from '../classes/MusicCarouselShelf.js'; import MusicDetailHeader from '../classes/MusicDetailHeader.js'; import MusicEditablePlaylistDetailHeader from '../classes/MusicEditablePlaylistDetailHeader.js'; import MusicPlaylistShelf from '../classes/MusicPlaylistShelf.js'; -import type MusicResponsiveListItem from '../classes/MusicResponsiveListItem.js'; import MusicShelf from '../classes/MusicShelf.js'; import SectionList from '../classes/SectionList.js'; import { InnertubeError } from '../../utils/Utils.js'; import type { ObservedArray, YTNode } from '../helpers.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; +import type { IBrowseResponse } from '../types/index.js'; +import type MusicResponsiveListItem from '../classes/MusicResponsiveListItem.js'; class Playlist { #page: IBrowseResponse; diff --git a/src/parser/ytmusic/Recap.ts b/src/parser/ytmusic/Recap.ts index c4b33013f..c3182c462 100644 --- a/src/parser/ytmusic/Recap.ts +++ b/src/parser/ytmusic/Recap.ts @@ -1,22 +1,20 @@ import { Parser } from '../index.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import { InnertubeError } from '../../utils/Utils.js'; +import Playlist from './Playlist.js'; import HighlightsCarousel from '../classes/HighlightsCarousel.js'; import MusicCarouselShelf from '../classes/MusicCarouselShelf.js'; import MusicElementHeader from '../classes/MusicElementHeader.js'; import MusicHeader from '../classes/MusicHeader.js'; import SingleColumnBrowseResults from '../classes/SingleColumnBrowseResults.js'; -import Playlist from './Playlist.js'; - import ItemSection from '../classes/ItemSection.js'; import Message from '../classes/Message.js'; import SectionList from '../classes/SectionList.js'; import Tab from '../classes/Tab.js'; -import { InnertubeError } from '../../utils/Utils.js'; import type { ObservedArray } from '../helpers.js'; -import type { IBrowseResponse } from '../types/ParsedResponse.js'; +import type { IBrowseResponse } from '../types/index.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; class Recap { #page: IBrowseResponse; diff --git a/src/parser/ytmusic/Search.ts b/src/parser/ytmusic/Search.ts index 9950ff556..759b66e47 100644 --- a/src/parser/ytmusic/Search.ts +++ b/src/parser/ytmusic/Search.ts @@ -1,4 +1,3 @@ -import type Actions from '../../core/Actions.js'; import { InnertubeError } from '../../utils/Utils.js'; import { Parser, MusicShelfContinuation } from '../index.js'; @@ -9,7 +8,6 @@ import ItemSection from '../classes/ItemSection.js'; import Message from '../classes/Message.js'; import MusicCardShelf from '../classes/MusicCardShelf.js'; import MusicHeader from '../classes/MusicHeader.js'; -import type MusicResponsiveListItem from '../classes/MusicResponsiveListItem.js'; import MusicShelf from '../classes/MusicShelf.js'; import SectionList from '../classes/SectionList.js'; import ShowingResultsFor from '../classes/ShowingResultsFor.js'; @@ -17,7 +15,8 @@ import TabbedSearchResults from '../classes/TabbedSearchResults.js'; import type { ObservedArray } from '../helpers.js'; import type { ISearchResponse } from '../types/ParsedResponse.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; +import type MusicResponsiveListItem from '../classes/MusicResponsiveListItem.js'; export default class Search { #page: ISearchResponse; diff --git a/src/parser/ytmusic/TrackInfo.ts b/src/parser/ytmusic/TrackInfo.ts index b5a903e3b..c1bd49ad1 100644 --- a/src/parser/ytmusic/TrackInfo.ts +++ b/src/parser/ytmusic/TrackInfo.ts @@ -1,28 +1,26 @@ -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; - -import * as Constants from '../../utils/Constants.js'; +import { Constants } from '../../utils/index.js'; import { InnertubeError } from '../../utils/Utils.js'; +import { MediaInfo } from '../../core/mixins/index.js'; +import Tab from '../classes/Tab.js'; import AutomixPreviewVideo from '../classes/AutomixPreviewVideo.js'; -import type Endscreen from '../classes/Endscreen.js'; import Message from '../classes/Message.js'; import MicroformatData from '../classes/MicroformatData.js'; -import type MusicCarouselShelf from '../classes/MusicCarouselShelf.js'; import MusicDescriptionShelf from '../classes/MusicDescriptionShelf.js'; -import type MusicQueue from '../classes/MusicQueue.js'; import PlayerOverlay from '../classes/PlayerOverlay.js'; import PlaylistPanel from '../classes/PlaylistPanel.js'; -import type RichGrid from '../classes/RichGrid.js'; import SectionList from '../classes/SectionList.js'; -import Tab from '../classes/Tab.js'; import WatchNextTabbedResults from '../classes/WatchNextTabbedResults.js'; +import type RichGrid from '../classes/RichGrid.js'; +import type MusicQueue from '../classes/MusicQueue.js'; +import type Endscreen from '../classes/Endscreen.js'; +import type MusicCarouselShelf from '../classes/MusicCarouselShelf.js'; import type NavigationEndpoint from '../classes/NavigationEndpoint.js'; import type PlayerLiveStoryboardSpec from '../classes/PlayerLiveStoryboardSpec.js'; import type PlayerStoryboardSpec from '../classes/PlayerStoryboardSpec.js'; import type { ObservedArray, YTNode } from '../helpers.js'; -import { MediaInfo } from '../../core/mixins/index.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; class TrackInfo extends MediaInfo { basic_info; diff --git a/src/parser/ytshorts/VideoInfo.ts b/src/parser/ytshorts/VideoInfo.ts index 140ca0973..bda69b0c0 100644 --- a/src/parser/ytshorts/VideoInfo.ts +++ b/src/parser/ytshorts/VideoInfo.ts @@ -1,13 +1,11 @@ +import { Parser, ContinuationCommand } from '../index.js'; +import { InnertubeError } from '../../utils/Utils.js'; +import { Reel } from '../../core/endpoints/index.js'; + import type NavigationEndpoint from '../classes/NavigationEndpoint.js'; import type PlayerOverlay from '../classes/PlayerOverlay.js'; -import type Actions from '../../core/Actions.js'; -import type { ApiResponse } from '../../core/Actions.js'; +import type { ApiResponse, Actions } from '../../core/index.js'; import type { ObservedArray, YTNode } from '../helpers.js'; -import { Parser, ContinuationCommand } from '../index.js'; -import { InnertubeError } from '../../utils/Utils.js'; -import { - Reel -} from '../../core/endpoints/index.js'; class VideoInfo { #watch_next_continuation?: ContinuationCommand; @@ -23,12 +21,12 @@ class VideoInfo { const info = Parser.parseResponse(data[0].data); - const watchNext = Parser.parseResponse(data[1].data); + const watch_next = Parser.parseResponse(data[1].data); this.basic_info = info.video_details; - this.watch_next_feed = watchNext.entries?.array(); - this.#watch_next_continuation = watchNext.continuationEndpoint?.as(ContinuationCommand); + this.watch_next_feed = watch_next.entries?.array(); + this.#watch_next_continuation = watch_next.continuation_endpoint?.as(ContinuationCommand); } /** @@ -49,7 +47,7 @@ class VideoInfo { const parsed = Parser.parseResponse(response.data); this.watch_next_feed = parsed.entries?.array(); - this.#watch_next_continuation = parsed.continuationEndpoint?.as(ContinuationCommand); + this.#watch_next_continuation = parsed.continuation_endpoint?.as(ContinuationCommand); return this; } diff --git a/src/platform/jsruntime/jinter.ts b/src/platform/jsruntime/jinter.ts index 77d8553f5..198a9ea5a 100644 --- a/src/platform/jsruntime/jinter.ts +++ b/src/platform/jsruntime/jinter.ts @@ -1,10 +1,21 @@ import { Jinter } from 'jintr'; import type { VMPrimative } from '../../types/PlatformShim.js'; +import { Log } from '../lib.js'; + +const TAG = 'JsRuntime'; export default function evaluate(code: string, env: Record) { + Log.info(TAG, 'Evaluating JavaScript.\n', code); + const runtime = new Jinter(code); + for (const [ key, value ] of Object.entries(env)) { runtime.scope.set(key, value); } - return runtime.interpret(); + + const result = runtime.interpret(); + + Log.info(TAG, 'Done. Result:', result); + + return result; } \ No newline at end of file diff --git a/src/platform/web.ts b/src/platform/web.ts index e585666d2..7fb2a7dd2 100644 --- a/src/platform/web.ts +++ b/src/platform/web.ts @@ -4,8 +4,10 @@ import { Platform } from '../utils/Utils.js'; import sha1Hash from './polyfills/web-crypto.js'; import package_json from '../../package.json' assert { type: 'json' }; import evaluate from './jsruntime/jinter.js'; +import Log from '../utils/Log.js'; class Cache implements ICache { + #TAG = 'Cache'; #persistent_directory: string; #persistent: boolean; @@ -21,7 +23,7 @@ class Cache implements ICache { #getBrowserDB() { const indexedDB: IDBFactory = Reflect.get(globalThis, 'indexedDB') || Reflect.get(globalThis, 'webkitIndexedDB') || Reflect.get(globalThis, 'mozIndexedDB') || Reflect.get(globalThis, 'msIndexedDB'); - if (!indexedDB) return console.log('IndexedDB is not supported. No cache will be used.'); + if (!indexedDB) return Log.warn(this.#TAG, 'IndexedDB is not supported. No cache will be used.'); return new Promise((resolve, reject) => { const request = indexedDB.open('youtubei.js', 1); diff --git a/src/utils/DashManifest.tsx b/src/utils/DashManifest.tsx index d5ed564fd..51af51877 100644 --- a/src/utils/DashManifest.tsx +++ b/src/utils/DashManifest.tsx @@ -1,15 +1,17 @@ /* eslint-disable tsdoc/syntax */ /** @jsxFactory DashUtils.createElement */ /** @jsxFragmentFactory DashUtils.Fragment */ +import * as DashUtils from './DashUtils.js'; +import { getStreamingInfo } from './StreamingInfo.js'; +import { InnertubeError } from './Utils.js'; + import type Actions from '../core/Actions.js'; import type Player from '../core/Player.js'; import type { IStreamingData } from '../parser/index.js'; -import type { PlayerLiveStoryboardSpec, PlayerStoryboardSpec } from '../parser/nodes.js'; -import * as DashUtils from './DashUtils.js'; +import type { PlayerStoryboardSpec } from '../parser/nodes.js'; import type { SegmentInfo as FSegmentInfo } from './StreamingInfo.js'; -import { getStreamingInfo } from './StreamingInfo.js'; import type { FormatFilter, URLTransformer } from '../types/FormatUtils.js'; -import { InnertubeError } from './Utils.js'; +import type PlayerLiveStoryboardSpec from '../parser/classes/PlayerLiveStoryboardSpec.js'; interface DashManifestProps { streamingData: IStreamingData; diff --git a/src/utils/FormatUtils.ts b/src/utils/FormatUtils.ts index b674af8c7..aa984b588 100644 --- a/src/utils/FormatUtils.ts +++ b/src/utils/FormatUtils.ts @@ -1,10 +1,9 @@ +import { Constants } from './index.js'; +import { InnertubeError, Platform, streamToIterable } from './Utils.js'; + import type Player from '../core/Player.js'; import type Actions from '../core/Actions.js'; - import type Format from '../parser/classes/misc/Format.js'; - -import * as Constants from './Constants.js'; -import { InnertubeError, Platform, streamToIterable } from './Utils.js'; import type { IPlayabilityStatus, IStreamingData } from '../parser/index.js'; import type { DownloadOptions, FormatOptions } from '../types/FormatUtils.js'; diff --git a/src/utils/HTTPClient.ts b/src/utils/HTTPClient.ts index 414e87fc3..f954f5d4e 100644 --- a/src/utils/HTTPClient.ts +++ b/src/utils/HTTPClient.ts @@ -1,7 +1,5 @@ -import type { Context } from '../core/Session.js'; -import type Session from '../core/Session.js'; -import type { FetchFunction } from '../types/PlatformShim.js'; import * as Constants from './Constants.js'; + import { Platform, generateSidAuth, @@ -10,6 +8,9 @@ import { InnertubeError } from './Utils.js'; +import type { Context, Session } from '../core/index.js'; +import type { FetchFunction } from '../types/index.js'; + export interface HTTPClientInit { baseURL?: string; } diff --git a/src/utils/Log.ts b/src/utils/Log.ts new file mode 100644 index 000000000..3becc0685 --- /dev/null +++ b/src/utils/Log.ts @@ -0,0 +1,49 @@ +export default class Log { + private static YTJS_TAG = 'YOUTUBEJS'; + + public static Level = { + NONE: 0, + ERROR: 1, + WARNING: 2, + INFO: 3, + DEBUG: 4 + }; + + private static log_map_ = { + [Log.Level.ERROR]: (...args: any[]) => console.error(...args), + [Log.Level.WARNING]: (...args: any[]) => console.warn(...args), + [Log.Level.INFO]: (...args: any[]) => console.info(...args), + [Log.Level.DEBUG]: (...args: any[]) => console.debug(...args) + }; + + private static log_level_ = [ Log.Level.WARNING ]; + private static one_time_warnings_issued_ = new Set(); + + static warnOnce = (id: string, ...args: any[]) => { + if (this.one_time_warnings_issued_.has(id)) + return; + this.doLog(Log.Level.WARNING, id, args); + this.one_time_warnings_issued_.add(id); + }; + + static warn = (tag?: string, ...args: any[]) => this.doLog(Log.Level.WARNING, tag, args); + static error = (tag?: string, ...args: any[]) => this.doLog(Log.Level.ERROR, tag, args); + static info = (tag?: string, ...args: any[]) => this.doLog(Log.Level.INFO, tag, args); + static debug = (tag?: string, ...args: any[]) => this.doLog(Log.Level.DEBUG, tag, args); + + private static doLog(level: number, tag?: string, args?: any[]) { + if (!this.log_map_[level] || !this.log_level_.includes(level)) + return; + + const tags = [ `[${this.YTJS_TAG}]` ]; + + if (tag) + tags.push(`[${tag}]`); + + this.log_map_[level](`${tags.join('')}:`, ...(args || [])); + } + + static setLevel(...args: number[]) { + this.log_level_ = args; + } +} \ No newline at end of file diff --git a/src/utils/StreamingInfo.ts b/src/utils/StreamingInfo.ts index 2efd8851e..49bf37233 100644 --- a/src/utils/StreamingInfo.ts +++ b/src/utils/StreamingInfo.ts @@ -8,7 +8,9 @@ import type { PlayerLiveStoryboardSpec } from '../parser/nodes.js'; import type { FormatFilter, URLTransformer } from '../types/FormatUtils.js'; import PlayerStoryboardSpec from '../parser/classes/PlayerStoryboardSpec.js'; import { InnertubeError, Platform, getStringBetweenStrings } from './Utils.js'; -import { Constants } from './index.js'; +import { Constants, Log } from './index.js'; + +const TAG_ = 'StreamingInfo'; export interface StreamingInfo { getDuration(): Promise; @@ -477,9 +479,9 @@ function getColorInfo(format: Format) { anonymisedFormat.signature_cipher = 'REDACTED'; anonymisedFormat.cipher = 'REDACTED'; - console.warn(`YouTube.js toDash(): Unknown matrix coefficients "${color_info.matrix_coefficients}", the DASH manifest is still usuable without this.\n` + Log.warn(TAG_, `Unknown matrix coefficients "${color_info.matrix_coefficients}", the DASH manifest is still usuable without this.\n` + `Please report it at ${Platform.shim.info.bugs_url} so we can add support for it.\n` - + `Innertube client: ${url.searchParams.get('c')}\nformat:`, anonymisedFormat); + + `InnerTube client: ${url.searchParams.get('c')}\nformat:`, anonymisedFormat); } } } diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 7242c105c..232a7c6f0 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -1,9 +1,13 @@ import { Memo } from '../parser/helpers.js'; -import type { EmojiRun, TextRun } from '../parser/misc.js'; import { Text } from '../parser/misc.js'; +import Log from './Log.js'; +import userAgents from './user-agents.js'; + +import type { EmojiRun, TextRun } from '../parser/misc.js'; import type { FetchFunction } from '../types/PlatformShim.js'; import type PlatformShim from '../types/PlatformShim.js'; -import userAgents from './user-agents.js'; + +const TAG_ = 'Utils'; export class Platform { static #shim: PlatformShim | undefined; @@ -214,8 +218,8 @@ export const debugFetch: FetchFunction = (input, init) => { `${arr_headers.map(([ key, value ]) => ` ${key}: ${value}`).join('\n')}` : ' (none)'; - console.log( - 'YouTube.js Fetch:\n' + + Log.warn(TAG_, + 'Fetch:\n' + ` url: ${url.toString()}\n` + ` method: ${init?.method || 'GET'}\n` + ` headers:\n${headers_serialized}\n' + diff --git a/src/utils/index.ts b/src/utils/index.ts index e06a19037..8d9004d93 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -11,3 +11,5 @@ export * from './HTTPClient.js'; export { Platform } from './Utils.js'; export * as Utils from './Utils.js'; + +export { default as Log } from './Log.js'; \ No newline at end of file