Moved methods all over, all artist methods work
This commit is contained in:
parent
779035391c
commit
f5b5047c31
|
|
@ -240,11 +240,11 @@ export default class YTMusic {
|
||||||
|
|
||||||
return traverse(searchData, "musicResponsiveListItemRenderer").map(
|
return traverse(searchData, "musicResponsiveListItemRenderer").map(
|
||||||
{
|
{
|
||||||
SONG: SongParser.parseSearch,
|
SONG: SongParser.parseSearchResult,
|
||||||
VIDEO: VideoParser.parseSearch,
|
VIDEO: VideoParser.parseSearchResult,
|
||||||
ARTIST: ArtistParser.parseSearch,
|
ARTIST: ArtistParser.parseSearchResult,
|
||||||
ALBUM: AlbumParser.parseSearch,
|
ALBUM: AlbumParser.parseSearchResult,
|
||||||
PLAYLIST: PlaylistParser.parseSearch
|
PLAYLIST: PlaylistParser.parseSearchResult
|
||||||
}[category!] || SearchParser.parse
|
}[category!] || SearchParser.parse
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -261,12 +261,24 @@ export default class YTMusic {
|
||||||
fs.writeFileSync("data.json", JSON.stringify(data))
|
fs.writeFileSync("data.json", JSON.stringify(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all possible information of an Artist
|
||||||
|
*
|
||||||
|
* @param artistId Artist ID
|
||||||
|
* @returns Artist Data
|
||||||
|
*/
|
||||||
public async getArtist(artistId: string): Promise<YTMusic.ArtistFull> {
|
public async getArtist(artistId: string): Promise<YTMusic.ArtistFull> {
|
||||||
const data = await this.constructRequest("browse", { browseId: artistId })
|
const data = await this.constructRequest("browse", { browseId: artistId })
|
||||||
|
|
||||||
return new ArtistParser(data).parse(artistId)
|
return new ArtistParser(data).parse(artistId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of Artist's Songs
|
||||||
|
*
|
||||||
|
* @param artistId Artist ID
|
||||||
|
* @returns Artist's Songs
|
||||||
|
*/
|
||||||
public async getArtistSongs(artistId: string): Promise<YTMusic.SongDetailed[]> {
|
public async getArtistSongs(artistId: string): Promise<YTMusic.SongDetailed[]> {
|
||||||
const artistData = await this.constructRequest("browse", { browseId: artistId })
|
const artistData = await this.constructRequest("browse", { browseId: artistId })
|
||||||
const browseToken = traverse(artistData, "musicShelfRenderer", "title", "browseId")
|
const browseToken = traverse(artistData, "musicShelfRenderer", "title", "browseId")
|
||||||
|
|
@ -279,9 +291,15 @@ export default class YTMusic {
|
||||||
{ continuation: continueToken }
|
{ continuation: continueToken }
|
||||||
)
|
)
|
||||||
|
|
||||||
return ArtistParser.parseSongs(songsData, moreSongsData)
|
return SongParser.parseArtistSongs(songsData, moreSongsData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of Artist's Albums
|
||||||
|
*
|
||||||
|
* @param artistId Artist ID
|
||||||
|
* @returns Artist's Albums
|
||||||
|
*/
|
||||||
public async getArtistAlbums(artistId: string): Promise<YTMusic.AlbumDetailed[]> {
|
public async getArtistAlbums(artistId: string): Promise<YTMusic.AlbumDetailed[]> {
|
||||||
const artistData = await this.constructRequest("browse", { browseId: artistId })
|
const artistData = await this.constructRequest("browse", { browseId: artistId })
|
||||||
const artistAlbumsData = traverse(artistData, "musicCarouselShelfRenderer")[0]
|
const artistAlbumsData = traverse(artistData, "musicCarouselShelfRenderer")[0]
|
||||||
|
|
@ -289,7 +307,7 @@ export default class YTMusic {
|
||||||
|
|
||||||
const albumsData = await this.constructRequest("browse", browseBody)
|
const albumsData = await this.constructRequest("browse", browseBody)
|
||||||
|
|
||||||
return ArtistParser.parseAlbums(artistId, albumsData)
|
return AlbumParser.parseArtistAlbums(artistId, albumsData)
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAlbum(albumId: string) {
|
public async getAlbum(albumId: string) {
|
||||||
|
|
@ -303,4 +321,4 @@ export default class YTMusic {
|
||||||
|
|
||||||
fs.writeFileSync("data.json", JSON.stringify(data))
|
fs.writeFileSync("data.json", JSON.stringify(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ import YTMusic from "./YTMusic"
|
||||||
|
|
||||||
const ytmusic = new YTMusic()
|
const ytmusic = new YTMusic()
|
||||||
ytmusic.initialize().then(() => {
|
ytmusic.initialize().then(() => {
|
||||||
ytmusic.search("Yours Raiden", "ALBUM").then(res => {
|
ytmusic.search("Yours Raiden", "ARTIST").then(res => {
|
||||||
console.log(JSON.stringify(res, null, 4))
|
ytmusic.getArtistAlbums(res[0].artistId).then(res => {
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
import fs from "fs"
|
|
||||||
|
|
||||||
export default class AlbumParser {
|
export default class AlbumParser {
|
||||||
public static parseSearch(item: any): YTMusic.AlbumDetailed {
|
public static parseSearchResult(item: any): YTMusic.AlbumDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const thumbnails = traverse(item, "thumbnails")
|
const thumbnails = traverse(item, "thumbnails")
|
||||||
|
|
||||||
|
|
@ -18,4 +17,36 @@ export default class AlbumParser {
|
||||||
thumbnails: [thumbnails].flat()
|
thumbnails: [thumbnails].flat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static parseArtistAlbums(artistId: string, albumsData: any): YTMusic.AlbumDetailed[] {
|
||||||
|
return traverse(albumsData, "musicTwoRowItemRenderer").map((item: any) => ({
|
||||||
|
type: "ALBUM",
|
||||||
|
albumId: [traverse(item, "browseId")].flat().at(-1),
|
||||||
|
playlistId: traverse(item, "thumbnailOverlay", "playlistId"),
|
||||||
|
name: traverse(item, "title", "text").at(0),
|
||||||
|
artists: [
|
||||||
|
{
|
||||||
|
artistId,
|
||||||
|
name: traverse(albumsData, "header", "text").at(0)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
year: +traverse(item, "subtitle", "text").at(-1),
|
||||||
|
thumbnails: [traverse(item, "thumbnails")].flat()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
public static parseArtistTopAlbums(
|
||||||
|
item: any,
|
||||||
|
artistBasic: YTMusic.ArtistBasic
|
||||||
|
): YTMusic.AlbumDetailed {
|
||||||
|
return {
|
||||||
|
type: "ALBUM",
|
||||||
|
albumId: traverse(item, "browseId").at(-1),
|
||||||
|
playlistId: traverse(item, "musicPlayButtonRenderer", "playlistId"),
|
||||||
|
name: traverse(item, "title", "text").at(0),
|
||||||
|
artists: [artistBasic],
|
||||||
|
year: +traverse(item, "subtitle", "text").at(-1),
|
||||||
|
thumbnails: [traverse(item, "thumbnails")].flat()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
import AlbumParser from "./AlbumParser"
|
||||||
import Parse from "./Parser"
|
import Parse from "./Parser"
|
||||||
|
import SongParser from "./SongParser"
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
|
|
||||||
export default class ArtistParser {
|
export default class ArtistParser {
|
||||||
|
|
@ -8,7 +10,7 @@ export default class ArtistParser {
|
||||||
this.data = data
|
this.data = data
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseSearch(item: any): YTMusic.ArtistDetailed {
|
public static parseSearchResult(item: any): YTMusic.ArtistDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const thumbnails = traverse(item, "thumbnails")
|
const thumbnails = traverse(item, "thumbnails")
|
||||||
|
|
||||||
|
|
@ -26,81 +28,21 @@ export default class ArtistParser {
|
||||||
name: traverse(this.data, "header", "title", "text").at(0)
|
name: traverse(this.data, "header", "title", "text").at(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const description = traverse(this.data, "header", "description", "text")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "ARTIST",
|
type: "ARTIST",
|
||||||
...artistBasic,
|
...artistBasic,
|
||||||
thumbnails: traverse(this.data, "header", "thumbnails"),
|
thumbnails: traverse(this.data, "header", "thumbnails"),
|
||||||
description: traverse(this.data, "header", "description", "text"),
|
description: description instanceof Array ? null : description,
|
||||||
subscribers: Parse.parseNumber(traverse(this.data, "subscriberCountText", "text")),
|
subscribers: Parse.parseNumber(traverse(this.data, "subscriberCountText", "text")),
|
||||||
topTracks: traverse(this.data, "musicShelfRenderer", "contents").map((item: any) => {
|
topSongs: traverse(this.data, "musicShelfRenderer", "contents").map((item: any) =>
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
SongParser.parseArtistTopSong(item, artistBasic)
|
||||||
|
),
|
||||||
return {
|
topAlbums: [traverse(this.data, "musicCarouselShelfRenderer", "contents")]
|
||||||
type: "SONG",
|
|
||||||
videoId: traverse(item, "playlistItemData", "videoId"),
|
|
||||||
name: traverse(flexColumns[0], "runs", "text"),
|
|
||||||
artists: [artistBasic],
|
|
||||||
album: {
|
|
||||||
albumId: traverse(flexColumns[2], "runs", "text"),
|
|
||||||
name: traverse(flexColumns[2], "browseId")
|
|
||||||
},
|
|
||||||
thumbnails: [traverse(item, "thumbnails")].flat()
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
topAlbums: [traverse(this.data, "musicCarouselShelfRenderer")]
|
|
||||||
.flat()
|
.flat()
|
||||||
.at(0)
|
.at(0)
|
||||||
.contents.map((item: any) => ({
|
.map((item: any) => AlbumParser.parseArtistTopAlbums(item, artistBasic))
|
||||||
type: "ALBUM",
|
|
||||||
albumId: traverse(item, "browseId").at(-1),
|
|
||||||
playlistId: traverse(item, "musicPlayButtonRenderer", "playlistId"),
|
|
||||||
name: traverse(item, "title", "text").at(0),
|
|
||||||
artists: [artistBasic],
|
|
||||||
year: +traverse(item, "subtitle", "text").at(-1),
|
|
||||||
thumbnails: [traverse(item, "thumbnails")].flat()
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseSongs(songsData: any, moreSongsData: any): YTMusic.SongDetailed[] {
|
|
||||||
return [
|
|
||||||
...traverse(songsData, "musicResponsiveListItemRenderer"),
|
|
||||||
...traverse(moreSongsData, "musicResponsiveListItemRenderer")
|
|
||||||
].map((item: any) => {
|
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: "SONG",
|
|
||||||
videoId: traverse(item, "playlistItemData", "videoId"),
|
|
||||||
name: traverse(flexColumns[0], "runs", "text"),
|
|
||||||
artists: [traverse(flexColumns[1], "runs")].flat().map((run: any) => ({
|
|
||||||
name: run.text,
|
|
||||||
artistId: traverse(run, "browseId")
|
|
||||||
})),
|
|
||||||
album: {
|
|
||||||
albumId: traverse(flexColumns[2], "browseId"),
|
|
||||||
name: traverse(flexColumns[2], "runs", "text")
|
|
||||||
},
|
|
||||||
duration: Parse.parseDuration(traverse(item, "fixedColumns", "runs", "text")),
|
|
||||||
thumbnails: [traverse(item, "thumbnails")].flat()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public static parseAlbums(artistId: string, albumsData: any): YTMusic.AlbumDetailed[] {
|
|
||||||
return traverse(albumsData, "musicTwoRowItemRenderer").map((item: any) => ({
|
|
||||||
type: "ALBUM",
|
|
||||||
albumId: [traverse(item, "browseId")].flat().at(-1),
|
|
||||||
playlistId: traverse(item, "thumbnailOverlay", "playlistId"),
|
|
||||||
name: traverse(item, "title", "text").at(0),
|
|
||||||
artists: [
|
|
||||||
{
|
|
||||||
artistId,
|
|
||||||
name: traverse(albumsData, "header", "text").at(0)
|
|
||||||
}
|
|
||||||
],
|
|
||||||
year: +traverse(item, "subtitle", "text").at(-1),
|
|
||||||
thumbnails: [traverse(item, "thumbnails")].flat()
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
|
|
||||||
export default class PlaylistParser {
|
export default class PlaylistParser {
|
||||||
public static parseSearch(item: any, specific: boolean): YTMusic.PlaylistDetailed {
|
public static parseSearchResult(item: any, specific: boolean): YTMusic.PlaylistDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const thumbnails = traverse(item, "thumbnails")
|
const thumbnails = traverse(item, "thumbnails")
|
||||||
const artistId = traverse(flexColumns[1], "browseId")
|
const artistId = traverse(flexColumns[1], "browseId")
|
||||||
|
|
@ -11,7 +11,7 @@ export default class PlaylistParser {
|
||||||
playlistId: traverse(item, "overlay", "playlistId"),
|
playlistId: traverse(item, "overlay", "playlistId"),
|
||||||
name: traverse(flexColumns[0], "runs", "text"),
|
name: traverse(flexColumns[0], "runs", "text"),
|
||||||
artist: {
|
artist: {
|
||||||
artistId: artistId instanceof Array ? undefined : artistId,
|
artistId: artistId instanceof Array ? null : artistId,
|
||||||
name: traverse(flexColumns[1], "runs", "text").at(specific ? 0 : 2)
|
name: traverse(flexColumns[1], "runs", "text").at(specific ? 0 : 2)
|
||||||
},
|
},
|
||||||
trackCount: +traverse(flexColumns[1], "runs", "text").at(-1).split(" ").at(0),
|
trackCount: +traverse(flexColumns[1], "runs", "text").at(-1).split(" ").at(0),
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,13 @@ export default class SearchParser {
|
||||||
| "Playlist"
|
| "Playlist"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Song: () => SongParser.parseSearch(item),
|
Song: () => SongParser.parseSearchResult(item),
|
||||||
Video: () => VideoParser.parseSearch(item, true),
|
Video: () => VideoParser.parseSearchResult(item, true),
|
||||||
Artist: () => ArtistParser.parseSearch(item),
|
Artist: () => ArtistParser.parseSearchResult(item),
|
||||||
EP: () => AlbumParser.parseSearch(item),
|
EP: () => AlbumParser.parseSearchResult(item),
|
||||||
Single: () => AlbumParser.parseSearch(item),
|
Single: () => AlbumParser.parseSearchResult(item),
|
||||||
Album: () => AlbumParser.parseSearch(item),
|
Album: () => AlbumParser.parseSearchResult(item),
|
||||||
Playlist: () => PlaylistParser.parseSearch(item, true)
|
Playlist: () => PlaylistParser.parseSearchResult(item, true)
|
||||||
}[type]()
|
}[type]()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import Parser from "./Parser"
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
|
|
||||||
export default class SongParser {
|
export default class SongParser {
|
||||||
public static parseSearch(item: any): YTMusic.SongDetailed {
|
public static parseSearchResult(item: any): YTMusic.SongDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const thumbnails = traverse(item, "thumbnails")
|
const thumbnails = traverse(item, "thumbnails")
|
||||||
|
|
||||||
|
|
@ -26,4 +26,51 @@ export default class SongParser {
|
||||||
thumbnails: thumbnails
|
thumbnails: thumbnails
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static parseArtistSongs(songsData: any, moreSongsData: any): YTMusic.SongDetailed[] {
|
||||||
|
return [
|
||||||
|
...traverse(songsData, "musicResponsiveListItemRenderer"),
|
||||||
|
...traverse(moreSongsData, "musicResponsiveListItemRenderer")
|
||||||
|
].map((item: any) => {
|
||||||
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "SONG",
|
||||||
|
videoId: traverse(item, "playlistItemData", "videoId"),
|
||||||
|
name: traverse(flexColumns[0], "runs", "text"),
|
||||||
|
artists: [traverse(flexColumns[1], "runs")]
|
||||||
|
.flat()
|
||||||
|
.filter((item: any) => "navigationEndpoint" in item)
|
||||||
|
.map((run: any) => ({
|
||||||
|
name: run.text,
|
||||||
|
artistId: traverse(run, "browseId")
|
||||||
|
})),
|
||||||
|
album: {
|
||||||
|
albumId: traverse(flexColumns[2], "browseId"),
|
||||||
|
name: traverse(flexColumns[2], "runs", "text")
|
||||||
|
},
|
||||||
|
duration: Parser.parseDuration(traverse(item, "fixedColumns", "runs", "text")),
|
||||||
|
thumbnails: [traverse(item, "thumbnails")].flat()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public static parseArtistTopSong(
|
||||||
|
item: any,
|
||||||
|
artistBasic: YTMusic.ArtistBasic
|
||||||
|
): Omit<YTMusic.SongDetailed, "duration"> {
|
||||||
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "SONG",
|
||||||
|
videoId: traverse(item, "playlistItemData", "videoId"),
|
||||||
|
name: traverse(flexColumns[0], "runs", "text"),
|
||||||
|
artists: [artistBasic],
|
||||||
|
album: {
|
||||||
|
albumId: traverse(flexColumns[2], "runs", "text"),
|
||||||
|
name: traverse(flexColumns[2], "browseId")
|
||||||
|
},
|
||||||
|
thumbnails: [traverse(item, "thumbnails")].flat()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import Parser from "./Parser"
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
|
|
||||||
export default class VideoParser {
|
export default class VideoParser {
|
||||||
public static parseSearch(item: any, specific: boolean): YTMusic.VideoDetailed {
|
public static parseSearchResult(item: any, specific: boolean): YTMusic.VideoDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const thumbnails = traverse(item, "thumbnails")
|
const thumbnails = traverse(item, "thumbnails")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import ObjectValidator from "validate-any/build/validators/ObjectValidator"
|
import ObjectValidator from "validate-any/build/validators/ObjectValidator"
|
||||||
import { LIST, NUMBER, OBJECT, OR, STRING, UNDEFINED } from "validate-any"
|
import { LIST, NULL, NUMBER, OBJECT, OR, STRING } from "validate-any"
|
||||||
|
|
||||||
export const THUMBNAIL_FULL: ObjectValidator<YTMusic.ThumbnailFull> = OBJECT({
|
export const THUMBNAIL_FULL: ObjectValidator<YTMusic.ThumbnailFull> = OBJECT({
|
||||||
url: STRING(),
|
url: STRING(),
|
||||||
|
|
@ -8,7 +8,7 @@ export const THUMBNAIL_FULL: ObjectValidator<YTMusic.ThumbnailFull> = OBJECT({
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ARTIST_BASIC: ObjectValidator<YTMusic.ArtistBasic> = OBJECT({
|
export const ARTIST_BASIC: ObjectValidator<YTMusic.ArtistBasic> = OBJECT({
|
||||||
artistId: OR(STRING(), UNDEFINED()),
|
artistId: OR(STRING(), NULL()),
|
||||||
name: STRING()
|
name: STRING()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -59,9 +59,9 @@ export const ARTIST_FULL: ObjectValidator<YTMusic.ArtistFull> = OBJECT({
|
||||||
name: STRING(),
|
name: STRING(),
|
||||||
type: STRING("ARTIST"),
|
type: STRING("ARTIST"),
|
||||||
thumbnails: LIST(THUMBNAIL_FULL),
|
thumbnails: LIST(THUMBNAIL_FULL),
|
||||||
description: STRING(),
|
description: OR(STRING(), NULL()),
|
||||||
subscribers: NUMBER(),
|
subscribers: NUMBER(),
|
||||||
topTracks: LIST(
|
topSongs: LIST(
|
||||||
OBJECT({
|
OBJECT({
|
||||||
type: STRING("SONG"),
|
type: STRING("SONG"),
|
||||||
videoId: STRING(),
|
videoId: STRING(),
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import YTMusic from "../YTMusic"
|
||||||
import {
|
import {
|
||||||
ALBUM_DETAILED,
|
ALBUM_DETAILED,
|
||||||
ARTIST_DETAILED,
|
ARTIST_DETAILED,
|
||||||
|
ARTIST_FULL,
|
||||||
PLAYLIST_DETAILED,
|
PLAYLIST_DETAILED,
|
||||||
SONG_DETAILED,
|
SONG_DETAILED,
|
||||||
VIDEO_DETAILED
|
VIDEO_DETAILED
|
||||||
|
|
@ -19,7 +20,13 @@ const tests: (query: string) => [() => Promise<any>, Validator<any>][] = query =
|
||||||
[
|
[
|
||||||
() => ytmusic.search(query),
|
() => ytmusic.search(query),
|
||||||
LIST(ALBUM_DETAILED, ARTIST_DETAILED, PLAYLIST_DETAILED, SONG_DETAILED, VIDEO_DETAILED)
|
LIST(ALBUM_DETAILED, ARTIST_DETAILED, PLAYLIST_DETAILED, SONG_DETAILED, VIDEO_DETAILED)
|
||||||
]
|
],
|
||||||
|
[() => ytmusic.getArtist("UCUCF7BJBzLcu_6qvgSBk7dA"), ARTIST_FULL],
|
||||||
|
[() => ytmusic.getArtist("UCTUR0sVEkD8T5MlSHqgaI_Q"), ARTIST_FULL],
|
||||||
|
[() => ytmusic.getArtistSongs("UCUCF7BJBzLcu_6qvgSBk7dA"), LIST(SONG_DETAILED)],
|
||||||
|
[() => ytmusic.getArtistSongs("UCTUR0sVEkD8T5MlSHqgaI_Q"), LIST(SONG_DETAILED)],
|
||||||
|
[() => ytmusic.getArtistAlbums("UCUCF7BJBzLcu_6qvgSBk7dA"), LIST(ALBUM_DETAILED)],
|
||||||
|
[() => ytmusic.getArtistAlbums("UCTUR0sVEkD8T5MlSHqgaI_Q"), LIST(ALBUM_DETAILED)]
|
||||||
]
|
]
|
||||||
|
|
||||||
const queries = ["Lilac", "Weekend", "Yours Raiden", "Eminem"]
|
const queries = ["Lilac", "Weekend", "Yours Raiden", "Eminem"]
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ declare namespace YTMusic {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ArtistBasic {
|
interface ArtistBasic {
|
||||||
artistId?: string
|
artistId: string | null
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,9 +37,9 @@ declare namespace YTMusic {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ArtistFull extends ArtistDetailed {
|
interface ArtistFull extends ArtistDetailed {
|
||||||
description: string
|
description: string | null
|
||||||
subscribers: number
|
subscribers: number
|
||||||
topTracks: Omit<SongDetailed, "duration">[]
|
topSongs: Omit<SongDetailed, "duration">[]
|
||||||
topAlbums: AlbumDetailed[]
|
topAlbums: AlbumDetailed[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue