const axios = require("axios"); const yts = require("yt-search"); const fs = require("fs-extra"); const path = require("path"); const { pipeline } = require("stream/promises"); const { Transform } = require("stream"); module.exports = { config: { name: "nila", aliases: ["nil", "নিল", "নীলা"], version: "1.2.0", author: "JABED", countDown: 3, role: 0, description: { en: "Nila — Bangla AI + Auto Song/Video Downloader", bn: "Nila — বাংলা AI + অটো গান/ভিডিও ডাউনলোডার" }, category: "ai", guide: { en: "{pn} \n{pn} song/play \n{pn} video/vdo ", bn: "{pn} <মেসেজ>\n{pn} song/play <গানের নাম>\n{pn} video/vdo <নাম>" } }, chatMemory: {}, SING_AUDIO_API: "https://yt-song-api.vercel.app/api/song", SING_VIDEO_API: "https://video-dl-api-tan.vercel.app", AI_API: "https://uzairrajputapis.qzz.io/api/ai/gemini", MAX_FILE_SIZE: 25 * 1024 * 1024, OWNER_TAG: "»»𝐎𝐖𝐍𝐄𝐑««★™ »»𝐉𝐀𝐁𝐄𝐃««", TRIGGER_WORDS: ["nila", "nil", "নিলা", "নীলা", "নিল"], async getMahmudBase() { try { const { data } = await axios.get( "https://raw.githubusercontent.com/mahmudx7/HINATA/main/baseApiUrl.json", { timeout: 10000 } ); return data.mahmud || data.api; } catch { return "https://mahmud-apis.vercel.app"; } }, fileSizeGuard(maxBytes) { let received = 0; return new Transform({ transform(chunk, _, cb) { received += chunk.length; if (received > maxBytes) { const e = new Error("File too large"); e.code = "TOO_LARGE"; return cb(e); } cb(null, chunk); } }); }, async removeFile(p) { if (p && fs.existsSync(p)) { try { await fs.unlink(p); } catch {} } }, async searchYT(query) { try { const s = await yts(query); if (s.videos?.[0]) { return { url: s.videos[0].url, title: s.videos[0].title, videoId: s.videos[0].videoId }; } } catch {} return null; }, // ===== AUDIO (sing → music fallback) ===== async downloadAudio(api, event, query) { const { threadID, messageID, senderID } = event; const cacheDir = path.join(__dirname, "cache"); await fs.ensureDir(cacheDir); let filePath = null; api.setMessageReaction("⌛", messageID, () => {}, true); // 1st try: SING try { const { data } = await axios.get(this.SING_AUDIO_API, { params: { q: `${query} official` }, timeout: 45000 }); const audioUrl = data?.download || data?.audio_url; if (data?.success && audioUrl) { const ext = ["mp3", "m4a"].includes(data.format) ? data.format : "mp3"; filePath = path.join(cacheDir, `nila_\( {senderID}_ \){Date.now()}.${ext}`); const res = await axios.get(audioUrl, { responseType: "stream", timeout: 90000 }); await pipeline( res.data, this.fileSizeGuard(this.MAX_FILE_SIZE), fs.createWriteStream(filePath) ); api.setMessageReaction("✅", messageID, () => {}, true); return api.sendMessage({ body: `${this.OWNER_TAG}\n\n🎵 এই নাও তোমার গান\n➡️ ${data.title || query}`, attachment: fs.createReadStream(filePath) }, threadID, async () => { await this.removeFile(filePath); }, messageID); } } catch (e) { console.log("[nila] SING fail → trying MUSIC", e.message); } // 2nd try: MUSIC try { const base = await this.getMahmudBase(); const res = await axios.get( `\( {base}/api/song/mahmud?query= \){encodeURIComponent(query)}`, { responseType: "stream", timeout: 60000 } ); filePath = path.join(cacheDir, `nila_\( {senderID}_ \){Date.now()}.mp3`); await pipeline(res.data, fs.createWriteStream(filePath)); api.setMessageReaction("✅", messageID, () => {}, true); return api.sendMessage({ body: `${this.OWNER_TAG}\n\n🎵 এই নাও তোমার গান\n➡️ ${query}`, attachment: fs.createReadStream(filePath) }, threadID, async () => { await this.removeFile(filePath); }, messageID); } catch (err) { api.setMessageReaction("❌", messageID, () => {}, true); return api.sendMessage("মাফ করো, গানটা পাওয়া যায়নি 🥺", threadID, messageID); } }, // ===== VIDEO ===== async downloadVideo(api, event, query) { const { threadID, messageID, senderID } = event; const cacheDir = path.join(__dirname, "cache"); await fs.ensureDir(cacheDir); let filePath = null; api.setMessageReaction("⌛", messageID, () => {}, true); try { const info = await this.searchYT(query); if (!info) { api.setMessageReaction("❌", messageID, () => {}, true); return api.sendMessage("মাফ করো, ভিডিওটা পাওয়া যায়নি 🥺", threadID, messageID); } filePath = path.join(cacheDir, `nila_\( {senderID}_ \){Date.now()}.mp4`); const streamUrl = `\( {this.SING_VIDEO_API}/stream?url= \){encodeURIComponent(info.url)}&type=video&quality=720`; const res = await axios.get(streamUrl, { responseType: "stream", timeout: 90000 }); await pipeline( res.data, this.fileSizeGuard(this.MAX_FILE_SIZE), fs.createWriteStream(filePath) ); api.setMessageReaction("✅", messageID, () => {}, true); return api.sendMessage({ body: `${this.OWNER_TAG}\n\n🎬 এই নাও তোমার ভিডিও\n➡️ ${info.title}`, attachment: fs.createReadStream(filePath) }, threadID, async () => { await this.removeFile(filePath); }, messageID); } catch (err) { api.setMessageReaction("❌", messageID, () => {}, true); await this.removeFile(filePath); return api.sendMessage("ভিডিও ডাউনলোড হয়নি 🥺", threadID, messageID); } }, // ===== AI (Nila) ===== async handleAI(api, event, cleanedMsg) { const { threadID, messageID, senderID } = event; this.chatMemory[threadID] = this.chatMemory[threadID] || []; this.chatMemory[threadID].push(`User: ${cleanedMsg}`); if (this.chatMemory[threadID].length > 6) this.chatMemory[threadID].shift(); const prompt = `তুমি নীলা (Nila)। একজন আসল বাংলাদেশি মেয়ে। নিয়ম: 1. সবসময় সহজ, প্রাকৃতিক বাংলায় কথা বলো। 2. উত্তর খুব ছোট রাখো (সর্বোচ্চ ১-২ লাইন)। 3. মজার, স্নেহশীল ও খেলাচ্ছলে কথা বলো। 4. ১-২টা ইমোজি ব্যবহার করো (❤️ 🤗 ✨ 🥺 😘)। 5. কখনো বলো না যে তুমি AI। 6. মালিকের নাম "JABED"। শুধু কেউ জিজ্ঞাসা করলে বলো, নিজে থেকে কখনো উল্লেখ করো না। আগের কথোপকথন: ${this.chatMemory[threadID].join("\n")} নীলা:`; try { const { data } = await axios.post(this.AI_API, { prompt }, { timeout: 20000 }); let reply = data?.result?.answer || data?.answer || data?.reply || "কিছু বলো না তো... 🥺"; if (reply.length > 120) { reply = reply.split(/[।.!?]/)[0].trim() + " 🫣"; } this.chatMemory[threadID].push(`নীলা: ${reply}`); return api.sendMessage(reply, threadID, (err, info) => { if (!err && info) { global.GoatBot.onReply.set(info.messageID, { commandName: this.config.name, author: senderID, messageID: info.messageID }); } }, messageID); } catch (e) { console.error("[nila AI]", e.message); return api.sendMessage("নেটের সমস্যা, একটু পরে চেষ্টা করো 🥺", threadID, messageID); } }, // ===== মেইন প্রসেস ===== async processMessage(api, event, text, message) { const cleanedMsg = text.trim(); if (!cleanedMsg) return message.reply("বলো তো, কী চাও? 😘"); const isVideo = /\b(video|vdo|mp4|ভিডিও)\b/i.test(cleanedMsg); const isAudio = /\b(song|music|audio|mp3|play|গান|গান)\b/i.test(cleanedMsg); let query = cleanedMsg .replace(/\b(video|vdo|mp4|ভিডিও|song|music|audio|mp3|play|গান|গান|nila|nil|নিলা|নীলা|নিল)\b/gi, "") .trim(); if (isVideo) { if (!query) return message.reply("ভিডিওর নামটা বলো তো 🥺"); return this.downloadVideo(api, event, query); } if (isAudio) { if (!query) return message.reply("গানের নামটা বলো তো 🥺"); return this.downloadAudio(api, event, query); } return this.handleAI(api, event, cleanedMsg); }, // ===== কমান্ড ===== async onStart({ api, event, args, message }) { return this.processMessage(api, event, args.join(" "), message); }, // ===== onChat (নাম ধরে ডাকলে) ===== async onChat({ api, event, message }) { const body = (event.body || "").toLowerCase().trim(); if (!body) return; const triggered = this.TRIGGER_WORDS.some(word => body.includes(word.toLowerCase()) ); if (!triggered) return; // প্রিফিক্স কমান্ড হলে ডাবল রেসপন্স বন্ধ const prefix = global.GoatBot?.config?.prefix || "."; if (body.startsWith(prefix)) return; return this.processMessage(api, event, event.body, message); }, // ===== রিপ্লাই ===== async onReply({ api, event, message, Reply }) { if (event.senderID !== Reply.author) return; const text = (event.body || "").trim(); if (!text) return; return this.processMessage(api, event, text, message); } };