UNPKG

@antoniojps/youtubei.js

Version:

A JavaScript client for YouTube's private API, known as InnerTube.

143 lines 5.81 kB
import { InnertubeError } from '../../utils/Utils.js'; import { Parser, MusicShelfContinuation } from '../index.js'; import ChipCloud from '../classes/ChipCloud.js'; import ChipCloudChip from '../classes/ChipCloudChip.js'; import DidYouMean from '../classes/DidYouMean.js'; 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 MusicShelf from '../classes/MusicShelf.js'; import SectionList from '../classes/SectionList.js'; import ShowingResultsFor from '../classes/ShowingResultsFor.js'; import TabbedSearchResults from '../classes/TabbedSearchResults.js'; export default class Search { #page; #actions; #continuation; header; contents; constructor(response, actions, is_filtered) { this.#actions = actions; this.#page = Parser.parseResponse(response.data); if (!this.#page.contents || !this.#page.contents_memo) throw new InnertubeError('Response did not contain any contents.'); const tab = this.#page.contents.item().as(TabbedSearchResults).tabs.get({ selected: true }); if (!tab) throw new InnertubeError('Could not find target tab.'); const tab_content = tab.content?.as(SectionList); if (!tab_content) throw new InnertubeError('Target tab did not have any content.'); this.header = tab_content.header?.as(ChipCloud); this.contents = tab_content.contents.as(MusicShelf, MusicCardShelf, ItemSection); if (is_filtered) { this.#continuation = this.contents.firstOfType(MusicShelf)?.continuation; } } /** * Loads more items for the given shelf. */ async getMore(shelf) { if (!shelf || !shelf.endpoint) throw new InnertubeError('Cannot retrieve more items for this shelf because it does not have an endpoint.'); const response = await shelf.endpoint.call(this.#actions, { client: 'YTMUSIC' }); if (!response) throw new InnertubeError('Endpoint did not return any data'); return new Search(response, this.#actions, true); } /** * Retrieves search continuation. Only available for filtered searches and shelf continuations. */ async getContinuation() { if (!this.#continuation) throw new InnertubeError('Continuation not found.'); const response = await this.#actions.execute('/search', { continuation: this.#continuation, client: 'YTMUSIC' }); return new SearchContinuation(this.#actions, response); } /** * Applies given filter to the search. */ async applyFilter(target_filter) { let cloud_chip; if (typeof target_filter === 'string') { cloud_chip = this.header?.chips?.as(ChipCloudChip).get({ text: target_filter }); if (!cloud_chip) throw new InnertubeError('Could not find filter with given name.', { available_filters: this.filters }); } else if (target_filter?.is(ChipCloudChip)) { cloud_chip = target_filter; } if (!cloud_chip) throw new InnertubeError('Invalid filter', { available_filters: this.filters }); if (cloud_chip?.is_selected) return this; if (!cloud_chip.endpoint) throw new InnertubeError('Selected filter does not have an endpoint.'); const response = await cloud_chip.endpoint.call(this.#actions, { client: 'YTMUSIC' }); return new Search(response, this.#actions, true); } get filters() { return this.header?.chips?.as(ChipCloudChip).map((chip) => chip.text) || []; } get has_continuation() { return !!this.#continuation; } get did_you_mean() { return this.#page.contents_memo?.getType(DidYouMean)[0]; } get showing_results_for() { return this.#page.contents_memo?.getType(ShowingResultsFor)[0]; } get message() { return this.#page.contents_memo?.getType(Message)[0]; } get songs() { return this.contents?.filterType(MusicShelf).find((section) => section.title.toString() === 'Songs'); } get videos() { return this.contents?.filterType(MusicShelf).find((section) => section.title.toString() === 'Videos'); } get albums() { return this.contents?.filterType(MusicShelf).find((section) => section.title.toString() === 'Albums'); } get artists() { return this.contents?.filterType(MusicShelf).find((section) => section.title.toString() === 'Artists'); } get playlists() { return this.contents?.filterType(MusicShelf).find((section) => section.title.toString() === 'Community playlists'); } get page() { return this.#page; } } export class SearchContinuation { #actions; #page; header; contents; constructor(actions, response) { this.#actions = actions; this.#page = Parser.parseResponse(response.data); this.header = this.#page.header?.item().as(MusicHeader); this.contents = this.#page.continuation_contents?.as(MusicShelfContinuation); } async getContinuation() { if (!this.contents?.continuation) throw new InnertubeError('Continuation not found.'); const response = await this.#actions.execute('/search', { continuation: this.contents.continuation, client: 'YTMUSIC' }); return new SearchContinuation(this.#actions, response); } get has_continuation() { return !!this.contents?.continuation; } get page() { return this.#page; } } //# sourceMappingURL=Search.js.map