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 AlbumParser from "./parsers/AlbumParser" | ||||||
| import ArtistParser from "./parsers/ArtistParser" | import ArtistParser from "./parsers/ArtistParser" | ||||||
| import axios, { AxiosInstance } from "axios" | import axios, { AxiosInstance } from "axios" | ||||||
| import fs from "fs" |  | ||||||
| import PlaylistParser from "./parsers/PlaylistParser" | import PlaylistParser from "./parsers/PlaylistParser" | ||||||
| import SearchParser from "./parsers/SearchParser" | import SearchParser from "./parsers/SearchParser" | ||||||
| import SongParser from "./parsers/SongParser" | 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 }) | 		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 }) | 		const data = await this.constructRequest("player", { videoId }) | ||||||
| 
 | 
 | ||||||
| 		fs.writeFileSync("data.json", JSON.stringify(data)) | 		return VideoParser.parse(data) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -320,7 +331,7 @@ export default class YTMusic { | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get all possible information of a Playlist except the tracks | 	 * Get all possible information of a Playlist except the tracks | ||||||
| 	 *  | 	 * | ||||||
| 	 * @param playlistId Playlist ID | 	 * @param playlistId Playlist ID | ||||||
| 	 * @returns Playlist Data | 	 * @returns Playlist Data | ||||||
| 	 */ | 	 */ | ||||||
|  | @ -333,7 +344,7 @@ export default class YTMusic { | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Get all videos in a Playlist | 	 * Get all videos in a Playlist | ||||||
| 	 *  | 	 * | ||||||
| 	 * @param playlistId Playlist ID | 	 * @param playlistId Playlist ID | ||||||
| 	 * @returns Playlist's Videos | 	 * @returns Playlist's Videos | ||||||
| 	 */ | 	 */ | ||||||
|  |  | ||||||
							
								
								
									
										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" | import traverse from "../utils/traverse" | ||||||
| 
 | 
 | ||||||
| export default class SongParser { | 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 { | 	public static parseSearchResult(item: any): YTMusic.SongDetailed { | ||||||
| 		const flexColumns = traverse(item, "flexColumns") | 		const flexColumns = traverse(item, "flexColumns") | ||||||
| 		const videoId = traverse(item, "playlistItemData", "videoId") | 		const videoId = traverse(item, "playlistItemData", "videoId") | ||||||
|  |  | ||||||
|  | @ -2,6 +2,28 @@ import Parser from "./Parser" | ||||||
| import traverse from "../utils/traverse" | import traverse from "../utils/traverse" | ||||||
| 
 | 
 | ||||||
| export default class VideoParser { | 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 { | 	public static parseSearchResult(item: any): YTMusic.VideoDetailed { | ||||||
| 		const flexColumns = traverse(item, "flexColumns") | 		const flexColumns = traverse(item, "flexColumns") | ||||||
| 		const videoId = traverse(item, "playNavigationEndpoint", "videoId") | 		const videoId = traverse(item, "playNavigationEndpoint", "videoId") | ||||||
|  |  | ||||||
|  | @ -8,7 +8,9 @@ import { | ||||||
| 	PLAYLIST_DETAILED, | 	PLAYLIST_DETAILED, | ||||||
| 	PLAYLIST_VIDEO, | 	PLAYLIST_VIDEO, | ||||||
| 	SONG_DETAILED, | 	SONG_DETAILED, | ||||||
| 	VIDEO_DETAILED | 	SONG_FULL, | ||||||
|  | 	VIDEO_DETAILED, | ||||||
|  | 	VIDEO_FULL | ||||||
| } from "./interfaces" | } from "./interfaces" | ||||||
| import { LIST, validate } from "validate-any" | import { LIST, validate } from "validate-any" | ||||||
| 
 | 
 | ||||||
|  | @ -26,10 +28,10 @@ ytmusic.initialize().then(() => | ||||||
| 			ytmusic.search(query) | 			ytmusic.search(query) | ||||||
| 		]) | 		]) | ||||||
| 
 | 
 | ||||||
| 		const [artist, artistSongs, artistAlbums, album, playlist, playlistVideos] = | 		const [song, video, artist, artistSongs, artistAlbums, album, playlist, playlistVideos] = | ||||||
| 			await Promise.all([ | 			await Promise.all([ | ||||||
| 				// ytmusic.getSong(songs[0].videoId),
 | 				ytmusic.getSong(songs[0].videoId!), | ||||||
| 				// ytmusic.getVideo(videos[0].videoId),
 | 				ytmusic.getVideo(videos[0].videoId!), | ||||||
| 				ytmusic.getArtist(artists[0].artistId), | 				ytmusic.getArtist(artists[0].artistId), | ||||||
| 				ytmusic.getArtistSongs(artists[0].artistId), | 				ytmusic.getArtistSongs(artists[0].artistId), | ||||||
| 				ytmusic.getArtistAlbums(artists[0].artistId), | 				ytmusic.getArtistAlbums(artists[0].artistId), | ||||||
|  | @ -54,8 +56,8 @@ ytmusic.initialize().then(() => | ||||||
| 					VIDEO_DETAILED | 					VIDEO_DETAILED | ||||||
| 				) | 				) | ||||||
| 			], | 			], | ||||||
| 			// [song, SONG_DETAILED],
 | 			[song, SONG_FULL], | ||||||
| 			// [video, VIDEO_DETAILED],
 | 			[video, VIDEO_FULL], | ||||||
| 			[artist, ARTIST_FULL], | 			[artist, ARTIST_FULL], | ||||||
| 			[artistSongs, LIST(SONG_DETAILED)], | 			[artistSongs, LIST(SONG_DETAILED)], | ||||||
| 			[artistAlbums, LIST(ALBUM_DETAILED)], | 			[artistAlbums, LIST(ALBUM_DETAILED)], | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import ObjectValidator from "validate-any/build/validators/ObjectValidator" | 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({ | export const THUMBNAIL_FULL: ObjectValidator<YTMusic.ThumbnailFull> = OBJECT({ | ||||||
| 	url: STRING(), | 	url: STRING(), | ||||||
|  | @ -54,6 +54,33 @@ export const ALBUM_DETAILED: ObjectValidator<YTMusic.AlbumDetailed> = OBJECT({ | ||||||
| 	thumbnails: LIST(THUMBNAIL_FULL) | 	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({ | export const ARTIST_FULL: ObjectValidator<YTMusic.ArtistFull> = OBJECT({ | ||||||
| 	artistId: STRING(), | 	artistId: STRING(), | ||||||
| 	name: 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[] | 		thumbnails: ThumbnailFull[] | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	interface SongFull extends Omit<SongDetailed, "album"> { | ||||||
|  | 		description: string | ||||||
|  | 		formats: any[] | ||||||
|  | 		adaptiveFormats: any[] | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	interface VideoDetailed { | 	interface VideoDetailed { | ||||||
| 		type: "VIDEO" | 		type: "VIDEO" | ||||||
| 		videoId: string | null | 		videoId: string | null | ||||||
|  | @ -25,6 +31,14 @@ declare namespace YTMusic { | ||||||
| 		thumbnails: ThumbnailFull[] | 		thumbnails: ThumbnailFull[] | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	interface VideoFull extends VideoDetailed { | ||||||
|  | 		description: string | ||||||
|  | 		unlisted: boolean | ||||||
|  | 		familySafe: boolean | ||||||
|  | 		paid: boolean | ||||||
|  | 		tags: string[] | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	interface ArtistBasic { | 	interface ArtistBasic { | ||||||
| 		artistId: string | null | 		artistId: string | null | ||||||
| 		name: string | 		name: string | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue