From 1aedbd3ea69a5e6d890edc3048ba1be8dfef2f89 Mon Sep 17 00:00:00 2001 From: LuanRT Date: Tue, 10 Jan 2023 23:24:12 -0300 Subject: [PATCH] refactor(ytmusic): minor improvements to `Library` --- docs/API/music.md | 8 ++++---- src/parser/index.ts | 8 +++++++- src/parser/ytmusic/Library.ts | 31 ++++++++++++++++++++----------- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/docs/API/music.md b/docs/API/music.md index 64ac5d6f..8bad7fb9 100644 --- a/docs/API/music.md +++ b/docs/API/music.md @@ -158,8 +158,8 @@ Retrieves library. - `#applyFilter(filter)` - Applies given filter to the library. -- `#applySortFilter(filter)` - - Applies given sort filter to the library items. +- `#applySort(sort_by)` + - Applies given sort option to the library items. - `#getContinuation()` - Retrieves continuation of the library items. @@ -170,8 +170,8 @@ Retrieves library. - `#filters` - Returns available filters. -- `#sort_filters` - - Returns available sort filters. +- `#sort_options` + - Returns available sort options. - `#page` - Returns original InnerTube response (sanitized). diff --git a/src/parser/index.ts b/src/parser/index.ts index 0058e26c..d7b83664 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -85,6 +85,11 @@ export default class Parser { const on_response_received_commands_memo = this.#getMemo(); this.#clearMemo(); + this.#createMemo(); + const continuation_contents = data.continuationContents ? Parser.parseLC(data.continuationContents) : null; + const continuation_contents_memo = this.#getMemo(); + this.#clearMemo(); + this.#createMemo(); const actions = data.actions ? Parser.parseActions(data.actions) : null; const actions_memo = this.#getMemo(); @@ -127,7 +132,8 @@ export default class Parser { on_response_received_commands, on_response_received_commands_memo, continuation: data.continuation ? Parser.parseC(data.continuation) : null, - continuation_contents: data.continuationContents ? Parser.parseLC(data.continuationContents) : null, + continuation_contents, + continuation_contents_memo, metadata: Parser.parse(data.metadata), microformat: data.microformat ? Parser.parseItem(data.microformat) : null, overlay: Parser.parseItem(data.overlay), diff --git a/src/parser/ytmusic/Library.ts b/src/parser/ytmusic/Library.ts index 15e63876..ff5c354d 100644 --- a/src/parser/ytmusic/Library.ts +++ b/src/parser/ytmusic/Library.ts @@ -1,4 +1,4 @@ -import Parser, { ParsedResponse } from '..'; +import Parser, { ParsedResponse, SectionListContinuation } from '..'; import type Actions from '../../core/Actions'; import type { ApiResponse } from '../../core/Actions'; @@ -29,7 +29,7 @@ class Library { this.#page = Parser.parseResponse(response.data); this.#actions = actions; - const section_list = this.#page.contents_memo.getType(SectionList)?.[0]; + const section_list = this.#page.contents_memo.getType(SectionList).first(); this.header = section_list?.header?.item().as(MusicSideAlignedItem); this.contents = section_list?.contents?.as(Grid, MusicShelf); @@ -38,9 +38,9 @@ class Library { } /** - * Applies given sort filter to the library items. + * Applies given sort option to the library items. */ - async applySortFilter(sort_by: string | MusicMultiSelectMenuItem): Promise { + async applySort(sort_by: string | MusicMultiSelectMenuItem): Promise { let target_item: MusicMultiSelectMenuItem | undefined; if (typeof sort_by === 'string') { @@ -54,13 +54,13 @@ class Library { target_item = options?.find((item) => item.title === sort_by); if (!target_item) - throw new InnertubeError(`Sort filter "${sort_by}" not found`, { available_filters: options.map((item) => item.title) }); + throw new InnertubeError(`Sort option "${sort_by}" not found`, { available_filters: options.map((item) => item.title) }); } else if (sort_by instanceof MusicMultiSelectMenuItem) { target_item = sort_by; } if (!target_item) - throw new InnertubeError('Invalid sort filter'); + throw new InnertubeError('Invalid sort option'); if (target_item.selected) return this; @@ -68,14 +68,23 @@ class Library { const cmd = target_item.endpoint?.payload?.commands?.find((cmd: any) => cmd.browseSectionListReloadEndpoint)?.browseSectionListReloadEndpoint; if (!cmd) - throw new InnertubeError('Failed to find sort filter command'); + throw new InnertubeError('Failed to find sort option command'); const response = await this.#actions.execute('/browse', { client: 'YTMUSIC', - continuation: cmd.continuation.reloadContinuationData.continuation + continuation: cmd.continuation.reloadContinuationData.continuation, + parse: true }); - return new Library(response, this.#actions); + const previously_selected_item = this.#page.contents_memo.getType(MusicMultiSelectMenuItem)?.find((item) => item.selected); + if (previously_selected_item) + previously_selected_item.selected = false; + + target_item.selected = true; + + this.contents = response.continuation_contents?.as(SectionListContinuation).contents?.as(Grid, MusicShelf); + + return this; } /** @@ -123,14 +132,14 @@ class Library { return !!this.#continuation; } - get sort_filters(): string[] { + get sort_options(): string[] { const button = this.#page.contents_memo.getType(MusicSortFilterButton)?.[0]; const options = button.menu?.options.filter((item: MusicMultiSelectMenuItem | MusicMenuItemDivider) => item instanceof MusicMultiSelectMenuItem) as MusicMultiSelectMenuItem[]; return options.map((item) => item.title); } get filters(): string[] { - return this.#page.contents_memo.getType(ChipCloud)?.[0].chips.map((chip: ChipCloudChip) => chip.text); + return this.#page.contents_memo.getType(ChipCloud)?.first()?.chips.map((chip: ChipCloudChip) => chip.text) || []; } get page(): ParsedResponse {