diff --git a/src/YTMusic.ts b/src/YTMusic.ts index 35dba43..1d14139 100644 --- a/src/YTMusic.ts +++ b/src/YTMusic.ts @@ -21,6 +21,7 @@ import { VideoFull } from "." import { Cookie, CookieJar } from "tough-cookie" +import { writeFileSync } from "fs" export default class YTMusic { private cookiejar: CookieJar @@ -436,7 +437,7 @@ export default class YTMusic { "musicPlaylistShelfRenderer", "musicResponsiveListItemRenderer" ) - let continuation = traverse(playlistData, "musicPlaylistShelfRenderer", "continuation") + let continuation = traverse(playlistData, "continuation") while (true) { if (continuation instanceof Array) break diff --git a/src/__tests__/traversing.spec.ts b/src/__tests__/traversing.spec.ts index b65c96d..405dcfe 100644 --- a/src/__tests__/traversing.spec.ts +++ b/src/__tests__/traversing.spec.ts @@ -1,20 +1,13 @@ import assert from "assert" import describeParallel from "mocha.parallel" -import Validator from "validate-any/dist/classes/Validator" -import YTMusic from ".." -import { - ALBUM_DETAILED, - ALBUM_FULL, - ARTIST_DETAILED, - ARTIST_FULL, - PLAYLIST_FULL, - PLAYLIST_VIDEO, - SONG_DETAILED, - SONG_FULL, - VIDEO_DETAILED, - VIDEO_FULL -} from "../interfaces" import { iValidationError, LIST, STRING, validate } from "validate-any" +import Validator from "validate-any/dist/classes/Validator" + +import YTMusic from "../" +import { + ALBUM_DETAILED, ALBUM_FULL, ARTIST_DETAILED, ARTIST_FULL, PLAYLIST_FULL, PLAYLIST_VIDEO, + SONG_DETAILED, SONG_FULL, VIDEO_DETAILED, VIDEO_FULL +} from "../interfaces" const issues: iValidationError[][] = [] const queries = ["Lilac", "Weekend", "Eill", "Eminem", "Lisa Hannigan"] diff --git a/src/index.ts b/src/index.ts index a758380..be972f2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,7 +27,6 @@ export interface VideoDetailed { videoId: string name: string artists: ArtistBasic[] - views: number duration: number thumbnails: ThumbnailFull[] } @@ -67,7 +66,6 @@ export interface AlbumDetailed extends AlbumBasic { type: "ALBUM" playlistId: string artists: ArtistBasic[] - year: number thumbnails: ThumbnailFull[] } diff --git a/src/interfaces.ts b/src/interfaces.ts index 00d17cb..9bd0bf5 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -1,19 +1,10 @@ -import ObjectValidator from "validate-any/dist/validators/ObjectValidator" -import { - AlbumBasic, - AlbumDetailed, - AlbumFull, - ArtistBasic, - ArtistDetailed, - ArtistFull, - PlaylistFull, - SongDetailed, - SongFull, - ThumbnailFull, - VideoDetailed, - VideoFull -} from "." import { BOOLEAN, LIST, NUMBER, OBJECT, STRING } from "validate-any" +import ObjectValidator from "validate-any/dist/validators/ObjectValidator" + +import { + AlbumBasic, AlbumDetailed, AlbumFull, ArtistBasic, ArtistDetailed, ArtistFull, PlaylistFull, + SongDetailed, SongFull, ThumbnailFull, VideoDetailed, VideoFull +} from "./" export const THUMBNAIL_FULL: ObjectValidator = OBJECT({ url: STRING(), @@ -46,7 +37,6 @@ export const VIDEO_DETAILED: ObjectValidator = OBJECT({ videoId: STRING(), name: STRING(), artists: LIST(ARTIST_BASIC), - views: NUMBER(), duration: NUMBER(), thumbnails: LIST(THUMBNAIL_FULL) }) @@ -64,7 +54,6 @@ export const ALBUM_DETAILED: ObjectValidator = OBJECT({ playlistId: STRING(), name: STRING(), artists: LIST(ARTIST_BASIC), - year: NUMBER(), thumbnails: LIST(THUMBNAIL_FULL) }) @@ -85,7 +74,6 @@ export const VIDEO_FULL: ObjectValidator = OBJECT({ videoId: STRING(), name: STRING(), artists: LIST(ARTIST_BASIC), - views: NUMBER(), duration: NUMBER(), thumbnails: LIST(THUMBNAIL_FULL), description: STRING(), @@ -121,7 +109,6 @@ export const ALBUM_FULL: ObjectValidator = OBJECT({ playlistId: STRING(), name: STRING(), artists: LIST(ARTIST_BASIC), - year: NUMBER(), thumbnails: LIST(THUMBNAIL_FULL), description: STRING(), songs: LIST(SONG_DETAILED) diff --git a/src/parsers/AlbumParser.ts b/src/parsers/AlbumParser.ts index ba5f1d5..dc56a59 100644 --- a/src/parsers/AlbumParser.ts +++ b/src/parsers/AlbumParser.ts @@ -1,9 +1,9 @@ +import { AlbumBasic, AlbumDetailed, AlbumFull, ArtistBasic } from "../" +import { ALBUM_DETAILED, ALBUM_FULL } from "../interfaces" import checkType from "../utils/checkType" -import SongParser from "./SongParser" import traverseList from "../utils/traverseList" import traverseString from "../utils/traverseString" -import { ALBUM_DETAILED, ALBUM_FULL } from "../interfaces" -import { AlbumBasic, AlbumDetailed, AlbumFull, ArtistBasic } from ".." +import SongParser from "./SongParser" export default class AlbumParser { public static parse(data: any, albumId: string): AlbumFull { @@ -25,7 +25,6 @@ export default class AlbumParser { ...albumBasic, playlistId: traverseString(data, "buttonRenderer", "playlistId")(), artists, - year: +traverseString(data, "header", "subtitle", "text")(-1), thumbnails, description: traverseString(data, "description", "text")(), songs: traverseList(data, "musicResponsiveListItemRenderer").map(item => @@ -51,7 +50,6 @@ export default class AlbumParser { name: traverseString(run, "text")() })), name: traverseString(flexColumns[0], "runs", "text")(), - year: +traverseString(flexColumns[1], "runs", "text")(-1), thumbnails: traverseList(item, "thumbnails") }, ALBUM_DETAILED @@ -66,7 +64,6 @@ export default class AlbumParser { playlistId: traverseString(item, "thumbnailOverlay", "playlistId")(), name: traverseString(item, "title", "text")(), artists: [artistBasic], - year: +traverseString(item, "subtitle", "text")(-1), thumbnails: traverseList(item, "thumbnails") }, ALBUM_DETAILED @@ -81,7 +78,6 @@ export default class AlbumParser { playlistId: traverseString(item, "musicPlayButtonRenderer", "playlistId")(), name: traverseString(item, "title", "text")(), artists: [artistBasic], - year: +traverseString(item, "subtitle", "text")(-1), thumbnails: traverseList(item, "thumbnails") }, ALBUM_DETAILED diff --git a/src/parsers/ArtistParser.ts b/src/parsers/ArtistParser.ts index eca147a..4f0ec74 100644 --- a/src/parsers/ArtistParser.ts +++ b/src/parsers/ArtistParser.ts @@ -1,11 +1,11 @@ -import AlbumParser from "./AlbumParser" +import { ArtistBasic, ArtistDetailed, ArtistFull } from "../" +import { ARTIST_DETAILED, ARTIST_FULL } from "../interfaces" import checkType from "../utils/checkType" -import Parser from "./Parser" -import SongParser from "./SongParser" import traverseList from "../utils/traverseList" import traverseString from "../utils/traverseString" -import { ARTIST_DETAILED, ARTIST_FULL } from "../interfaces" -import { ArtistBasic, ArtistDetailed, ArtistFull } from ".." +import AlbumParser from "./AlbumParser" +import Parser from "./Parser" +import SongParser from "./SongParser" export default class ArtistParser { public static parse(data: any, artistId: string): ArtistFull { diff --git a/src/parsers/PlaylistParser.ts b/src/parsers/PlaylistParser.ts index 9c251a5..45b2772 100644 --- a/src/parsers/PlaylistParser.ts +++ b/src/parsers/PlaylistParser.ts @@ -1,8 +1,8 @@ +import { PlaylistFull } from "../" +import { PLAYLIST_FULL } from "../interfaces" import checkType from "../utils/checkType" import traverseList from "../utils/traverseList" import traverseString from "../utils/traverseString" -import { PLAYLIST_FULL } from "../interfaces" -import { PlaylistFull } from ".." export default class PlaylistParser { public static parse(data: any, playlistId: string): PlaylistFull { diff --git a/src/parsers/SearchParser.ts b/src/parsers/SearchParser.ts index ef4ed56..85de453 100644 --- a/src/parsers/SearchParser.ts +++ b/src/parsers/SearchParser.ts @@ -1,10 +1,10 @@ +import { SearchResult } from "../" +import traverseList from "../utils/traverseList" import AlbumParser from "./AlbumParser" import ArtistParser from "./ArtistParser" import PlaylistParser from "./PlaylistParser" import SongParser from "./SongParser" -import traverseList from "../utils/traverseList" import VideoParser from "./VideoParser" -import { SearchResult } from ".." export default class SearchParser { public static parse(item: any): SearchResult { diff --git a/src/parsers/SongParser.ts b/src/parsers/SongParser.ts index 31bac30..c288dcd 100644 --- a/src/parsers/SongParser.ts +++ b/src/parsers/SongParser.ts @@ -1,10 +1,11 @@ +import { LIST, OBJECT, STRING } from "validate-any" + +import { AlbumBasic, ArtistBasic, SongDetailed, SongFull, ThumbnailFull } from "../" +import { ALBUM_BASIC, ARTIST_BASIC, SONG_DETAILED, SONG_FULL, THUMBNAIL_FULL } from "../interfaces" import checkType from "../utils/checkType" -import Parser from "./Parser" import traverseList from "../utils/traverseList" import traverseString from "../utils/traverseString" -import { ALBUM_BASIC, ARTIST_BASIC, SONG_DETAILED, SONG_FULL, THUMBNAIL_FULL } from "../interfaces" -import { AlbumBasic, ArtistBasic, SongDetailed, SongFull, ThumbnailFull } from ".." -import { LIST, OBJECT, STRING } from "validate-any" +import Parser from "./Parser" export default class SongParser { public static parse(data: any): SongFull { @@ -19,7 +20,7 @@ export default class SongParser { name: traverseString(data, "author")() } ], - duration: +traverseString(data, "videoDetails", "lengthSeconds"), + duration: +traverseString(data, "videoDetails", "lengthSeconds")(), thumbnails: traverseList(data, "videoDetails", "thumbnails"), description: traverseString(data, "description")(), formats: traverseList(data, "streamingData", "formats"), @@ -45,7 +46,7 @@ export default class SongParser { })) .slice(0, -1), album: { - albumId: traverseString(item, "browseId")(-1), + albumId: traverseString(flexColumns[1], "runs", "browseId")(-1), name: traverseString(flexColumns[1], "runs", "text")(-3) }, duration: Parser.parseDuration(traverseString(flexColumns[1], "runs", "text")(-1)), @@ -97,8 +98,8 @@ export default class SongParser { name: traverseString(flexColumns[0], "runs", "text")(), artists: [artistBasic], album: { - albumId: traverseString(flexColumns[2], "runs", "text")(), - name: traverseString(flexColumns[2], "browseId")() + albumId: traverseString(flexColumns[2], "browseId")(), + name: traverseString(flexColumns[2], "runs", "text")() }, thumbnails: traverseList(item, "thumbnails") }, diff --git a/src/parsers/VideoParser.ts b/src/parsers/VideoParser.ts index fcf33b2..aa7c017 100644 --- a/src/parsers/VideoParser.ts +++ b/src/parsers/VideoParser.ts @@ -1,10 +1,10 @@ +import { VideoDetailed, VideoFull } from "../" +import { PLAYLIST_VIDEO } from "../interfaces" import checkType from "../utils/checkType" -import Parser from "./Parser" import traverse from "../utils/traverse" import traverseList from "../utils/traverseList" import traverseString from "../utils/traverseString" -import { PLAYLIST_VIDEO } from "../interfaces" -import { VideoDetailed, VideoFull } from ".." +import Parser from "./Parser" export default class VideoParser { public static parse(data: any): VideoFull { @@ -18,7 +18,6 @@ export default class VideoParser { name: traverseString(data, "author")() } ], - views: +traverseString(data, "videoDetails", "viewCount")(), duration: +traverseString(data, "videoDetails", "lengthSeconds")(), thumbnails: traverseList(data, "videoDetails", "thumbnails"), description: traverseString(data, "description")(), @@ -43,9 +42,6 @@ export default class VideoParser { artistId: traverseString(run, "browseId")(), name: traverseString(run, "text")() })), - views: Parser.parseNumber( - traverseString(flexColumns[1], "runs", "text")(-3).slice(0, -6) - ), duration: Parser.parseDuration(traverseString(flexColumns[1], "text")(-1)), thumbnails: traverseList(item, "thumbnails") } @@ -53,7 +49,9 @@ export default class VideoParser { public static parsePlaylistVideo(item: any): Omit { const flexColumns = traverseList(item, "flexColumns") - const videoId = traverseString(item, "playNavigationEndpoint", "videoId")() + const videoId = + traverseString(item, "playNavigationEndpoint", "videoId")() || + traverseList(item, "thumbnails")[0].url.match(/https:\/\/i\.ytimg\.com\/vi\/(.+)\//)[1] return checkType>( {