goat
command
nila
No description
0
views
0
likes
0
installs
Aliases: nil, নিল, নীলা
raw source
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} <message>\n{pn} song/play <name>\n{pn} video/vdo <name>",
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);
}
};