import type {SoundcloudPlaylistFilter, SoundcloudPlaylistSearch, SoundcloudPlaylist} from "../types" import {API} from "../API" import {Tracks, Resolve} from "./index" export class Playlists { private readonly tracks = new Tracks(this.api) private readonly resolve = new Resolve(this.api) public constructor(private readonly api: API) {} /** * Return playlist with all tracks fetched. */ public fetch = async (playlist: SoundcloudPlaylist) => { const unresolvedTracks = playlist.tracks.splice(playlist.tracks.findIndex(t => !t.title)).map(t => t.id) if (unresolvedTracks.length === 0) return playlist playlist.tracks = playlist.tracks.concat(await this.tracks.getArray(unresolvedTracks, true)) return playlist as SoundcloudPlaylist } /** * Searches for playlists using the v2 API. */ public search = async (params?: SoundcloudPlaylistFilter) => { const response = await this.api.getV2("search/playlists", params) return response as Promise } /** * Fetches a playlist from URL or ID using Soundcloud v2 API. */ public get = async (playlistResolvable: string | number) => { const playlistID = await this.resolve.get(playlistResolvable) const response = await this.api.getV2(`/playlists/${playlistID}`) return this.fetch(response) as Promise } /** * Searches for playlists (web scraping) */ public searchAlt = async (query: string) => { const headers = this.api.headers const html = await fetch(`https://soundcloud.com/search/sets?q=${query}`, {headers}).then(r => r.text()) const urls = html.match(/(?<=
  • )/gm)?.map((u: any) => `https://soundcloud.com${u}`) if (!urls) return [] const scrape: any = [] for (let i = 0; i < urls.length; i++) { const songHTML = await fetch(urls[i], {headers}).then(r => r.text()) const json = JSON.parse(songHTML.match(/(\[{)(.*)(?=;)/gm)[0]) const playlist = json[json.length - 1].data scrape.push(playlist) } return scrape as Promise } /** * Gets a playlist by URL (web scraping) */ public getAlt = async (url: string) => { if (!url.startsWith("https://soundcloud.com/")) url = `https://soundcloud.com/${url}` const headers = this.api.headers const songHTML = await fetch(url, {headers}).then((r: any) => r.text()) const json = JSON.parse(songHTML.match(/(\[{)(.*)(?=;)/gm)[0]) const playlist = json[json.length - 1].data return this.fetch(playlist) as Promise } }