Song and Video data fetching works
This commit is contained in:
parent
7471f1e70c
commit
9479811d4c
|
|
@ -1,7 +1,6 @@
|
|||
import AlbumParser from "./parsers/AlbumParser"
|
||||
import ArtistParser from "./parsers/ArtistParser"
|
||||
import axios, { AxiosInstance } from "axios"
|
||||
import fs from "fs"
|
||||
import PlaylistParser from "./parsers/PlaylistParser"
|
||||
import SearchParser from "./parsers/SearchParser"
|
||||
import SongParser from "./parsers/SongParser"
|
||||
|
|
@ -237,16 +236,28 @@ export default class YTMusic {
|
|||
)
|
||||
}
|
||||
|
||||
public async getSong(videoId: string) {
|
||||
/**
|
||||
* Get all possible information of a Song
|
||||
*
|
||||
* @param videoId Video ID
|
||||
* @returns Song Data
|
||||
*/
|
||||
public async getSong(videoId: string): Promise<YTMusic.SongFull> {
|
||||
const data = await this.constructRequest("player", { videoId })
|
||||
|
||||
fs.writeFileSync("data.json", JSON.stringify(data))
|
||||
return SongParser.parse(data)
|
||||
}
|
||||
|
||||
public async getVideo(videoId: string) {
|
||||
/**
|
||||
* Get all possible information of a Video
|
||||
*
|
||||
* @param videoId Video ID
|
||||
* @returns Video Data
|
||||
*/
|
||||
public async getVideo(videoId: string): Promise<YTMusic.VideoFull> {
|
||||
const data = await this.constructRequest("player", { videoId })
|
||||
|
||||
fs.writeFileSync("data.json", JSON.stringify(data))
|
||||
return VideoParser.parse(data)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
10
src/index.ts
10
src/index.ts
|
|
@ -1,10 +0,0 @@
|
|||
import YTMusic from "./YTMusic"
|
||||
|
||||
const ytmusic = new YTMusic()
|
||||
ytmusic.initialize().then(() => {
|
||||
ytmusic.search("Lilac", "PLAYLIST").then(res => {
|
||||
ytmusic.getPlaylist(res[0].playlistId).then(res => {
|
||||
console.log(res)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -2,6 +2,25 @@ import Parser from "./Parser"
|
|||
import traverse from "../utils/traverse"
|
||||
|
||||
export default class SongParser {
|
||||
public static parse(data: any): YTMusic.SongFull {
|
||||
return {
|
||||
type: "SONG",
|
||||
videoId: traverse(data, "videoDetails", "videoId"),
|
||||
name: traverse(data, "videoDetails", "title"),
|
||||
artists: [
|
||||
{
|
||||
artistId: traverse(data, "videoDetails", "channelId"),
|
||||
name: traverse(data, "author")
|
||||
}
|
||||
],
|
||||
duration: +traverse(data, "videoDetails", "lengthSeconds"),
|
||||
thumbnails: [traverse(data, "videoDetails", "thumbnails")].flat(),
|
||||
description: traverse(data, "description"),
|
||||
formats: traverse(data, "streamingData", "formats"),
|
||||
adaptiveFormats: traverse(data, "streamingData", "adaptiveFormats")
|
||||
}
|
||||
}
|
||||
|
||||
public static parseSearchResult(item: any): YTMusic.SongDetailed {
|
||||
const flexColumns = traverse(item, "flexColumns")
|
||||
const videoId = traverse(item, "playlistItemData", "videoId")
|
||||
|
|
|
|||
|
|
@ -2,6 +2,28 @@ import Parser from "./Parser"
|
|||
import traverse from "../utils/traverse"
|
||||
|
||||
export default class VideoParser {
|
||||
public static parse(data: any): YTMusic.VideoFull {
|
||||
return {
|
||||
type: "VIDEO",
|
||||
videoId: traverse(data, "videoDetails", "videoId"),
|
||||
name: traverse(data, "videoDetails", "title"),
|
||||
artists: [
|
||||
{
|
||||
artistId: traverse(data, "videoDetails", "channelId"),
|
||||
name: traverse(data, "author")
|
||||
}
|
||||
],
|
||||
views: +traverse(data, "videoDetails", "viewCount"),
|
||||
duration: +traverse(data, "videoDetails", "lengthSeconds"),
|
||||
thumbnails: [traverse(data, "videoDetails", "thumbnails")].flat(),
|
||||
description: traverse(data, "description"),
|
||||
unlisted: traverse(data, "unlisted"),
|
||||
familySafe: traverse(data, "familySafe"),
|
||||
paid: traverse(data, "paid"),
|
||||
tags: traverse(data, "tags")
|
||||
}
|
||||
}
|
||||
|
||||
public static parseSearchResult(item: any): YTMusic.VideoDetailed {
|
||||
const flexColumns = traverse(item, "flexColumns")
|
||||
const videoId = traverse(item, "playNavigationEndpoint", "videoId")
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ import {
|
|||
PLAYLIST_DETAILED,
|
||||
PLAYLIST_VIDEO,
|
||||
SONG_DETAILED,
|
||||
VIDEO_DETAILED
|
||||
SONG_FULL,
|
||||
VIDEO_DETAILED,
|
||||
VIDEO_FULL
|
||||
} from "./interfaces"
|
||||
import { LIST, validate } from "validate-any"
|
||||
|
||||
|
|
@ -26,10 +28,10 @@ ytmusic.initialize().then(() =>
|
|||
ytmusic.search(query)
|
||||
])
|
||||
|
||||
const [artist, artistSongs, artistAlbums, album, playlist, playlistVideos] =
|
||||
const [song, video, artist, artistSongs, artistAlbums, album, playlist, playlistVideos] =
|
||||
await Promise.all([
|
||||
// ytmusic.getSong(songs[0].videoId),
|
||||
// ytmusic.getVideo(videos[0].videoId),
|
||||
ytmusic.getSong(songs[0].videoId!),
|
||||
ytmusic.getVideo(videos[0].videoId!),
|
||||
ytmusic.getArtist(artists[0].artistId),
|
||||
ytmusic.getArtistSongs(artists[0].artistId),
|
||||
ytmusic.getArtistAlbums(artists[0].artistId),
|
||||
|
|
@ -54,8 +56,8 @@ ytmusic.initialize().then(() =>
|
|||
VIDEO_DETAILED
|
||||
)
|
||||
],
|
||||
// [song, SONG_DETAILED],
|
||||
// [video, VIDEO_DETAILED],
|
||||
[song, SONG_FULL],
|
||||
[video, VIDEO_FULL],
|
||||
[artist, ARTIST_FULL],
|
||||
[artistSongs, LIST(SONG_DETAILED)],
|
||||
[artistAlbums, LIST(ALBUM_DETAILED)],
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import ObjectValidator from "validate-any/build/validators/ObjectValidator"
|
||||
import { 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({
|
||||
url: STRING(),
|
||||
|
|
@ -54,6 +54,33 @@ export const ALBUM_DETAILED: ObjectValidator<YTMusic.AlbumDetailed> = OBJECT({
|
|||
thumbnails: LIST(THUMBNAIL_FULL)
|
||||
})
|
||||
|
||||
export const SONG_FULL: ObjectValidator<YTMusic.SongFull> = OBJECT({
|
||||
type: STRING("SONG"),
|
||||
videoId: OR(STRING(), NULL()),
|
||||
name: STRING(),
|
||||
artists: LIST(ARTIST_BASIC),
|
||||
duration: NUMBER(),
|
||||
thumbnails: LIST(THUMBNAIL_FULL),
|
||||
description: STRING(),
|
||||
formats: LIST(OBJECT()),
|
||||
adaptiveFormats: LIST(OBJECT())
|
||||
})
|
||||
|
||||
export const VIDEO_FULL: ObjectValidator<YTMusic.VideoFull> = OBJECT({
|
||||
type: STRING("VIDEO"),
|
||||
videoId: OR(STRING(), NULL()),
|
||||
name: STRING(),
|
||||
artists: LIST(ARTIST_BASIC),
|
||||
views: NUMBER(),
|
||||
duration: NUMBER(),
|
||||
thumbnails: LIST(THUMBNAIL_FULL),
|
||||
description: STRING(),
|
||||
unlisted: BOOLEAN(),
|
||||
familySafe: BOOLEAN(),
|
||||
paid: BOOLEAN(),
|
||||
tags: LIST(STRING())
|
||||
})
|
||||
|
||||
export const ARTIST_FULL: ObjectValidator<YTMusic.ArtistFull> = OBJECT({
|
||||
artistId: STRING(),
|
||||
name: STRING(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
import YTMusic from "../YTMusic"
|
||||
|
||||
const ytmusic = new YTMusic()
|
||||
ytmusic.initialize().then(() => {
|
||||
ytmusic.search("Lilac", "SONG").then(res => {
|
||||
ytmusic.getSong(res.find(r => !!r.videoId)!.videoId!).then(res => {
|
||||
console.log(res)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -15,6 +15,12 @@ declare namespace YTMusic {
|
|||
thumbnails: ThumbnailFull[]
|
||||
}
|
||||
|
||||
interface SongFull extends Omit<SongDetailed, "album"> {
|
||||
description: string
|
||||
formats: any[]
|
||||
adaptiveFormats: any[]
|
||||
}
|
||||
|
||||
interface VideoDetailed {
|
||||
type: "VIDEO"
|
||||
videoId: string | null
|
||||
|
|
@ -25,6 +31,14 @@ declare namespace YTMusic {
|
|||
thumbnails: ThumbnailFull[]
|
||||
}
|
||||
|
||||
interface VideoFull extends VideoDetailed {
|
||||
description: string
|
||||
unlisted: boolean
|
||||
familySafe: boolean
|
||||
paid: boolean
|
||||
tags: string[]
|
||||
}
|
||||
|
||||
interface ArtistBasic {
|
||||
artistId: string | null
|
||||
name: string
|
||||
|
|
|
|||
Loading…
Reference in New Issue