UNPKG

erela.js-apple

Version:

Apple Music plugin for Erela.JS

350 lines (279 loc) 13.9 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AppleMusic = void 0; const cheerio = require("cheerio"); const axios = require("axios"); const erela_js_1 = require("erela.js"); const axios_1 = __importDefault(require("axios")); const REGEXTRACK = /(http(s|):\/\/music\.apple\.com\/..\/.....\/.*\/([0-9]){1,})\?i=([0-9]){1,}/gmi const REGEX = /(?:https:\/\/music\.apple\.com\/)(?:\w{2}\/)?(track|album|playlist)/g; const buildSearch = (loadType, tracks, error, name) => ({ loadType: loadType, tracks: tracks !== null && tracks !== void 0 ? tracks : [], playlist: name ? { name, duration: tracks .reduce((acc, cur) => acc + (cur.duration || 0), 0), } : null, exception: error ? { plugin: `AppleMusic`, message: error, severity: "COMMON" } : null, }); const check = (options) => { if (typeof options.convertUnresolved !== "undefined" && typeof options.convertUnresolved !== "boolean") throw new TypeError('AppleMusic option "convertUnresolved" must be a boolean.'); if (typeof options.playlistLimit !== "undefined" && typeof options.playlistLimit !== "number") throw new TypeError('AppleMusic option "playlistLimit" must be a number.'); if (typeof options.albumLimit !== "undefined" && typeof options.albumLimit !== "number") throw new TypeError('AppleMusic option "albumLimit" must be a number.'); }; class AppleMusic extends erela_js_1.Plugin { constructor(options = {}) { super(); check(options); this.options = { playlistLimit: options.playlistLimit && options.playlistLimit >= 1 ? options.playlistLimit : 100, albumLimit: options.albumLimit && options.albumLimit >= 1 ? options.albumLimit : 50, convertUnresolved: options.convertUnresolved ? options.convertUnresolved : false }; this.functions = { track: this.getTrack.bind(this), album: this.getAlbumTracks.bind(this), playlist: this.getPlaylistTracks.bind(this), }; }; load(manager) { this.manager = manager; this._search = manager.search.bind(manager); manager.search = this.search.bind(this); } search(query, requester) { var _a, _b, _c; return __awaiter(this, void 0, void 0, function* () { let AppleURL const finalQuery = query.query || query; if(typeof finalQuery !== "string") return buildSearch("LOAD_FAILED", null, "Query must be a String", null); if(typeof finalQuery === "string") AppleURL = finalQuery.match(REGEX) else AppleURL = null let tipo = AppleURL ? typeSong(query) : [] if(tipo && finalQuery.match(REGEXTRACK)) tipo = `track` if (tipo in this.functions) { try { const func = this.functions[tipo]; if (func) { const data = yield func(query); const loadType = tipo === "track" ? "TRACK_LOADED" : "PLAYLIST_LOADED"; const name = ["playlist", "album"].includes(tipo) ? data.name : null; if(!data || !data.tracks || !data.tracks[0]) return buildSearch('NO_MATCHES', null, null, null); const tracks = data.tracks.map(query => { const track = erela_js_1.TrackUtils.buildUnresolved(query, requester); if (this.options.convertUnresolved) track.resolve(); return track; }); return buildSearch(loadType, tracks, null, name); } const msg = 'Incorrect type for AppleMusic URL, must be one "track of album","album" or "playlist".'; return buildSearch("LOAD_FAILED", null, msg, null); } catch (e) { return buildSearch((_b = e.loadType) !== null && _b !== void 0 ? _b : "LOAD_FAILED", null, (_c = e.message) !== null && _c !== void 0 ? _c : null, null); }; }; return this._search(query, requester); }); }; getAlbumTracks(url) { return __awaiter(this, void 0, void 0, function* () { let x = axios.get(url) let s = yield x let $ = cheerio.load(s.data), Title = $(".songs-list-row__song-name").toArray(), Artist = $(".dt-link-to").toArray(), Album = $(".product-name").toArray(), Otro = $(`.songs-list-row__link`).toArray(), Playlist = [] let Alterno = Otro[0] ? Otro[0].children[2].prev.data : 'No existe capo' let artista = Artist[0] ? Artist[0].children[1].data : Alterno let i = 0 for(i; i < Title.length; i++){ Playlist.push({ title: Title[i].lastChild.prev.data, uri: url, album: Album[0].children[4].data.replace(/ /g, "").replace(/\n/g, ""), artist: `${artista}`, }); } let data = Playlist let titulo = Album[0].children[4].data.replace(/ /g, "").replace(/\n/g, "") const tracks = data.map(item => AppleMusic.convertToUnresolved(item)); return { tracks: tracks.splice(0, this.options.albumLimit), name: titulo }; }); }; getPlaylistTracks(url) { return __awaiter(this, void 0, void 0, function* () { let res = yield ApplePlayList(url) let PlaylistName = Titulo(url) const tracks = res.map(item => AppleMusic.convertToUnresolved(item)); return { tracks: tracks.splice(0, this.options.playlistLimit), name: PlaylistName }; }); }; getTrack(url) { return __awaiter(this, void 0, void 0, function* () { const title = replaceTexto(url) var x = axios.get(url).then(async res => { var $ = cheerio.load(res.data), Title = $(".songs-list-row__song-name").toArray(), Artist = $(".dt-link-to").toArray(), Otro = $(`.songs-list-row__link`).toArray(), Alternative = $(`.songs-list-row__link`).toArray(), arrayObject = [] $(`.songs-list-row__song-container .songs-list-row__song-wrapper`).each((x, y) => { arrayObject.push({authors: $(y).find("a").text().trim(),song: $(y).find(`.songs-list-row__song-name`).text()}) }) let i = 0 try{ var Alterno = Otro[0] ? Otro[0].children[2].prev.data : 'No existe capo' var artista = Artist[0] ? Artist[1] ? Artist[1].children[1].data : Artist[0].children[1].data : Alterno while(Title[i].lastChild.prev.data.toLowerCase().replace("¡", "").replace("!", "").replace(`'`, '').replace("¿", '').replace("?", '') !== title.toLowerCase()){ i++ } let objectTrack = { artist: `${artista}`, uri: url, title:`${Title[i].lastChild.prev.data} ${artista}` } return objectTrack } catch (e) { console.log(e) let objectTrackErr let i = 0 if(typeof artista == "undefined"){ let res = await gettrackWithArist(arrayObject, title) objectTrackErr = { artist: res.authors, uri: url, title: res.song } return objectTrackErr } else { objectTrackErr = { artist: `${artista}`, uri: url, title:`${Title[0].lastChild.prev.data} ${artista}` } } return objectTrackErr } }) let data = yield x const track = AppleMusic.convertToUnresolved(data); return { tracks: [track] }; }); }; static convertToUnresolved(track) { if (!track) throw new ReferenceError("The Apple track object was not provided"); if (!track.artist) throw new ReferenceError("The track artist array was not provided"); if (!track.title) throw new ReferenceError("The track title was not provided"); if (typeof track.title !== "string") throw new TypeError(`The track title must be a string, received type ${typeof track.name}`); return { title: track.title, author: track.artist, uri: track.uri, duration: getRandom(140, 250) * 1000, }; } }; function typeSong(url) { let res = url.replace(/https:\/\//i,'').split('/')[2] return res } function Titulo(title){ let first = title.replace(/https:\/\//i,'').split('/')[3] let text = first.replace(/-/g, " ").split(" ") let coso = ''; for (let i of text) { coso+=i.slice(0,1).toUpperCase() +i.slice(1) + ' ' } return coso } function getRandom(min, max) { return Math.random() * (max - min) + min; } function replaceTexto(texto) { let nuevo = texto.replace(/https:\/\//i,'').split('/')[3].replace(/-/g, " ").replace(/%C3%B3/g, "ó").replace(/%C3%A9/g, "é").replace(/%C3%BA/g, "ú").replace(/%C3%AD/g, "í").replace(/%C3%A1/g, "á").replace(/%C3%B1/g, "ñ") return nuevo } async function gettrackWithArist(arr, title){ for(const data of arr){ let cosa = letras(data.song) let nuevostring = cosa.split(" ").slice(0, 2).join(" ").replace(")", "").replace(".","").replace("(", "") let reg = new RegExp(nuevostring, "gmi") if(reg.test(title)){ return data } } } /** * Get the apple music playlist and returns an array of objects with an album, artist and title property * @param {string} url The url to the apple music playlist * @return {Promise<object[]>} The playlist array */ function ApplePlayList(url) { return new Promise((resolve, reject) => { if (!url) { reject(new Error("Playlist url is undefined")); } else { axios.get(url).then(res => { let $ = cheerio.load(res.data), aTitleDivs = $(".songs-list-row__song-name").toArray(), aArtistDivs = $(".songs-list-row__link").toArray(), aPlaylist = [], i, j = 0; for (i = 0; i < aTitleDivs.length; i++) { aPlaylist.push({ uri: aArtistDivs[j].children[1].parent.attribs.href, album: aArtistDivs[j + 2].firstChild.data, artist: aArtistDivs[j].children[1].data, title: `${aTitleDivs[i].children[1].data} ${aArtistDivs[j].children[1].data}` }); j += 3; } resolve(aPlaylist); }).catch(err => { reject(err); }); } }); } function letras(imput) { const input = imput.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/'/g, "").replace(/,/g, ""); return input; } function delayFor(ms) { return new Promise(resolve => { setTimeout(resolve, ms); }); } exports.AppleMusic = AppleMusic;