downloader-spotify
#3r4cfi3javascript ยท 181 baris ยท 23481 dilihat
/**
* ๐ Plugin : Spotify & Lyrics Search (NIXCODE UI v4.6 & Smart LRCLib)
*/
import axios from 'axios';
import { Button } from '../lib/nixcode.js';
const SPOTIFY_SEARCH_1 = "https://api.nexray.eu.cc/search/spotify";
const SPOTIFY_SEARCH_V1 = "https://api.nexray.eu.cc/search/v1/spotify";
const SPOTIFY_DL = "https://api.nexray.eu.cc/downloader/spotify";
function formatDuration(ms) {
if (!ms) return "-";
let minutes = Math.floor(ms / 60000);
let seconds = ((ms % 60000) / 1000).toFixed(0);
return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
}
// Fungsi Lirik Pintar & Akurat (Menyaring versi instrumental/lagu kosong)
async function getLyrics(artist, title) {
try {
let searchQuery = artist && title ? `${artist} ${title}` : title;
if (!searchQuery) return null;
const { data } = await axios.get(`https://lrclib.net/api/search?q=${encodeURIComponent(searchQuery)}`, {
headers: {
referer: `https://lrclib.net/search/${encodeURIComponent(searchQuery)}`,
'user-agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36'
},
timeout: 15000
});
if (!data || !data.length) return null;
// Saring data: Ambil yang memiliki plainLyrics, panjang teks > 50 karakter, dan bukan instrumental
let validSongs = data.filter(v => v.plainLyrics && v.plainLyrics.length > 50 && !v.instrumental);
// Prioritaskan yang cocok dengan nama artisnya jika ada
let matchedSong = validSongs.find(v => artist && v.artistName.toLowerCase().includes(artist.toLowerCase())) || validSongs[0] || data[0];
return matchedSong?.plainLyrics || null;
} catch (e) {
return null;
}
}
let handler = async (m, { conn, text, usedPrefix, command, args }) => {
let cmd = command.toLowerCase();
let query = text || args.join(" ");
// ==========================================
// 1. LYRICS (.lyrics / .lirik)
// ==========================================
if (cmd === "lyrics" || cmd === "lirik") {
if (!query) return m.reply(`โ ๏ธ *Contoh penggunaan:*\n${usedPrefix + command} seafret atlantis`);
await m.react('๐');
try {
let res = await axios.get(`https://lrclib.net/api/search?q=${encodeURIComponent(query)}`, {
headers: {
referer: `https://lrclib.net/search/${encodeURIComponent(query)}`,
'user-agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36'
},
timeout: 15000
});
if (!res.data || !res.data.length) throw new Error("Lirik tidak ditemukan!");
let song = res.data.find(v => v.plainLyrics && v.plainLyrics.length > 50) || res.data[0];
let hasil = `๐ต *LYRICS FINDER*\n\n` +
`*Judul:* ${song.trackName || '-'}\n` +
`*Artis:* ${song.artistName || '-'}\n` +
`*Album:* ${song.albumName || '-'}\n\n` +
`๐ *Lirik:*\n${song.plainLyrics || 'Tidak ada lirik tersedia.'}\n\n` +
`> ยฉ Erine-AI`;
await conn.sendMessage(m.chat, { text: hasil }, { quoted: m });
await m.react('โ
');
} catch (e) {
await m.react('โ');
m.reply(`โ Error: ${e.message}`);
}
return;
}
// ==========================================
// 2. SPOTIFY SEARCH (.spotify / .spsearch)
// ==========================================
if (cmd === "spotify" || cmd === "spsearch") {
if (!query) return m.reply(`โ ๏ธ *Contoh penggunaan:*\n${usedPrefix + command} seafret atlantis`);
await m.react('โณ');
try {
let res;
try {
res = await axios.get(`${SPOTIFY_SEARCH_1}?q=${encodeURIComponent(query)}`, { timeout: 30000 });
} catch (err) {
res = await axios.get(`${SPOTIFY_SEARCH_V1}?q=${encodeURIComponent(query)}`, { timeout: 30000 });
}
let tracks = res.data?.result || res.data?.tracks || res.data?.data || res.data;
if (!Array.isArray(tracks) || !tracks.length) throw new Error("Lagu tidak ditemukan.");
let track = tracks[0];
let trackUrl = track.url || track.external_urls?.spotify || track.link;
let title = track.title || track.name || 'Tanpa Judul';
let artist = track.artist || track.artists?.map(v => v.name).join(', ') || 'Unknown';
let album = track.album || track.album?.name || '-';
let duration = track.duration_ms ? formatDuration(track.duration_ms) : (track.duration || '-');
let thumbnail = track.image || track.thumbnail || track.album?.images?.[0]?.url;
// Ambil lirik dengan menyertakan nama artis + judul agar anti nyasar ke lagu instrumen
let lirikText = await getLyrics(artist, title);
if (!lirikText) lirikText = await getLyrics(null, query);
if (!lirikText) lirikText = "Lirik tidak tersedia.";
let captionText =
`๐ต *Judul:* ${title}\n` +
`๐ค *Penyanyi:* ${artist}\n` +
`๐ฟ *Album:* ${album}\n` +
`โฑ๏ธ *Durasi:* ${duration}\n\n` +
`๐ *Lirik:*\n${lirikText}\n\n` +
`> ยฉ Erine-AI`;
let button = new Button(conn)
.setTitle('๐ง NOW PLAYING')
.setSubtitle(artist)
.setBody(captionText)
.setFooter('');
if (thumbnail) button.setImage(thumbnail);
if (trackUrl) {
button.addReply('๐ฅ Download MP3', `${usedPrefix}spdl ${trackUrl}`, { icon: 'DEFAULT' });
button.addUrl('๐ Open Spotify', trackUrl, true, { icon: 'PROMOTION' });
}
await button.send(m.chat, { quoted: m });
await m.react('โ
');
} catch (e) {
await m.react('โ');
m.reply(`โ Gagal: ${e.message}`);
}
return;
}
// ==========================================
// 3. SPOTIFY DOWNLOADER (.spdl)
// ==========================================
if (cmd === "spdl" || cmd === "spotifydl") {
if (!query) return m.reply(`โ ๏ธ *Masukkan URL Spotify!*\n\n*Contoh:*\n${usedPrefix + command} https://open.spotify.com/track/...`);
await m.react('๐ง');
try {
let { data } = await axios.get(`${SPOTIFY_DL}?url=${encodeURIComponent(query)}`, { timeout: 50000 });
let audioUrl = data?.result?.url || data?.result?.download || data?.url || data?.data;
if (!audioUrl) throw new Error("Link unduhan audio tidak valid dari API.");
await conn.sendMessage(m.chat, {
audio: { url: audioUrl },
mimetype: 'audio/mpeg',
fileName: `SpotifyMusic.mp3`,
ptt: false
}, { quoted: m });
await m.react('โ
');
} catch (e) {
await m.react('โ');
m.reply(`โ Gagal download: ${e.message}`);
}
return;
}
};
handler.help = ["lyrics <query>", "spotify <query>", "spdl <url>"];
handler.tags = ["downloader", "tools", "internet"];
handler.command = /^(lyrics|lirik|spotify|spsearch|spdl|spotifydl)$/i;
handler.limit = true;
handler.register = true;
export default handler;