Skip to content

Commit 815e54b

Browse files
committed
feat(MusicResponsiveListItem): Detect non music tracks properly
This should make it easier to identify podcast episodes.
1 parent f766605 commit 815e54b

File tree

1 file changed

+46
-15
lines changed

1 file changed

+46
-15
lines changed

src/parser/classes/MusicResponsiveListItem.ts

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
// TODO: Clean up and refactor this.
22

3+
import { YTNode } from '../helpers.js';
4+
import { isTextRun, timeToSeconds } from '../../utils/Utils.js';
5+
import type { ObservedArray } from '../helpers.js';
6+
import type { RawNode } from '../index.js';
7+
38
import Parser from '../index.js';
49
import MusicItemThumbnailOverlay from './MusicItemThumbnailOverlay.js';
510
import MusicResponsiveListItemFixedColumn from './MusicResponsiveListItemFixedColumn.js';
@@ -9,11 +14,6 @@ import NavigationEndpoint from './NavigationEndpoint.js';
914
import Menu from './menus/Menu.js';
1015
import Text from './misc/Text.js';
1116

12-
import { isTextRun, timeToSeconds } from '../../utils/Utils.js';
13-
import type { ObservedArray } from '../helpers.js';
14-
import { YTNode } from '../helpers.js';
15-
import type { RawNode } from '../index.js';
16-
1717
export default class MusicResponsiveListItem extends YTNode {
1818
static type = 'MusicResponsiveListItem';
1919

@@ -24,8 +24,8 @@ export default class MusicResponsiveListItem extends YTNode {
2424
playlist_set_video_id: string;
2525
};
2626

27-
endpoint: NavigationEndpoint | null;
28-
item_type: 'album' | 'playlist' | 'artist' | 'library_artist' | 'video' | 'song' | 'endpoint' | 'unknown' | undefined;
27+
endpoint?: NavigationEndpoint;
28+
item_type: 'album' | 'playlist' | 'artist' | 'library_artist' | 'non_music_track' | 'video' | 'song' | 'endpoint' | 'unknown' | undefined;
2929
index?: Text;
3030
thumbnail?: MusicThumbnail | null;
3131
badges;
@@ -82,9 +82,21 @@ export default class MusicResponsiveListItem extends YTNode {
8282
playlist_set_video_id: data?.playlistItemData?.playlistSetVideoId || null
8383
};
8484

85-
this.endpoint = data.navigationEndpoint ? new NavigationEndpoint(data.navigationEndpoint) : null;
85+
if (Reflect.has(data, 'navigationEndpoint')) {
86+
this.endpoint = new NavigationEndpoint(data.navigationEndpoint);
87+
}
88+
89+
let page_type = this.endpoint?.payload?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType;
90+
91+
if (!page_type) {
92+
const is_non_music_track = this.flex_columns.find(
93+
(col) => col.title.endpoint?.payload?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType === 'MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE'
94+
);
8695

87-
const page_type = this.endpoint?.payload?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType;
96+
if (is_non_music_track) {
97+
page_type = 'MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE';
98+
}
99+
}
88100

89101
switch (page_type) {
90102
case 'MUSIC_PAGE_TYPE_ALBUM':
@@ -104,23 +116,37 @@ export default class MusicResponsiveListItem extends YTNode {
104116
this.item_type = 'library_artist';
105117
this.#parseLibraryArtist();
106118
break;
119+
case 'MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE':
120+
this.item_type = 'non_music_track';
121+
this.#parseNonMusicTrack();
122+
break;
107123
default:
108124
if (this.flex_columns[1]) {
109125
this.#parseVideoOrSong();
110126
} else {
111127
this.#parseOther();
112128
}
113-
break;
114129
}
115130

116-
if (data.index) {
131+
if (Reflect.has(data, 'index')) {
117132
this.index = new Text(data.index);
118133
}
119134

120-
this.thumbnail = Parser.parseItem(data.thumbnail, MusicThumbnail);
121-
this.badges = Parser.parseArray(data.badges);
122-
this.menu = Parser.parseItem(data.menu, Menu);
123-
this.overlay = Parser.parseItem(data.overlay, MusicItemThumbnailOverlay);
135+
if (Reflect.has(data, 'thumbnail')) {
136+
this.thumbnail = Parser.parseItem(data.thumbnail, MusicThumbnail);
137+
}
138+
139+
if (Reflect.has(data, 'badges')) {
140+
this.badges = Parser.parseArray(data.badges);
141+
}
142+
143+
if (Reflect.has(data, 'menu')) {
144+
this.menu = Parser.parseItem(data.menu, Menu);
145+
}
146+
147+
if (Reflect.has(data, 'overlay')) {
148+
this.overlay = Parser.parseItem(data.overlay, MusicItemThumbnailOverlay);
149+
}
124150
}
125151

126152
#parseOther() {
@@ -236,6 +262,11 @@ export default class MusicResponsiveListItem extends YTNode {
236262
this.song_count = this.subtitle?.runs?.find((run) => (/^\d+(,\d+)? songs?$/i).test(run.text))?.text || '';
237263
}
238264

265+
#parseNonMusicTrack() {
266+
this.id = this.#playlist_item_data.video_id || this.endpoint?.payload?.videoId;
267+
this.title = this.flex_columns.first().title.toString();
268+
}
269+
239270
#parseAlbum() {
240271
this.id = this.endpoint?.payload?.browseId;
241272
this.title = this.flex_columns.first().title.toString();

0 commit comments

Comments
 (0)