✨ make artists singular and delete descriptions
This commit is contained in:
parent
dd06c5ac65
commit
aca523a303
|
|
@ -9,7 +9,7 @@ export const ThumbnailFull = type({
|
||||||
|
|
||||||
export type ArtistBasic = typeof ArtistBasic.infer
|
export type ArtistBasic = typeof ArtistBasic.infer
|
||||||
export const ArtistBasic = type({
|
export const ArtistBasic = type({
|
||||||
artistId: "string|null",
|
artistId: "string|null", // Only null for YouTube Music
|
||||||
name: "string",
|
name: "string",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ export const SongDetailed = type({
|
||||||
type: '"SONG"',
|
type: '"SONG"',
|
||||||
videoId: "string",
|
videoId: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
artists: [ArtistBasic, "[]"],
|
artist: ArtistBasic,
|
||||||
album: AlbumBasic,
|
album: AlbumBasic,
|
||||||
duration: "number|null",
|
duration: "number|null",
|
||||||
thumbnails: [ThumbnailFull, "[]"],
|
thumbnails: [ThumbnailFull, "[]"],
|
||||||
|
|
@ -35,7 +35,7 @@ export const VideoDetailed = type({
|
||||||
type: '"VIDEO"',
|
type: '"VIDEO"',
|
||||||
videoId: "string",
|
videoId: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
artists: [ArtistBasic, "[]"],
|
artist: ArtistBasic,
|
||||||
duration: "number|null",
|
duration: "number|null",
|
||||||
thumbnails: [ThumbnailFull, "[]"],
|
thumbnails: [ThumbnailFull, "[]"],
|
||||||
})
|
})
|
||||||
|
|
@ -54,7 +54,7 @@ export const AlbumDetailed = type({
|
||||||
albumId: "string",
|
albumId: "string",
|
||||||
playlistId: "string",
|
playlistId: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
artists: [ArtistBasic, "[]"],
|
artist: ArtistBasic,
|
||||||
year: "number|null",
|
year: "number|null",
|
||||||
thumbnails: [ThumbnailFull, "[]"],
|
thumbnails: [ThumbnailFull, "[]"],
|
||||||
})
|
})
|
||||||
|
|
@ -73,10 +73,9 @@ export const SongFull = type({
|
||||||
type: '"SONG"',
|
type: '"SONG"',
|
||||||
videoId: "string",
|
videoId: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
artists: [ArtistBasic, "[]"],
|
artist: ArtistBasic,
|
||||||
duration: "number",
|
duration: "number",
|
||||||
thumbnails: [ThumbnailFull, "[]"],
|
thumbnails: [ThumbnailFull, "[]"],
|
||||||
description: "string",
|
|
||||||
formats: "any[]",
|
formats: "any[]",
|
||||||
adaptiveFormats: "any[]",
|
adaptiveFormats: "any[]",
|
||||||
})
|
})
|
||||||
|
|
@ -86,10 +85,9 @@ export const VideoFull = type({
|
||||||
type: '"VIDEO"',
|
type: '"VIDEO"',
|
||||||
videoId: "string",
|
videoId: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
artists: [ArtistBasic, "[]"],
|
artist: ArtistBasic,
|
||||||
duration: "number",
|
duration: "number",
|
||||||
thumbnails: [ThumbnailFull, "[]"],
|
thumbnails: [ThumbnailFull, "[]"],
|
||||||
description: "string",
|
|
||||||
unlisted: "boolean",
|
unlisted: "boolean",
|
||||||
familySafe: "boolean",
|
familySafe: "boolean",
|
||||||
paid: "boolean",
|
paid: "boolean",
|
||||||
|
|
@ -102,7 +100,6 @@ export const ArtistFull = type({
|
||||||
name: "string",
|
name: "string",
|
||||||
type: '"ARTIST"',
|
type: '"ARTIST"',
|
||||||
thumbnails: [ThumbnailFull, "[]"],
|
thumbnails: [ThumbnailFull, "[]"],
|
||||||
description: "string",
|
|
||||||
topSongs: [SongDetailed, "[]"],
|
topSongs: [SongDetailed, "[]"],
|
||||||
topAlbums: [AlbumDetailed, "[]"],
|
topAlbums: [AlbumDetailed, "[]"],
|
||||||
topSingles: [AlbumDetailed, "[]"],
|
topSingles: [AlbumDetailed, "[]"],
|
||||||
|
|
@ -117,7 +114,7 @@ export const AlbumFull = type({
|
||||||
albumId: "string",
|
albumId: "string",
|
||||||
playlistId: "string",
|
playlistId: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
artists: [ArtistBasic, "[]"],
|
artist: ArtistBasic,
|
||||||
year: "number|null",
|
year: "number|null",
|
||||||
thumbnails: [ThumbnailFull, "[]"],
|
thumbnails: [ThumbnailFull, "[]"],
|
||||||
songs: [SongDetailed, "[]"],
|
songs: [SongDetailed, "[]"],
|
||||||
|
|
|
||||||
|
|
@ -389,16 +389,12 @@ export default class YTMusic {
|
||||||
* @returns Artist's Songs
|
* @returns Artist's Songs
|
||||||
*/
|
*/
|
||||||
public async getArtistSongs(artistId: string): Promise<(typeof SongDetailed.infer)[]> {
|
public async getArtistSongs(artistId: string): Promise<(typeof SongDetailed.infer)[]> {
|
||||||
const artistData = await this.constructRequest("browse", {
|
const artistData = await this.constructRequest("browse", { browseId: artistId })
|
||||||
browseId: artistId,
|
|
||||||
})
|
|
||||||
const browseToken = traverse(artistData, "musicShelfRenderer", "title", "browseId")
|
const browseToken = traverse(artistData, "musicShelfRenderer", "title", "browseId")
|
||||||
|
|
||||||
if (browseToken instanceof Array) return []
|
if (browseToken instanceof Array) return []
|
||||||
|
|
||||||
const songsData = await this.constructRequest("browse", {
|
const songsData = await this.constructRequest("browse", { browseId: browseToken })
|
||||||
browseId: browseToken,
|
|
||||||
})
|
|
||||||
const continueToken = traverse(songsData, "continuation")
|
const continueToken = traverse(songsData, "continuation")
|
||||||
const moreSongsData = await this.constructRequest(
|
const moreSongsData = await this.constructRequest(
|
||||||
"browse",
|
"browse",
|
||||||
|
|
@ -409,7 +405,12 @@ export default class YTMusic {
|
||||||
return [
|
return [
|
||||||
...traverseList(songsData, "musicResponsiveListItemRenderer"),
|
...traverseList(songsData, "musicResponsiveListItemRenderer"),
|
||||||
...traverseList(moreSongsData, "musicResponsiveListItemRenderer"),
|
...traverseList(moreSongsData, "musicResponsiveListItemRenderer"),
|
||||||
].map(SongParser.parseArtistSong)
|
].map(s =>
|
||||||
|
SongParser.parseArtistSong(s, {
|
||||||
|
artistId,
|
||||||
|
name: traverseString(artistData, "header", "title", "text")(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import { AlbumBasic, AlbumDetailed, AlbumFull, ArtistBasic } from "../@types/types"
|
import { AlbumBasic, AlbumDetailed, AlbumFull, ArtistBasic } from "../@types/types"
|
||||||
import checkType from "../utils/checkType"
|
import checkType from "../utils/checkType"
|
||||||
|
import { isArtist } from "../utils/filters"
|
||||||
|
import traverse from "../utils/traverse"
|
||||||
import traverseList from "../utils/traverseList"
|
import traverseList from "../utils/traverseList"
|
||||||
import traverseString from "../utils/traverseString"
|
import traverseString from "../utils/traverseString"
|
||||||
import SongParser from "./SongParser"
|
import SongParser from "./SongParser"
|
||||||
|
|
@ -11,12 +13,11 @@ export default class AlbumParser {
|
||||||
name: traverseString(data, "header", "title", "text")(),
|
name: traverseString(data, "header", "title", "text")(),
|
||||||
}
|
}
|
||||||
|
|
||||||
const artists: ArtistBasic[] = traverseList(data, "header", "subtitle", "runs")
|
const artistData = traverse(data, "header", "subtitle", "runs")
|
||||||
.filter(run => "navigationEndpoint" in run)
|
const artistBasic: ArtistBasic = {
|
||||||
.map(run => ({
|
artistId: traverseString(artistData, "browseId")(),
|
||||||
artistId: traverseString(run, "browseId")(),
|
name: traverseString(artistData, "text")(),
|
||||||
name: traverseString(run, "text")(),
|
}
|
||||||
}))
|
|
||||||
|
|
||||||
const thumbnails = traverseList(data, "header", "thumbnails")
|
const thumbnails = traverseList(data, "header", "thumbnails")
|
||||||
|
|
||||||
|
|
@ -25,13 +26,13 @@ export default class AlbumParser {
|
||||||
type: "ALBUM",
|
type: "ALBUM",
|
||||||
...albumBasic,
|
...albumBasic,
|
||||||
playlistId: traverseString(data, "buttonRenderer", "playlistId")(),
|
playlistId: traverseString(data, "buttonRenderer", "playlistId")(),
|
||||||
artists,
|
artist: artistBasic,
|
||||||
year: AlbumParser.processYear(
|
year: AlbumParser.processYear(
|
||||||
traverseString(data, "header", "subtitle", "text")(-1),
|
traverseString(data, "header", "subtitle", "text")(-1),
|
||||||
),
|
),
|
||||||
thumbnails,
|
thumbnails,
|
||||||
songs: traverseList(data, "musicResponsiveListItemRenderer").map(item =>
|
songs: traverseList(data, "musicResponsiveListItemRenderer").map(item =>
|
||||||
SongParser.parseAlbumSong(item, artists, albumBasic, thumbnails),
|
SongParser.parseAlbumSong(item, artistBasic, albumBasic, thumbnails),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
AlbumFull,
|
AlbumFull,
|
||||||
|
|
@ -39,21 +40,23 @@ export default class AlbumParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseSearchResult(item: any): AlbumDetailed {
|
public static parseSearchResult(item: any): AlbumDetailed {
|
||||||
const flexColumns = traverseList(item, "flexColumns")
|
const columns = traverseList(item, "flexColumns", "runs").flat()
|
||||||
|
|
||||||
|
// No specific way to identify the title
|
||||||
|
const title = columns[0]
|
||||||
|
const artist = columns.find(isArtist) || columns[3]
|
||||||
|
|
||||||
return checkType(
|
return checkType(
|
||||||
{
|
{
|
||||||
type: "ALBUM",
|
type: "ALBUM",
|
||||||
albumId: traverseString(item, "browseId")(-1),
|
albumId: traverseString(item, "browseId")(-1),
|
||||||
playlistId: traverseString(item, "overlay", "playlistId")(),
|
playlistId: traverseString(item, "overlay", "playlistId")(),
|
||||||
artists: traverseList(flexColumns[1], "runs")
|
artist: {
|
||||||
.filter(run => "navigationEndpoint" in run)
|
name: traverseString(artist, "text")(),
|
||||||
.map(run => ({
|
artistId: traverseString(artist, "browseId")() || null,
|
||||||
artistId: traverseString(run, "browseId")(),
|
},
|
||||||
name: traverseString(run, "text")(),
|
year: AlbumParser.processYear(traverseString(columns[1], "runs", "text")(-1)),
|
||||||
})),
|
name: traverseString(title, "text")(),
|
||||||
year: AlbumParser.processYear(traverseString(flexColumns[1], "runs", "text")(-1)),
|
|
||||||
name: traverseString(flexColumns[0], "runs", "text")(),
|
|
||||||
thumbnails: traverseList(item, "thumbnails"),
|
thumbnails: traverseList(item, "thumbnails"),
|
||||||
},
|
},
|
||||||
AlbumDetailed,
|
AlbumDetailed,
|
||||||
|
|
@ -67,7 +70,7 @@ export default class AlbumParser {
|
||||||
albumId: traverseString(item, "browseId")(-1),
|
albumId: traverseString(item, "browseId")(-1),
|
||||||
playlistId: traverseString(item, "thumbnailOverlay", "playlistId")(),
|
playlistId: traverseString(item, "thumbnailOverlay", "playlistId")(),
|
||||||
name: traverseString(item, "title", "text")(),
|
name: traverseString(item, "title", "text")(),
|
||||||
artists: [artistBasic],
|
artist: artistBasic,
|
||||||
year: AlbumParser.processYear(traverseString(item, "subtitle", "text")(-1)),
|
year: AlbumParser.processYear(traverseString(item, "subtitle", "text")(-1)),
|
||||||
thumbnails: traverseList(item, "thumbnails"),
|
thumbnails: traverseList(item, "thumbnails"),
|
||||||
},
|
},
|
||||||
|
|
@ -82,7 +85,7 @@ export default class AlbumParser {
|
||||||
albumId: traverseString(item, "browseId")(-1),
|
albumId: traverseString(item, "browseId")(-1),
|
||||||
playlistId: traverseString(item, "musicPlayButtonRenderer", "playlistId")(),
|
playlistId: traverseString(item, "musicPlayButtonRenderer", "playlistId")(),
|
||||||
name: traverseString(item, "title", "text")(),
|
name: traverseString(item, "title", "text")(),
|
||||||
artists: [artistBasic],
|
artist: artistBasic,
|
||||||
year: AlbumParser.processYear(traverseString(item, "subtitle", "text")(-1)),
|
year: AlbumParser.processYear(traverseString(item, "subtitle", "text")(-1)),
|
||||||
thumbnails: traverseList(item, "thumbnails"),
|
thumbnails: traverseList(item, "thumbnails"),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,11 @@ export default class ArtistParser {
|
||||||
name: traverseString(data, "header", "title", "text")(),
|
name: traverseString(data, "header", "title", "text")(),
|
||||||
}
|
}
|
||||||
|
|
||||||
const description = traverseString(data, "header", "description", "text")()
|
|
||||||
|
|
||||||
return checkType(
|
return checkType(
|
||||||
{
|
{
|
||||||
type: "ARTIST",
|
type: "ARTIST",
|
||||||
...artistBasic,
|
...artistBasic,
|
||||||
thumbnails: traverseList(data, "header", "thumbnails"),
|
thumbnails: traverseList(data, "header", "thumbnails"),
|
||||||
description,
|
|
||||||
topSongs: traverseList(data, "musicShelfRenderer", "contents").map(item =>
|
topSongs: traverseList(data, "musicShelfRenderer", "contents").map(item =>
|
||||||
SongParser.parseArtistTopSong(item, artistBasic),
|
SongParser.parseArtistTopSong(item, artistBasic),
|
||||||
),
|
),
|
||||||
|
|
@ -46,8 +43,9 @@ export default class ArtistParser {
|
||||||
featuredOn:
|
featuredOn:
|
||||||
traverseList(data, "musicCarouselShelfRenderer")
|
traverseList(data, "musicCarouselShelfRenderer")
|
||||||
?.at(3)
|
?.at(3)
|
||||||
?.contents.map((item: any) => PlaylistParser.parseArtistFeaturedOn(item)) ??
|
?.contents.map((item: any) =>
|
||||||
[],
|
PlaylistParser.parseArtistFeaturedOn(item, artistBasic),
|
||||||
|
) ?? [],
|
||||||
similarArtists:
|
similarArtists:
|
||||||
traverseList(data, "musicCarouselShelfRenderer")
|
traverseList(data, "musicCarouselShelfRenderer")
|
||||||
?.at(4)
|
?.at(4)
|
||||||
|
|
@ -58,7 +56,7 @@ export default class ArtistParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseSearchResult(item: any): ArtistDetailed {
|
public static parseSearchResult(item: any): ArtistDetailed {
|
||||||
const columns = traverseList(item, "flexColumns")
|
const columns = traverseList(item, "flexColumns", "runs").flat()
|
||||||
|
|
||||||
// No specific way to identify the title
|
// No specific way to identify the title
|
||||||
const title = columns[0]
|
const title = columns[0]
|
||||||
|
|
@ -67,7 +65,7 @@ export default class ArtistParser {
|
||||||
{
|
{
|
||||||
type: "ARTIST",
|
type: "ARTIST",
|
||||||
artistId: traverseString(item, "browseId")(),
|
artistId: traverseString(item, "browseId")(),
|
||||||
name: traverseString(title, "runs", "text")(),
|
name: traverseString(title, "text")(),
|
||||||
thumbnails: traverseList(item, "thumbnails"),
|
thumbnails: traverseList(item, "thumbnails"),
|
||||||
},
|
},
|
||||||
ArtistDetailed,
|
ArtistDetailed,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { PlaylistDetailed, PlaylistFull } from "../@types/types"
|
import { ArtistBasic, PlaylistDetailed, PlaylistFull } from "../@types/types"
|
||||||
import checkType from "../utils/checkType"
|
import checkType from "../utils/checkType"
|
||||||
import { isArtist } from "../utils/filters"
|
import { isArtist } from "../utils/filters"
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
|
|
@ -53,16 +53,13 @@ export default class PlaylistParser {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseArtistFeaturedOn(item: any): PlaylistDetailed {
|
public static parseArtistFeaturedOn(item: any, artistBasic: ArtistBasic): PlaylistDetailed {
|
||||||
return checkType(
|
return checkType(
|
||||||
{
|
{
|
||||||
type: "PLAYLIST",
|
type: "PLAYLIST",
|
||||||
playlistId: traverseString(item, "navigationEndpoint", "browseId")(),
|
playlistId: traverseString(item, "navigationEndpoint", "browseId")(),
|
||||||
name: traverseString(item, "runs", "text")(),
|
name: traverseString(item, "runs", "text")(),
|
||||||
artist: {
|
artist: artistBasic,
|
||||||
artistId: traverseString(item, "browseId")(),
|
|
||||||
name: traverseString(item, "runs", "text")(-3),
|
|
||||||
},
|
|
||||||
thumbnails: traverseList(item, "thumbnails"),
|
thumbnails: traverseList(item, "thumbnails"),
|
||||||
},
|
},
|
||||||
PlaylistDetailed,
|
PlaylistDetailed,
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,12 @@ export default class SongParser {
|
||||||
type: "SONG",
|
type: "SONG",
|
||||||
videoId: traverseString(data, "videoDetails", "videoId")(),
|
videoId: traverseString(data, "videoDetails", "videoId")(),
|
||||||
name: traverseString(data, "videoDetails", "title")(),
|
name: traverseString(data, "videoDetails", "title")(),
|
||||||
artists: [
|
artist: {
|
||||||
{
|
|
||||||
artistId: traverseString(data, "videoDetails", "channelId")(),
|
|
||||||
name: traverseString(data, "author")(),
|
name: traverseString(data, "author")(),
|
||||||
|
artistId: traverseString(data, "videoDetails", "channelId")(),
|
||||||
},
|
},
|
||||||
],
|
|
||||||
duration: +traverseString(data, "videoDetails", "lengthSeconds")(),
|
duration: +traverseString(data, "videoDetails", "lengthSeconds")(),
|
||||||
thumbnails: traverseList(data, "videoDetails", "thumbnails"),
|
thumbnails: traverseList(data, "videoDetails", "thumbnails"),
|
||||||
description: traverseString(data, "description")(),
|
|
||||||
formats: traverseList(data, "streamingData", "formats"),
|
formats: traverseList(data, "streamingData", "formats"),
|
||||||
adaptiveFormats: traverseList(data, "streamingData", "adaptiveFormats"),
|
adaptiveFormats: traverseList(data, "streamingData", "adaptiveFormats"),
|
||||||
},
|
},
|
||||||
|
|
@ -41,12 +38,10 @@ export default class SongParser {
|
||||||
type: "SONG",
|
type: "SONG",
|
||||||
videoId: traverseString(item, "playlistItemData", "videoId")(),
|
videoId: traverseString(item, "playlistItemData", "videoId")(),
|
||||||
name: traverseString(title, "text")(),
|
name: traverseString(title, "text")(),
|
||||||
artists: [
|
artist: {
|
||||||
{
|
|
||||||
name: traverseString(artist, "text")(),
|
name: traverseString(artist, "text")(),
|
||||||
artistId: traverseString(artist, "browseId")(),
|
artistId: traverseString(artist, "browseId")(),
|
||||||
},
|
},
|
||||||
],
|
|
||||||
album: {
|
album: {
|
||||||
name: traverseString(album, "text")(),
|
name: traverseString(album, "text")(),
|
||||||
albumId: traverseString(album, "browseId")(),
|
albumId: traverseString(album, "browseId")(),
|
||||||
|
|
@ -58,11 +53,10 @@ export default class SongParser {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseArtistSong(item: any): SongDetailed {
|
public static parseArtistSong(item: any, artistBasic: ArtistBasic): SongDetailed {
|
||||||
const columns = traverseList(item, "flexColumns", "runs").flat()
|
const columns = traverseList(item, "flexColumns", "runs").flat()
|
||||||
|
|
||||||
const title = columns.find(isTitle)
|
const title = columns.find(isTitle)
|
||||||
const artist = columns.find(isArtist)
|
|
||||||
const album = columns.find(isAlbum)
|
const album = columns.find(isAlbum)
|
||||||
const duration = columns.find(isDuration)
|
const duration = columns.find(isDuration)
|
||||||
|
|
||||||
|
|
@ -71,12 +65,7 @@ export default class SongParser {
|
||||||
type: "SONG",
|
type: "SONG",
|
||||||
videoId: traverseString(item, "playlistItemData", "videoId")(),
|
videoId: traverseString(item, "playlistItemData", "videoId")(),
|
||||||
name: traverseString(title, "text")(),
|
name: traverseString(title, "text")(),
|
||||||
artists: [
|
artist: artistBasic,
|
||||||
{
|
|
||||||
name: traverseString(artist, "text")(),
|
|
||||||
artistId: traverseString(artist, "browseId")(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
album: {
|
album: {
|
||||||
name: traverseString(album, "text")(),
|
name: traverseString(album, "text")(),
|
||||||
albumId: traverseString(album, "browseId")(),
|
albumId: traverseString(album, "browseId")(),
|
||||||
|
|
@ -99,7 +88,7 @@ export default class SongParser {
|
||||||
type: "SONG",
|
type: "SONG",
|
||||||
videoId: traverseString(item, "playlistItemData", "videoId")(),
|
videoId: traverseString(item, "playlistItemData", "videoId")(),
|
||||||
name: traverseString(title, "text")(),
|
name: traverseString(title, "text")(),
|
||||||
artists: [artistBasic],
|
artist: artistBasic,
|
||||||
album: {
|
album: {
|
||||||
name: traverseString(album, "text")(),
|
name: traverseString(album, "text")(),
|
||||||
albumId: traverseString(album, "browseId")(),
|
albumId: traverseString(album, "browseId")(),
|
||||||
|
|
@ -113,7 +102,7 @@ export default class SongParser {
|
||||||
|
|
||||||
public static parseAlbumSong(
|
public static parseAlbumSong(
|
||||||
item: any,
|
item: any,
|
||||||
artists: ArtistBasic[],
|
artistBasic: ArtistBasic,
|
||||||
albumBasic: AlbumBasic,
|
albumBasic: AlbumBasic,
|
||||||
thumbnails: ThumbnailFull[],
|
thumbnails: ThumbnailFull[],
|
||||||
): SongDetailed {
|
): SongDetailed {
|
||||||
|
|
@ -127,7 +116,7 @@ export default class SongParser {
|
||||||
type: "SONG",
|
type: "SONG",
|
||||||
videoId: traverseString(item, "playlistItemData", "videoId")(),
|
videoId: traverseString(item, "playlistItemData", "videoId")(),
|
||||||
name: traverseString(title, "text")(),
|
name: traverseString(title, "text")(),
|
||||||
artists,
|
artist: artistBasic,
|
||||||
album: albumBasic,
|
album: albumBasic,
|
||||||
duration: duration ? Parser.parseDuration(duration.text) : null,
|
duration: duration ? Parser.parseDuration(duration.text) : null,
|
||||||
thumbnails,
|
thumbnails,
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,12 @@ export default class VideoParser {
|
||||||
type: "VIDEO",
|
type: "VIDEO",
|
||||||
videoId: traverseString(data, "videoDetails", "videoId")(),
|
videoId: traverseString(data, "videoDetails", "videoId")(),
|
||||||
name: traverseString(data, "videoDetails", "title")(),
|
name: traverseString(data, "videoDetails", "title")(),
|
||||||
artists: [
|
artist: {
|
||||||
{
|
|
||||||
artistId: traverseString(data, "videoDetails", "channelId")(),
|
artistId: traverseString(data, "videoDetails", "channelId")(),
|
||||||
name: traverseString(data, "author")(),
|
name: traverseString(data, "author")(),
|
||||||
},
|
},
|
||||||
],
|
|
||||||
duration: +traverseString(data, "videoDetails", "lengthSeconds")(),
|
duration: +traverseString(data, "videoDetails", "lengthSeconds")(),
|
||||||
thumbnails: traverseList(data, "videoDetails", "thumbnails"),
|
thumbnails: traverseList(data, "videoDetails", "thumbnails"),
|
||||||
description: traverseString(data, "description")(),
|
|
||||||
unlisted: traverse(data, "unlisted"),
|
unlisted: traverse(data, "unlisted"),
|
||||||
familySafe: traverse(data, "familySafe"),
|
familySafe: traverse(data, "familySafe"),
|
||||||
paid: traverse(data, "paid"),
|
paid: traverse(data, "paid"),
|
||||||
|
|
@ -39,12 +36,10 @@ export default class VideoParser {
|
||||||
type: "VIDEO",
|
type: "VIDEO",
|
||||||
videoId: traverseString(item, "playNavigationEndpoint", "videoId")(),
|
videoId: traverseString(item, "playNavigationEndpoint", "videoId")(),
|
||||||
name: traverseString(title, "text")(),
|
name: traverseString(title, "text")(),
|
||||||
artists: [
|
artist: {
|
||||||
{
|
|
||||||
name: traverseString(artist, "text")(),
|
name: traverseString(artist, "text")(),
|
||||||
artistId: traverseString(artist, "browseId")(),
|
artistId: traverseString(artist, "browseId")(),
|
||||||
},
|
},
|
||||||
],
|
|
||||||
duration: Parser.parseDuration(duration.text),
|
duration: Parser.parseDuration(duration.text),
|
||||||
thumbnails: traverseList(item, "thumbnails"),
|
thumbnails: traverseList(item, "thumbnails"),
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +50,7 @@ export default class VideoParser {
|
||||||
type: "VIDEO",
|
type: "VIDEO",
|
||||||
videoId: traverseString(item, "videoId")(),
|
videoId: traverseString(item, "videoId")(),
|
||||||
name: traverseString(item, "runs", "text")(),
|
name: traverseString(item, "runs", "text")(),
|
||||||
artists: [artistBasic],
|
artist: artistBasic,
|
||||||
duration: null,
|
duration: null,
|
||||||
thumbnails: traverseList(item, "thumbnails"),
|
thumbnails: traverseList(item, "thumbnails"),
|
||||||
}
|
}
|
||||||
|
|
@ -77,12 +72,10 @@ export default class VideoParser {
|
||||||
/https:\/\/i\.ytimg\.com\/vi\/(.+)\//,
|
/https:\/\/i\.ytimg\.com\/vi\/(.+)\//,
|
||||||
)[1],
|
)[1],
|
||||||
name: traverseString(title, "text")(),
|
name: traverseString(title, "text")(),
|
||||||
artists: [
|
artist: {
|
||||||
{
|
|
||||||
name: traverseString(artist, "text")(),
|
name: traverseString(artist, "text")(),
|
||||||
artistId: traverseString(artist, "browseId")() || null,
|
artistId: traverseString(artist, "browseId")() || null,
|
||||||
},
|
},
|
||||||
],
|
|
||||||
duration: duration ? Parser.parseDuration(duration.text) : null,
|
duration: duration ? Parser.parseDuration(duration.text) : null,
|
||||||
thumbnails: traverseList(item, "thumbnails"),
|
thumbnails: traverseList(item, "thumbnails"),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue