@pixel_nomad/kazagumo-jiosaavn
Version:
A JioSaavn plugin for Kazagumo
212 lines (211 loc) • 8.85 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KazagumoPlugin = void 0;
const kazagumo_1 = require("@pixel_nomad/kazagumo");
const JioSaavnAPI_1 = require("./JioSaavnAPI");
const kazagumo_2 = require("@pixel_nomad/kazagumo");
const REGEX = /(?:https?:\/\/)?(?:www\.)?(?:jiosaavn\.com|saavn\.com)\/(song|album|artist|featured)\/[^\/]+\/([^\/]+)/i;
const newREGEX = /(?:https?:\/\/)?(?:www\.)?(?:jiosaavn\.com|saavn\.com)\/s\/(playlist)\/[^\/]+\/[^\/]+\/([^\/]+)/i;
const bkpREGEX = /(?:https?:\/\/)?(?:www\.)?(?:jiosaavn\.com|saavn\.com)\/s\/(song)\/[^\/]+\/[^\/]+\/[^\/]+\/([^\/]+)/i;
// export interface JioSaavnPluginOptions {
// /**
// * The number of tracks to fetch per page for playlists/albums
// * @default 50
// */
// pageLimit?: number;
// /**
// * The track limit when searching
// * @default 10
// */
// searchLimit?: number;
// /**
// * Number of retries for failed requests
// * @default 2
// */
// retryLimit?: number;
// }
class KazagumoPlugin extends kazagumo_1.KazagumoPlugin {
constructor(options = {}) {
super();
this.options = {
pageLimit: options.pageLimit ?? 50,
searchLimit: options.searchLimit ?? 10,
retryLimit: options.retryLimit ?? 2,
};
this.api = new JioSaavnAPI_1.JioSaavnAPI();
this.kazagumo = null;
this._search = null;
this.retriesLeft = this.options.retryLimit;
this.methods = {
song: this.getTrack.bind(this),
album: this.getAlbum.bind(this),
artist: this.getArtist.bind(this),
playlist: this.getPlaylist.bind(this),
featured: this.getPlaylist.bind(this),
};
}
load(kazagumo) {
this.kazagumo = kazagumo;
this._search = kazagumo.search.bind(kazagumo);
kazagumo.search = this.search.bind(this);
}
async search(query, options) {
if (!this.kazagumo || !this._search) {
throw new kazagumo_2.KazagumoError(1, 'kazagumo-jiosaavn is not loaded yet.');
}
if (!query)
throw new kazagumo_2.KazagumoError(3, 'Query is required');
const isUrl = /^https?:\/\//i.test(query);
const normalURL = REGEX.test(query);
const bkpURL = bkpREGEX.test(query);
if (normalURL) {
const [, type, id] = REGEX.exec(query) || [];
if (type in this.methods) {
try {
// Try with Lavalink first if enabled
if (this.retriesLeft > 0) {
const lavalinkResult = await this._search(query, options);
if (lavalinkResult.tracks.length > 0)
return lavalinkResult;
this.retriesLeft--;
}
const result = await this.methods[type](id, options?.requester);
const loadType = type === 'song' ? 'TRACK' : 'PLAYLIST';
return this.buildSearch(result.name, result.tracks, loadType);
}
catch (e) {
return this.buildSearch(undefined, [], 'SEARCH');
}
}
else if (options?.engine === 'jiosaavn' && !isUrl) {
const result = await this.searchTrack(query, options?.requester);
return this.buildSearch(undefined, result.tracks, 'SEARCH');
}
}
else if (bkpURL) {
const [, type, id] = bkpREGEX.exec(query) || [];
if (type in this.methods) {
try {
// Try with Lavalink first if enabled
if (this.retriesLeft > 0) {
const lavalinkResult = await this._search(query, options);
if (lavalinkResult.tracks.length > 0)
return lavalinkResult;
this.retriesLeft--;
}
const result = await this.methods[type](id, options?.requester);
const loadType = type === 'song' ? 'TRACK' : 'PLAYLIST';
return this.buildSearch(result.name, result.tracks, loadType);
}
catch (e) {
return this.buildSearch(undefined, [], 'SEARCH');
}
}
else if (options?.engine === 'jiosaavn' && !isUrl) {
const result = await this.searchTrack(query, options?.requester);
return this.buildSearch(undefined, result.tracks, 'SEARCH');
}
}
else {
const [, type, id] = newREGEX.exec(query) || [];
if (type in this.methods) {
try {
// Try with Lavalink first if enabled
if (this.retriesLeft > 0) {
const lavalinkResult = await this._search(query, options);
if (lavalinkResult.tracks.length > 0)
return lavalinkResult;
this.retriesLeft--;
}
const result = await this.methods[type](id, options?.requester);
const loadType = type === 'song' ? 'TRACK' : 'PLAYLIST';
return this.buildSearch(result.name, result.tracks, loadType);
}
catch (e) {
return this.buildSearch(undefined, [], 'SEARCH');
}
}
else if (options?.engine === 'jiosaavn' && !isUrl) {
const result = await this.searchTrack(query, options?.requester);
return this.buildSearch(undefined, result.tracks, 'SEARCH');
}
}
return this._search(query, options);
}
async searchTrack(query, requester) {
const { results } = await this.api.search(query);
const tracks = results.slice(0, this.options.searchLimit)
.map(track => this.buildKazagumoTrack(track, requester));
return { tracks };
}
async getTrack(id, requester) {
const { track } = await this.api.getTrack(id);
return { tracks: [this.buildKazagumoTrack(track, requester)] };
}
async getAlbum(id, requester) {
const { album } = await this.api.getAlbum(id);
const tracks = album.tracks
.slice(0, this.options.pageLimit)
.map(track => this.buildKazagumoTrack(track, requester));
return { tracks, name: album.name };
}
async getArtist(id, requester) {
const { artist } = await this.api.getArtist(id);
const tracks = artist.tracks
.slice(0, this.options.pageLimit)
.map(track => this.buildKazagumoTrack(track, requester));
return { tracks, name: artist.name };
}
async getPlaylist(id, requester) {
const { playlist } = await this.api.getPlaylist(id, this.options.pageLimit);
const tracks = playlist.tracks
.map(track => this.buildKazagumoTrack(track, requester));
return { tracks, name: playlist.title };
}
buildSearch(playlistName, tracks = [], type) {
return {
playlistName,
tracks,
type: type ?? 'TRACK',
};
}
buildKazagumoTrack(jiosaavnTrack, requester) {
return new kazagumo_1.KazagumoTrack({
encoded: '',
pluginInfo: {
name: 'kazagumo-jiosaavn',
},
info: {
sourceName: 'jiosaavn',
identifier: jiosaavnTrack.identifier,
isSeekable: true,
author: jiosaavnTrack.author || 'Unknown Artist',
length: jiosaavnTrack.length,
isStream: false,
position: 0,
title: jiosaavnTrack.title,
uri: jiosaavnTrack.uri || `https://www.jiosaavn.com/song/${jiosaavnTrack.identifier}`,
artworkUrl: jiosaavnTrack.artworkUrl,
},
}, requester).setKazagumo(this.kazagumo);
}
}
exports.KazagumoPlugin = KazagumoPlugin;
// interface Result {
// tracks: KazagumoTrack[];
// name?: string;
// }
// export interface JioSaavnTrack {
// identifier: string;
// title: string;
// length: number;
// uri: string | null;
// artworkUrl: string;
// author: string | null;
// encryptedMediaUrl: string | null;
// albumUrl: string | null;
// artistUrl: string | null;
// albumName: string | null;
// artistArtworkUrl: string | null;
// previewUrl: string | null;
// }