Skip to content

Commit f84c352

Browse files
committed
chore(YouTube): Add some documentation comments
1 parent a8da1a2 commit f84c352

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
lines changed

providers/YouTubeMusic/mod.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
220220

221221
this.updateCacheTime(timestamp);
222222

223+
// The main list of search results
223224
const tab = content
224225
.contents
225226
.tabbedSearchResultsRenderer
@@ -231,9 +232,14 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
231232
?.content
232233
.sectionListRenderer
233234
.contents
235+
// Search results are grouped into music shelfs.
236+
// Since we filtered the search by albums,
237+
// we only care about the first (and only) music shelf
234238
.find((renderer) => 'musicShelfRenderer' in renderer)
235239
?.musicShelfRenderer
236240
.contents
241+
// The first (and usually only) item in the music in the shelf
242+
// is the album we are looking for
237243
.at(0)
238244
?.musicResponsiveListItemRenderer
239245
.navigationEndpoint
@@ -253,6 +259,7 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
253259
};
254260
}
255261

262+
/** Fetch a YouTube Music album by its browse ID */
256263
async fetchAlbum(albumId: string) {
257264
const { content, timestamp } = await this.provider.browse<Album>(albumId)
258265
.catch((reason) => {
@@ -267,6 +274,7 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
267274
return content;
268275
}
269276

277+
/** Fetch a YouTube Music playlist by its playlist ID */
270278
async fetchPlaylist(playlistId: string) {
271279
const { content, timestamp } = await this.provider.browse<Playlist>(`VL${playlistId}`)
272280
.catch((reason) => {
@@ -281,6 +289,7 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
281289
return content;
282290
}
283291

292+
/** Extract and fetch the corresponding playlist of an album */
284293
async playlistFromAlbum(album: Album) {
285294
const { id } = this.provider.extractEntityFromUrl(
286295
new URL(album.microformat.microformatDataRenderer.urlCanonical),
@@ -289,6 +298,10 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
289298
return await this.fetchPlaylist(id);
290299
}
291300

301+
/**
302+
* Extract and fetch the corresponding album of a playlist, if it exists.
303+
* Throws a ProviderError otherwise.
304+
*/
292305
async albumFromPlaylist(playlistId: string) {
293306
// cbrd=1 seems to skip the privacy consent screen
294307
const { content, timestamp } = await this.provider.extractEmbeddedJson(
@@ -314,12 +327,19 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
314327
}
315328

316329
protected override convertRawRelease({ album, playlist }: YouTubeMusicRelease) {
330+
const url = album.microformat.microformatDataRenderer.urlCanonical;
331+
317332
if (!this.entity) {
318333
this.entity = this.provider.extractEntityFromUrl(
319-
new URL(album.microformat.microformatDataRenderer.urlCanonical),
334+
new URL(url),
320335
);
321336
}
322337

338+
/**
339+
* The header contains the main metadata about the album.
340+
* It's mostly what's shown on the left half of an album screen
341+
* on the YouTube Music web UI.
342+
*/
323343
const header = album
324344
.contents
325345
.twoColumnBrowseResultsRenderer
@@ -393,7 +413,7 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
393413
externalLinks: [
394414
{
395415
// Album URL is always of type https://music.youtube.com/playlist?list=:playlist_id
396-
url: album.microformat.microformatDataRenderer.urlCanonical,
416+
url,
397417
// Set free streaming if every track is (seemingly) streamable
398418
types: tracklist.every((track) => track.recording?.externalIds?.length) ? ['free streaming'] : undefined,
399419
},
@@ -413,6 +433,7 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
413433
?.musicThumbnailRenderer
414434
.thumbnail
415435
.thumbnails
436+
// Sort by highest pixel count
416437
.sort((a, b) => a.width * a.height - b.width * b.height)
417438
.at(-1);
418439
if (image) {
@@ -503,12 +524,16 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
503524
}
504525

505526
extractTrackData(item: Renderer<'MusicResponsiveListItem'>) {
506-
const columns = item.musicResponsiveListItemRenderer.flexColumns.map(
527+
// Extract the text run of each flex column.
528+
// The flex columns usually are:
529+
// - Title (usually with endpoint to video)
530+
// - Artist name (usually with endpoint to artist)
531+
// - Album name (usually with endpoint to album)
532+
const columnTextRuns = item.musicResponsiveListItemRenderer.flexColumns.map(
507533
(column) => column.musicResponsiveListItemFlexColumnRenderer.text.runs,
508534
);
509535

510-
item.musicResponsiveListItemRenderer;
511-
const titleRun = columns[0][0];
536+
const titleRun = columnTextRuns[0][0];
512537
const title = titleRun.text;
513538

514539
let videoId: string | undefined;
@@ -518,10 +543,10 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
518543
musicVideoType = titleRun.navigationEndpoint.watchEndpoint?.watchEndpointMusicSupportedConfigs?.musicVideoType;
519544
}
520545

521-
const artistRuns = columns[1];
546+
const artistRuns = columnTextRuns[1];
522547
const artists = artistRuns ? this.extractArtistCredit(artistRuns) : undefined;
523548

524-
const albumRun = columns.at(2)?.at(0);
549+
const albumRun = columnTextRuns.at(2)?.at(0);
525550
let albumName: string | undefined;
526551
let albumId: string | undefined;
527552
if (albumRun) {
@@ -533,11 +558,11 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
533558

534559
const index = item.musicResponsiveListItemRenderer.index?.runs.at(0)?.text;
535560

561+
// The duration is given in (HH:)MM:SS, which is then parsed manually using the code below
536562
const durationString = item.musicResponsiveListItemRenderer.fixedColumns?.at(0)
537563
?.musicResponsiveListItemFixedColumnRenderer.text.runs
538564
.map((r) => r.text)
539565
.join('');
540-
541566
const duration = durationString?.split(':').reduce((acc, curr) => {
542567
try {
543568
return acc * 60 + Number.parseInt(curr);
@@ -560,7 +585,6 @@ export class YouTubeMusicReleaseLookup extends ReleaseLookup<YouTubeMusicProvide
560585
.filter((endpoint) => 'browseEndpoint' in endpoint)
561586
.find((endpoint) => endpoint.browseEndpoint.browseId.startsWith('MPTC'))
562587
?.browseEndpoint;
563-
564588
if (creditsEndpoint) {
565589
// await this.provider.browse(creditsEndpoint.browseId);
566590
}

0 commit comments

Comments
 (0)