Not exporting namespace anymore
This commit is contained in:
parent
5a458d5557
commit
08ea5a47b6
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "ytmusic-api",
|
"name": "ytmusic-api",
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"description": "YouTube Music API",
|
"description": "YouTube Music API",
|
||||||
"main": "build/index.js",
|
"main": "build/index.js",
|
||||||
"types": "build/index.d.ts",
|
"types": "build/index.d.ts",
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,21 @@ import SearchParser from "./parsers/SearchParser"
|
||||||
import SongParser from "./parsers/SongParser"
|
import SongParser from "./parsers/SongParser"
|
||||||
import traverse from "./utils/traverse"
|
import traverse from "./utils/traverse"
|
||||||
import VideoParser from "./parsers/VideoParser"
|
import VideoParser from "./parsers/VideoParser"
|
||||||
import YTMusic from "."
|
import {
|
||||||
|
AlbumDetailed,
|
||||||
|
AlbumFull,
|
||||||
|
ArtistDetailed,
|
||||||
|
ArtistFull,
|
||||||
|
PlaylistFull,
|
||||||
|
SearchResult,
|
||||||
|
SongDetailed,
|
||||||
|
SongFull,
|
||||||
|
VideoDetailed,
|
||||||
|
VideoFull
|
||||||
|
} from "."
|
||||||
import { Cookie, CookieJar } from "tough-cookie"
|
import { Cookie, CookieJar } from "tough-cookie"
|
||||||
|
|
||||||
export default class Api {
|
export default class YTMusic {
|
||||||
private cookiejar: CookieJar
|
private cookiejar: CookieJar
|
||||||
private config?: Record<string, string>
|
private config?: Record<string, string>
|
||||||
private client: AxiosInstance
|
private client: AxiosInstance
|
||||||
|
|
@ -206,12 +217,12 @@ export default class Api {
|
||||||
* @param query Query string
|
* @param query Query string
|
||||||
* @param category Type of search results to receive
|
* @param category Type of search results to receive
|
||||||
*/
|
*/
|
||||||
public async search(query: string, category: "SONG"): Promise<YTMusic.SongDetailed[]>
|
public async search(query: string, category: "SONG"): Promise<SongDetailed[]>
|
||||||
public async search(query: string, category: "VIDEO"): Promise<YTMusic.VideoDetailed[]>
|
public async search(query: string, category: "VIDEO"): Promise<VideoDetailed[]>
|
||||||
public async search(query: string, category: "ARTIST"): Promise<YTMusic.ArtistDetailed[]>
|
public async search(query: string, category: "ARTIST"): Promise<ArtistDetailed[]>
|
||||||
public async search(query: string, category: "ALBUM"): Promise<YTMusic.AlbumDetailed[]>
|
public async search(query: string, category: "ALBUM"): Promise<AlbumDetailed[]>
|
||||||
public async search(query: string, category: "PLAYLIST"): Promise<YTMusic.PlaylistFull[]>
|
public async search(query: string, category: "PLAYLIST"): Promise<PlaylistFull[]>
|
||||||
public async search(query: string): Promise<YTMusic.SearchResult[]>
|
public async search(query: string): Promise<SearchResult[]>
|
||||||
public async search(query: string, category?: string) {
|
public async search(query: string, category?: string) {
|
||||||
const searchData = await this.constructRequest("search", {
|
const searchData = await this.constructRequest("search", {
|
||||||
query,
|
query,
|
||||||
|
|
@ -242,7 +253,7 @@ export default class Api {
|
||||||
* @param videoId Video ID
|
* @param videoId Video ID
|
||||||
* @returns Song Data
|
* @returns Song Data
|
||||||
*/
|
*/
|
||||||
public async getSong(videoId: string): Promise<YTMusic.SongFull> {
|
public async getSong(videoId: string): Promise<SongFull> {
|
||||||
const data = await this.constructRequest("player", { videoId })
|
const data = await this.constructRequest("player", { videoId })
|
||||||
|
|
||||||
return SongParser.parse(data)
|
return SongParser.parse(data)
|
||||||
|
|
@ -254,7 +265,7 @@ export default class Api {
|
||||||
* @param videoId Video ID
|
* @param videoId Video ID
|
||||||
* @returns Video Data
|
* @returns Video Data
|
||||||
*/
|
*/
|
||||||
public async getVideo(videoId: string): Promise<YTMusic.VideoFull> {
|
public async getVideo(videoId: string): Promise<VideoFull> {
|
||||||
const data = await this.constructRequest("player", { videoId })
|
const data = await this.constructRequest("player", { videoId })
|
||||||
|
|
||||||
return VideoParser.parse(data)
|
return VideoParser.parse(data)
|
||||||
|
|
@ -266,7 +277,7 @@ export default class Api {
|
||||||
* @param artistId Artist ID
|
* @param artistId Artist ID
|
||||||
* @returns Artist Data
|
* @returns Artist Data
|
||||||
*/
|
*/
|
||||||
public async getArtist(artistId: string): Promise<YTMusic.ArtistFull> {
|
public async getArtist(artistId: string): Promise<ArtistFull> {
|
||||||
const data = await this.constructRequest("browse", { browseId: artistId })
|
const data = await this.constructRequest("browse", { browseId: artistId })
|
||||||
|
|
||||||
return ArtistParser.parse(data, artistId)
|
return ArtistParser.parse(data, artistId)
|
||||||
|
|
@ -278,7 +289,7 @@ export default class Api {
|
||||||
* @param artistId Artist ID
|
* @param artistId Artist ID
|
||||||
* @returns Artist's Songs
|
* @returns Artist's Songs
|
||||||
*/
|
*/
|
||||||
public async getArtistSongs(artistId: string): Promise<YTMusic.SongDetailed[]> {
|
public async getArtistSongs(artistId: string): Promise<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")
|
||||||
|
|
||||||
|
|
@ -302,7 +313,7 @@ export default class Api {
|
||||||
* @param artistId Artist ID
|
* @param artistId Artist ID
|
||||||
* @returns Artist's Albums
|
* @returns Artist's Albums
|
||||||
*/
|
*/
|
||||||
public async getArtistAlbums(artistId: string): Promise<YTMusic.AlbumDetailed[]> {
|
public async getArtistAlbums(artistId: string): Promise<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]
|
||||||
const browseBody = traverse(artistAlbumsData, "moreContentButton", "browseEndpoint")
|
const browseBody = traverse(artistAlbumsData, "moreContentButton", "browseEndpoint")
|
||||||
|
|
@ -323,7 +334,7 @@ export default class Api {
|
||||||
* @param albumId Album ID
|
* @param albumId Album ID
|
||||||
* @returns Album Data
|
* @returns Album Data
|
||||||
*/
|
*/
|
||||||
public async getAlbum(albumId: string): Promise<YTMusic.AlbumFull> {
|
public async getAlbum(albumId: string): Promise<AlbumFull> {
|
||||||
const data = await this.constructRequest("browse", { browseId: albumId })
|
const data = await this.constructRequest("browse", { browseId: albumId })
|
||||||
|
|
||||||
return AlbumParser.parse(data, albumId)
|
return AlbumParser.parse(data, albumId)
|
||||||
|
|
@ -335,7 +346,7 @@ export default class Api {
|
||||||
* @param playlistId Playlist ID
|
* @param playlistId Playlist ID
|
||||||
* @returns Playlist Data
|
* @returns Playlist Data
|
||||||
*/
|
*/
|
||||||
public async getPlaylist(playlistId: string): Promise<YTMusic.PlaylistFull> {
|
public async getPlaylist(playlistId: string): Promise<PlaylistFull> {
|
||||||
if (playlistId.startsWith("PL")) playlistId = "VL" + playlistId
|
if (playlistId.startsWith("PL")) playlistId = "VL" + playlistId
|
||||||
const data = await this.constructRequest("browse", { browseId: playlistId })
|
const data = await this.constructRequest("browse", { browseId: playlistId })
|
||||||
|
|
||||||
|
|
@ -348,9 +359,7 @@ export default class Api {
|
||||||
* @param playlistId Playlist ID
|
* @param playlistId Playlist ID
|
||||||
* @returns Playlist's Videos
|
* @returns Playlist's Videos
|
||||||
*/
|
*/
|
||||||
public async getPlaylistVideos(
|
public async getPlaylistVideos(playlistId: string): Promise<Omit<VideoDetailed, "views">[]> {
|
||||||
playlistId: string
|
|
||||||
): Promise<Omit<YTMusic.VideoDetailed, "views">[]> {
|
|
||||||
if (playlistId.startsWith("PL")) playlistId = "VL" + playlistId
|
if (playlistId.startsWith("PL")) playlistId = "VL" + playlistId
|
||||||
const playlistData = await this.constructRequest("browse", { browseId: playlistId })
|
const playlistData = await this.constructRequest("browse", { browseId: playlistId })
|
||||||
|
|
||||||
186
src/index.ts
186
src/index.ts
|
|
@ -1,99 +1,95 @@
|
||||||
import Api from "./Api"
|
import YTMusic from "./YTMusic"
|
||||||
|
|
||||||
declare namespace YTMusic {
|
export interface ThumbnailFull {
|
||||||
export { Api }
|
url: string
|
||||||
|
width: number
|
||||||
export interface ThumbnailFull {
|
height: number
|
||||||
url: string
|
|
||||||
width: number
|
|
||||||
height: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SongDetailed {
|
|
||||||
type: "SONG"
|
|
||||||
videoId: string | null
|
|
||||||
name: string
|
|
||||||
artists: ArtistBasic[]
|
|
||||||
album: AlbumBasic
|
|
||||||
duration: number
|
|
||||||
thumbnails: ThumbnailFull[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SongFull extends Omit<SongDetailed, "album"> {
|
|
||||||
description: string
|
|
||||||
formats: any[]
|
|
||||||
adaptiveFormats: any[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VideoDetailed {
|
|
||||||
type: "VIDEO"
|
|
||||||
videoId: string | null
|
|
||||||
name: string
|
|
||||||
artists: ArtistBasic[]
|
|
||||||
views: number
|
|
||||||
duration: number
|
|
||||||
thumbnails: ThumbnailFull[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VideoFull extends VideoDetailed {
|
|
||||||
description: string
|
|
||||||
unlisted: boolean
|
|
||||||
familySafe: boolean
|
|
||||||
paid: boolean
|
|
||||||
tags: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ArtistBasic {
|
|
||||||
artistId: string | null
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ArtistDetailed extends ArtistBasic {
|
|
||||||
type: "ARTIST"
|
|
||||||
artistId: string
|
|
||||||
thumbnails: ThumbnailFull[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ArtistFull extends ArtistDetailed {
|
|
||||||
description: string | null
|
|
||||||
subscribers: number
|
|
||||||
topSongs: Omit<SongDetailed, "duration">[]
|
|
||||||
topAlbums: AlbumDetailed[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AlbumBasic {
|
|
||||||
albumId: string
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AlbumDetailed extends AlbumBasic {
|
|
||||||
type: "ALBUM"
|
|
||||||
playlistId: string
|
|
||||||
artists: ArtistBasic[]
|
|
||||||
year: number
|
|
||||||
thumbnails: ThumbnailFull[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AlbumFull extends AlbumDetailed {
|
|
||||||
description: string | null
|
|
||||||
songs: SongDetailed[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PlaylistFull {
|
|
||||||
type: "PLAYLIST"
|
|
||||||
playlistId: string
|
|
||||||
name: string
|
|
||||||
artist: ArtistBasic
|
|
||||||
videoCount: number
|
|
||||||
thumbnails: ThumbnailFull[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SearchResult =
|
|
||||||
| SongDetailed
|
|
||||||
| VideoDetailed
|
|
||||||
| AlbumDetailed
|
|
||||||
| ArtistDetailed
|
|
||||||
| PlaylistFull
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SongDetailed {
|
||||||
|
type: "SONG"
|
||||||
|
videoId: string | null
|
||||||
|
name: string
|
||||||
|
artists: ArtistBasic[]
|
||||||
|
album: AlbumBasic
|
||||||
|
duration: number
|
||||||
|
thumbnails: ThumbnailFull[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SongFull extends Omit<SongDetailed, "album"> {
|
||||||
|
description: string
|
||||||
|
formats: any[]
|
||||||
|
adaptiveFormats: any[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VideoDetailed {
|
||||||
|
type: "VIDEO"
|
||||||
|
videoId: string | null
|
||||||
|
name: string
|
||||||
|
artists: ArtistBasic[]
|
||||||
|
views: number
|
||||||
|
duration: number
|
||||||
|
thumbnails: ThumbnailFull[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VideoFull extends VideoDetailed {
|
||||||
|
description: string
|
||||||
|
unlisted: boolean
|
||||||
|
familySafe: boolean
|
||||||
|
paid: boolean
|
||||||
|
tags: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArtistBasic {
|
||||||
|
artistId: string | null
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArtistDetailed extends ArtistBasic {
|
||||||
|
type: "ARTIST"
|
||||||
|
artistId: string
|
||||||
|
thumbnails: ThumbnailFull[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArtistFull extends ArtistDetailed {
|
||||||
|
description: string | null
|
||||||
|
subscribers: number
|
||||||
|
topSongs: Omit<SongDetailed, "duration">[]
|
||||||
|
topAlbums: AlbumDetailed[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlbumBasic {
|
||||||
|
albumId: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlbumDetailed extends AlbumBasic {
|
||||||
|
type: "ALBUM"
|
||||||
|
playlistId: string
|
||||||
|
artists: ArtistBasic[]
|
||||||
|
year: number
|
||||||
|
thumbnails: ThumbnailFull[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlbumFull extends AlbumDetailed {
|
||||||
|
description: string | null
|
||||||
|
songs: SongDetailed[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PlaylistFull {
|
||||||
|
type: "PLAYLIST"
|
||||||
|
playlistId: string
|
||||||
|
name: string
|
||||||
|
artist: ArtistBasic
|
||||||
|
videoCount: number
|
||||||
|
thumbnails: ThumbnailFull[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SearchResult =
|
||||||
|
| SongDetailed
|
||||||
|
| VideoDetailed
|
||||||
|
| AlbumDetailed
|
||||||
|
| ArtistDetailed
|
||||||
|
| PlaylistFull
|
||||||
|
|
||||||
export default YTMusic
|
export default YTMusic
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import SongParser from "./SongParser"
|
import SongParser from "./SongParser"
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
import YTMusic from ".."
|
import { AlbumDetailed, AlbumFull, ArtistBasic } from ".."
|
||||||
|
|
||||||
export default class AlbumParser {
|
export default class AlbumParser {
|
||||||
public static parse(data: any, albumId: string): YTMusic.AlbumFull {
|
public static parse(data: any, albumId: string): AlbumFull {
|
||||||
const albumBasic = {
|
const albumBasic = {
|
||||||
albumId,
|
albumId,
|
||||||
name: traverse(data, "header", "title", "text").at(0)
|
name: traverse(data, "header", "title", "text").at(0)
|
||||||
|
|
@ -30,7 +30,7 @@ export default class AlbumParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseSearchResult(item: any): YTMusic.AlbumDetailed {
|
public static parseSearchResult(item: any): AlbumDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -46,10 +46,7 @@ export default class AlbumParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseArtistAlbum(
|
public static parseArtistAlbum(item: any, artistBasic: ArtistBasic): AlbumDetailed {
|
||||||
item: any,
|
|
||||||
artistBasic: YTMusic.ArtistBasic
|
|
||||||
): YTMusic.AlbumDetailed {
|
|
||||||
return {
|
return {
|
||||||
type: "ALBUM",
|
type: "ALBUM",
|
||||||
albumId: [traverse(item, "browseId")].flat().at(-1),
|
albumId: [traverse(item, "browseId")].flat().at(-1),
|
||||||
|
|
@ -61,10 +58,7 @@ export default class AlbumParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseArtistTopAlbums(
|
public static parseArtistTopAlbums(item: any, artistBasic: ArtistBasic): AlbumDetailed {
|
||||||
item: any,
|
|
||||||
artistBasic: YTMusic.ArtistBasic
|
|
||||||
): YTMusic.AlbumDetailed {
|
|
||||||
return {
|
return {
|
||||||
type: "ALBUM",
|
type: "ALBUM",
|
||||||
albumId: traverse(item, "browseId").at(-1),
|
albumId: traverse(item, "browseId").at(-1),
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ import AlbumParser from "./AlbumParser"
|
||||||
import Parser from "./Parser"
|
import Parser from "./Parser"
|
||||||
import SongParser from "./SongParser"
|
import SongParser from "./SongParser"
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
import YTMusic from ".."
|
import { ArtistDetailed, ArtistFull } from ".."
|
||||||
|
|
||||||
export default class ArtistParser {
|
export default class ArtistParser {
|
||||||
public static parse(data: any, artistId: string): YTMusic.ArtistFull {
|
public static parse(data: any, artistId: string): ArtistFull {
|
||||||
const artistBasic = {
|
const artistBasic = {
|
||||||
artistId,
|
artistId,
|
||||||
name: traverse(data, "header", "title", "text").at(0)
|
name: traverse(data, "header", "title", "text").at(0)
|
||||||
|
|
@ -29,7 +29,7 @@ export default class ArtistParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseSearchResult(item: any): YTMusic.ArtistDetailed {
|
public static parseSearchResult(item: any): ArtistDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
import YTMusic from ".."
|
import { PlaylistFull } from ".."
|
||||||
|
|
||||||
export default class PlaylistParser {
|
export default class PlaylistParser {
|
||||||
public static parse(data: any, playlistId: string): YTMusic.PlaylistFull {
|
public static parse(data: any, playlistId: string): PlaylistFull {
|
||||||
return {
|
return {
|
||||||
type: "PLAYLIST",
|
type: "PLAYLIST",
|
||||||
playlistId,
|
playlistId,
|
||||||
|
|
@ -20,7 +20,7 @@ export default class PlaylistParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseSearchResult(item: any): YTMusic.PlaylistFull {
|
public static parseSearchResult(item: any): PlaylistFull {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const artistId = traverse(flexColumns[1], "browseId")
|
const artistId = traverse(flexColumns[1], "browseId")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ import PlaylistParser from "./PlaylistParser"
|
||||||
import SongParser from "./SongParser"
|
import SongParser from "./SongParser"
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
import VideoParser from "./VideoParser"
|
import VideoParser from "./VideoParser"
|
||||||
import YTMusic from ".."
|
import { SearchResult } from ".."
|
||||||
|
|
||||||
export default class SearchParser {
|
export default class SearchParser {
|
||||||
public static parse(item: any): YTMusic.SearchResult {
|
public static parse(item: any): SearchResult {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const type = traverse(flexColumns[1], "runs", "text").at(0) as
|
const type = traverse(flexColumns[1], "runs", "text").at(0) as
|
||||||
| "Song"
|
| "Song"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import Parser from "./Parser"
|
import Parser from "./Parser"
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
import YTMusic from ".."
|
import { AlbumBasic, ArtistBasic, SongDetailed, SongFull, ThumbnailFull } from ".."
|
||||||
|
|
||||||
export default class SongParser {
|
export default class SongParser {
|
||||||
public static parse(data: any): YTMusic.SongFull {
|
public static parse(data: any): SongFull {
|
||||||
return {
|
return {
|
||||||
type: "SONG",
|
type: "SONG",
|
||||||
videoId: traverse(data, "videoDetails", "videoId"),
|
videoId: traverse(data, "videoDetails", "videoId"),
|
||||||
|
|
@ -22,7 +22,7 @@ export default class SongParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseSearchResult(item: any): YTMusic.SongDetailed {
|
public static parseSearchResult(item: any): SongDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const videoId = traverse(item, "playlistItemData", "videoId")
|
const videoId = traverse(item, "playlistItemData", "videoId")
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ export default class SongParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseArtistSong(item: any): YTMusic.SongDetailed {
|
public static parseArtistSong(item: any): SongDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const videoId = traverse(item, "playlistItemData", "videoId")
|
const videoId = traverse(item, "playlistItemData", "videoId")
|
||||||
|
|
||||||
|
|
@ -69,8 +69,8 @@ export default class SongParser {
|
||||||
|
|
||||||
public static parseArtistTopSong(
|
public static parseArtistTopSong(
|
||||||
item: any,
|
item: any,
|
||||||
artistBasic: YTMusic.ArtistBasic
|
artistBasic: ArtistBasic
|
||||||
): Omit<YTMusic.SongDetailed, "duration"> {
|
): Omit<SongDetailed, "duration"> {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const videoId = traverse(item, "playlistItemData", "videoId")
|
const videoId = traverse(item, "playlistItemData", "videoId")
|
||||||
|
|
||||||
|
|
@ -89,10 +89,10 @@ export default class SongParser {
|
||||||
|
|
||||||
public static parseAlbumSong(
|
public static parseAlbumSong(
|
||||||
item: any,
|
item: any,
|
||||||
artists: YTMusic.ArtistBasic[],
|
artists: ArtistBasic[],
|
||||||
albumBasic: YTMusic.AlbumBasic,
|
albumBasic: AlbumBasic,
|
||||||
thumbnails: YTMusic.ThumbnailFull[]
|
thumbnails: ThumbnailFull[]
|
||||||
): YTMusic.SongDetailed {
|
): SongDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const videoId = traverse(item, "playlistItemData", "videoId")
|
const videoId = traverse(item, "playlistItemData", "videoId")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import Parser from "./Parser"
|
import Parser from "./Parser"
|
||||||
import traverse from "../utils/traverse"
|
import traverse from "../utils/traverse"
|
||||||
import YTMusic from ".."
|
import { VideoDetailed, VideoFull } from ".."
|
||||||
|
|
||||||
export default class VideoParser {
|
export default class VideoParser {
|
||||||
public static parse(data: any): YTMusic.VideoFull {
|
public static parse(data: any): VideoFull {
|
||||||
return {
|
return {
|
||||||
type: "VIDEO",
|
type: "VIDEO",
|
||||||
videoId: traverse(data, "videoDetails", "videoId"),
|
videoId: traverse(data, "videoDetails", "videoId"),
|
||||||
|
|
@ -25,7 +25,7 @@ export default class VideoParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parseSearchResult(item: any): YTMusic.VideoDetailed {
|
public static parseSearchResult(item: any): VideoDetailed {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const videoId = traverse(item, "playNavigationEndpoint", "videoId")
|
const videoId = traverse(item, "playNavigationEndpoint", "videoId")
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ export default class VideoParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static parsePlaylistVideo(item: any): Omit<YTMusic.VideoDetailed, "views"> {
|
public static parsePlaylistVideo(item: any): Omit<VideoDetailed, "views"> {
|
||||||
const flexColumns = traverse(item, "flexColumns")
|
const flexColumns = traverse(item, "flexColumns")
|
||||||
const videoId = traverse(item, "playNavigationEndpoint", "videoId")
|
const videoId = traverse(item, "playNavigationEndpoint", "videoId")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import Validator from "validate-any/build/classes/Validator"
|
import Validator from "validate-any/build/classes/Validator"
|
||||||
import YTMusicApi from "../Api"
|
import YTMusic from "../YTMusic"
|
||||||
import {
|
import {
|
||||||
ALBUM_DETAILED,
|
ALBUM_DETAILED,
|
||||||
ALBUM_FULL,
|
ALBUM_FULL,
|
||||||
|
|
@ -15,7 +15,7 @@ import {
|
||||||
import { LIST, validate } from "validate-any"
|
import { LIST, validate } from "validate-any"
|
||||||
|
|
||||||
const queries = ["Lilac", "Weekend", "Yours Raiden", "Eminem", "Lisa Hannigan"]
|
const queries = ["Lilac", "Weekend", "Yours Raiden", "Eminem", "Lisa Hannigan"]
|
||||||
const ytmusic = new YTMusicApi()
|
const ytmusic = new YTMusic()
|
||||||
|
|
||||||
ytmusic.initialize().then(() =>
|
ytmusic.initialize().then(() =>
|
||||||
queries.forEach(async query => {
|
queries.forEach(async query => {
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,37 @@
|
||||||
import ObjectValidator from "validate-any/build/validators/ObjectValidator"
|
import ObjectValidator from "validate-any/build/validators/ObjectValidator"
|
||||||
import YTMusic from "../index"
|
import {
|
||||||
|
AlbumBasic,
|
||||||
|
AlbumDetailed,
|
||||||
|
AlbumFull,
|
||||||
|
ArtistBasic,
|
||||||
|
ArtistDetailed,
|
||||||
|
ArtistFull,
|
||||||
|
PlaylistFull,
|
||||||
|
SongDetailed,
|
||||||
|
SongFull,
|
||||||
|
ThumbnailFull,
|
||||||
|
VideoDetailed,
|
||||||
|
VideoFull
|
||||||
|
} from "../index"
|
||||||
import { BOOLEAN, LIST, NULL, NUMBER, OBJECT, OR, STRING } from "validate-any"
|
import { BOOLEAN, LIST, NULL, NUMBER, OBJECT, OR, STRING } from "validate-any"
|
||||||
|
|
||||||
export const THUMBNAIL_FULL: ObjectValidator<YTMusic.ThumbnailFull> = OBJECT({
|
export const THUMBNAIL_FULL: ObjectValidator<ThumbnailFull> = OBJECT({
|
||||||
url: STRING(),
|
url: STRING(),
|
||||||
width: NUMBER(),
|
width: NUMBER(),
|
||||||
height: NUMBER()
|
height: NUMBER()
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ARTIST_BASIC: ObjectValidator<YTMusic.ArtistBasic> = OBJECT({
|
export const ARTIST_BASIC: ObjectValidator<ArtistBasic> = OBJECT({
|
||||||
artistId: OR(STRING(), NULL()),
|
artistId: OR(STRING(), NULL()),
|
||||||
name: STRING()
|
name: STRING()
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ALBUM_BASIC: ObjectValidator<YTMusic.AlbumBasic> = OBJECT({
|
export const ALBUM_BASIC: ObjectValidator<AlbumBasic> = OBJECT({
|
||||||
albumId: STRING(),
|
albumId: STRING(),
|
||||||
name: STRING()
|
name: STRING()
|
||||||
})
|
})
|
||||||
|
|
||||||
export const SONG_DETAILED: ObjectValidator<YTMusic.SongDetailed> = OBJECT({
|
export const SONG_DETAILED: ObjectValidator<SongDetailed> = OBJECT({
|
||||||
type: STRING("SONG"),
|
type: STRING("SONG"),
|
||||||
videoId: OR(STRING(), NULL()),
|
videoId: OR(STRING(), NULL()),
|
||||||
name: STRING(),
|
name: STRING(),
|
||||||
|
|
@ -28,7 +41,7 @@ export const SONG_DETAILED: ObjectValidator<YTMusic.SongDetailed> = OBJECT({
|
||||||
thumbnails: LIST(THUMBNAIL_FULL)
|
thumbnails: LIST(THUMBNAIL_FULL)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const VIDEO_DETAILED: ObjectValidator<YTMusic.VideoDetailed> = OBJECT({
|
export const VIDEO_DETAILED: ObjectValidator<VideoDetailed> = OBJECT({
|
||||||
type: STRING("VIDEO"),
|
type: STRING("VIDEO"),
|
||||||
videoId: OR(STRING(), NULL()),
|
videoId: OR(STRING(), NULL()),
|
||||||
name: STRING(),
|
name: STRING(),
|
||||||
|
|
@ -38,14 +51,14 @@ export const VIDEO_DETAILED: ObjectValidator<YTMusic.VideoDetailed> = OBJECT({
|
||||||
thumbnails: LIST(THUMBNAIL_FULL)
|
thumbnails: LIST(THUMBNAIL_FULL)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ARTIST_DETAILED: ObjectValidator<YTMusic.ArtistDetailed> = OBJECT({
|
export const ARTIST_DETAILED: ObjectValidator<ArtistDetailed> = OBJECT({
|
||||||
artistId: STRING(),
|
artistId: STRING(),
|
||||||
name: STRING(),
|
name: STRING(),
|
||||||
type: STRING("ARTIST"),
|
type: STRING("ARTIST"),
|
||||||
thumbnails: LIST(THUMBNAIL_FULL)
|
thumbnails: LIST(THUMBNAIL_FULL)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ALBUM_DETAILED: ObjectValidator<YTMusic.AlbumDetailed> = OBJECT({
|
export const ALBUM_DETAILED: ObjectValidator<AlbumDetailed> = OBJECT({
|
||||||
type: STRING("ALBUM"),
|
type: STRING("ALBUM"),
|
||||||
albumId: STRING(),
|
albumId: STRING(),
|
||||||
playlistId: STRING(),
|
playlistId: STRING(),
|
||||||
|
|
@ -55,7 +68,7 @@ export const ALBUM_DETAILED: ObjectValidator<YTMusic.AlbumDetailed> = OBJECT({
|
||||||
thumbnails: LIST(THUMBNAIL_FULL)
|
thumbnails: LIST(THUMBNAIL_FULL)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const SONG_FULL: ObjectValidator<YTMusic.SongFull> = OBJECT({
|
export const SONG_FULL: ObjectValidator<SongFull> = OBJECT({
|
||||||
type: STRING("SONG"),
|
type: STRING("SONG"),
|
||||||
videoId: OR(STRING(), NULL()),
|
videoId: OR(STRING(), NULL()),
|
||||||
name: STRING(),
|
name: STRING(),
|
||||||
|
|
@ -67,7 +80,7 @@ export const SONG_FULL: ObjectValidator<YTMusic.SongFull> = OBJECT({
|
||||||
adaptiveFormats: LIST(OBJECT())
|
adaptiveFormats: LIST(OBJECT())
|
||||||
})
|
})
|
||||||
|
|
||||||
export const VIDEO_FULL: ObjectValidator<YTMusic.VideoFull> = OBJECT({
|
export const VIDEO_FULL: ObjectValidator<VideoFull> = OBJECT({
|
||||||
type: STRING("VIDEO"),
|
type: STRING("VIDEO"),
|
||||||
videoId: OR(STRING(), NULL()),
|
videoId: OR(STRING(), NULL()),
|
||||||
name: STRING(),
|
name: STRING(),
|
||||||
|
|
@ -82,7 +95,7 @@ export const VIDEO_FULL: ObjectValidator<YTMusic.VideoFull> = OBJECT({
|
||||||
tags: LIST(STRING())
|
tags: LIST(STRING())
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ARTIST_FULL: ObjectValidator<YTMusic.ArtistFull> = OBJECT({
|
export const ARTIST_FULL: ObjectValidator<ArtistFull> = OBJECT({
|
||||||
artistId: STRING(),
|
artistId: STRING(),
|
||||||
name: STRING(),
|
name: STRING(),
|
||||||
type: STRING("ARTIST"),
|
type: STRING("ARTIST"),
|
||||||
|
|
@ -102,7 +115,7 @@ export const ARTIST_FULL: ObjectValidator<YTMusic.ArtistFull> = OBJECT({
|
||||||
topAlbums: LIST(ALBUM_DETAILED)
|
topAlbums: LIST(ALBUM_DETAILED)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const ALBUM_FULL: ObjectValidator<YTMusic.AlbumFull> = OBJECT({
|
export const ALBUM_FULL: ObjectValidator<AlbumFull> = OBJECT({
|
||||||
type: STRING("ALBUM"),
|
type: STRING("ALBUM"),
|
||||||
albumId: STRING(),
|
albumId: STRING(),
|
||||||
playlistId: STRING(),
|
playlistId: STRING(),
|
||||||
|
|
@ -114,7 +127,7 @@ export const ALBUM_FULL: ObjectValidator<YTMusic.AlbumFull> = OBJECT({
|
||||||
songs: LIST(SONG_DETAILED)
|
songs: LIST(SONG_DETAILED)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const PLAYLIST_DETAILED: ObjectValidator<YTMusic.PlaylistFull> = OBJECT({
|
export const PLAYLIST_DETAILED: ObjectValidator<PlaylistFull> = OBJECT({
|
||||||
type: STRING("PLAYLIST"),
|
type: STRING("PLAYLIST"),
|
||||||
playlistId: STRING(),
|
playlistId: STRING(),
|
||||||
name: STRING(),
|
name: STRING(),
|
||||||
|
|
@ -123,7 +136,7 @@ export const PLAYLIST_DETAILED: ObjectValidator<YTMusic.PlaylistFull> = OBJECT({
|
||||||
thumbnails: LIST(THUMBNAIL_FULL)
|
thumbnails: LIST(THUMBNAIL_FULL)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const PLAYLIST_VIDEO: ObjectValidator<Omit<YTMusic.VideoDetailed, "views">> = OBJECT({
|
export const PLAYLIST_VIDEO: ObjectValidator<Omit<VideoDetailed, "views">> = OBJECT({
|
||||||
type: STRING("VIDEO"),
|
type: STRING("VIDEO"),
|
||||||
videoId: OR(STRING(), NULL()),
|
videoId: OR(STRING(), NULL()),
|
||||||
name: STRING(),
|
name: STRING(),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import YTMusicApi from "../Api"
|
import YTMusic from "../YTMusic"
|
||||||
|
|
||||||
const ytmusic = new YTMusicApi()
|
const ytmusic = new YTMusic()
|
||||||
ytmusic.initialize().then(() => {
|
ytmusic.initialize().then(() => {
|
||||||
ytmusic.search("Lilac", "SONG").then(res => {
|
ytmusic.search("Lilac", "SONG").then(res => {
|
||||||
ytmusic.getSong(res.find(r => !!r.videoId)!.videoId!).then(res => {
|
ytmusic.getSong(res.find(r => !!r.videoId)!.videoId!).then(res => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue