UNPKG

apple-music-metadata

Version:

gets apple music metadata for songs, albums and playlists links

168 lines (167 loc) 5.59 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EnableDebug = void 0; const tslib_1 = require("tslib"); const axios_1 = tslib_1.__importDefault(require("axios")); const cheerio_1 = tslib_1.__importDefault(require("cheerio")); const debugPrefix = "apple music: "; let debug = false; function EnableDebug() { debug = true; } exports.EnableDebug = EnableDebug; function getRawPlaylist(document) { const $ = cheerio_1.default.load(document); const tracks = []; const songList = $("div.songs-list-row").toArray(); songList.forEach((song) => { const lookArtist = $(song) .find("div.songs-list__col--artist") .find("a.songs-list-row__link"); const track = { artist: { name: lookArtist.text(), url: lookArtist.attr("href") ?? "", }, title: $(song) .find("div.songs-list__col--song") .find("div.songs-list-row__song-name") .text(), duration: $(song) .find("div.songs-list__col--time") .find("time") .text() .trim() .split(":") .map((value) => Number(value)) .reduce((acc, time) => 60 * acc + time), url: $(song) .find("div.songs-list__col--album") .find("a.songs-list-row__link") .attr("href") ?? "", type: "song", }; tracks.push(track); }); const product = $("div.product-page-header"); const creator = product.find("div.product-creator").find("a.dt-link-to"); const playlist = { title: product.find("h1.product-name").text().trim(), description: product .find("div.product-page-header__metadata--notes") .text() .trim(), creator: { name: creator.text().trim(), url: "https://music.apple.com" + creator.attr("href") ?? "", }, tracks, numTracks: tracks.length, type: "playlist", }; return playlist; } function getRawAlbum(document) { const $ = cheerio_1.default.load(document); const tracks = []; const product = $("div.product-page-header"); const creator = product.find("div.product-creator").find("a.dt-link-to"); const artist = { name: creator.text().trim(), url: creator.attr("href") ?? "", }; const albumUrl = $("meta[property='og:url']").attr("content"); const songList = $("div.songs-list-row").toArray(); songList.forEach((song) => { const track = { artist, title: $(song) .find("div.songs-list__col--song") .find("div.songs-list-row__song-name") .text(), duration: $(song) .find("div.songs-list__col--time") .find("time") .text() .trim() .split(":") .map((value) => Number(value)) .reduce((acc, time) => 60 * acc + time), url: albumUrl ? albumUrl + "?i=" + JSON.parse($(song) .find("div.songs-list__col--time") .find("button.preview-button") .attr("data-metrics-click") ?? "{ targetId: 0 }")["targetId"] ?? "" : "", type: "song", }; tracks.push(track); }); const playlist = { title: product.find("h1.product-name").text().trim(), description: product .find("div.product-page-header__metadata--notes") .text() .trim(), artist, tracks, numTracks: tracks.length, type: "album", }; return playlist; } function linkType(url) { if (RegExp(/https?:\/\/music\.apple\.com\/.+?\/album\/.+?\/.+?\?i=([0-9]+)/).test(url)) { return "song"; } else if (RegExp(/https?:\/\/music\.apple\.com\/.+?\/playlist\//).test(url)) { return "playlist"; } else if (RegExp(/https?:\/\/music\.apple\.com\/.+?\/album\//).test(url)) { return "album"; } else { throw Error("Apple Music link is invalid"); } } async function search(url) { const urlType = linkType(url); const page = await axios_1.default .get(url) .then((res) => res.data) .catch(() => undefined); if (!page) { if (debug) { console.log(debugPrefix + "http request failed"); } return null; } if (urlType === "playlist") { return getRawPlaylist(page); } const album = getRawAlbum(page); if (urlType === "album") { return album; } const match = new RegExp(/https?:\/\/music\.apple\.com\/.+?\/album\/.+?\/.+?\?i=([0-9]+)/).exec(url); const id = match ? match[1] : undefined; if (!id) { if (debug) { console.log(debugPrefix + "failed to extract song id"); } return null; } const track = album.tracks.find((track) => { return track.url.includes(`?i=${id}`); }); if (!track) { if (debug) { console.log(debugPrefix + "track not found in album"); } return null; } return track; } exports.default = search;