// code from goatstore // api: https://store.agi.bd const axios = require("axios"); /* ───────────── সেটিংস ───────────── */ const MAX_TURNS = 12; // কতগুলো মেসেজ মনে রাখবে const MAX_CHARS = 1800; // Messenger-এ এক মেসেজের সীমা (বড় হলে ভাগ করে পাঠাবে) const TIMEOUT = 40000; // প্রতি সার্ভারের জন্য অপেক্ষা (ms) const RETRIES = 2; // প্রতি সার্ভারে আবার চেষ্টা const TZ = "Asia/Dhaka"; // ফ্রি মডেলের তালিকা (API key লাগে না) — একটা ব্যর্থ হলে পরেরটা চেষ্টা করবে const MODELS = ["openai", "openai-large", "mistral", "llama", "deepseek"]; const memory = new Map(); // থ্রেড+ইউজার অনুযায়ী কথোপকথন const busy = new Set(); // একই ইউজারের একসাথে দুইবার প্রশ্ন আটকাতে function systemPrompt() { const now = new Date().toLocaleString("en-GB", { timeZone: TZ, dateStyle: "full", timeStyle: "short" }); return ( "You are Claude-style AI assistant inside a Messenger chat bot. " + "You are knowledgeable, honest, friendly and helpful across every topic: general knowledge, " + "science, math, coding (any language), writing, translation, study help, advice, ideas, jokes, and casual chat. " + "Always reply in the same language the user writes in (Bangla, English, Banglish, Hindi etc). " + "Give accurate, complete answers. For code, put it in a plain code block and explain briefly. " + "If you are unsure or don't know, say so instead of making things up. " + "Do not use markdown headings or tables; short lists and plain text are fine. " + `Current date/time (Bangladesh): ${now}.` ); } /* ───────────── সার্ভার কল ───────────── */ const sleep = ms => new Promise(r => setTimeout(r, ms)); function clean(text) { if (!text) return ""; let t = String(text).trim(); // কিছু সার্ভার JSON/এরর টেক্সট ফেরত দেয় — সেগুলো বাদ if (/^\{\s*"error"/i.test(t)) return ""; if (/^( m.role === "system")?.content || ""; const convo = messages .filter(m => m.role !== "system") .slice(-6) .map(m => `${m.role === "user" ? "User" : "Assistant"}: ${typeof m.content === "string" ? m.content : "[image]"}`) .join("\n"); const url = "https://text.pollinations.ai/" + encodeURIComponent(convo.slice(-3500) + "\nAssistant:") + "?model=" + model + "&system=" + encodeURIComponent(sys.slice(0, 700)); const res = await axios.get(url, { timeout: TIMEOUT, responseType: "text" }); return clean(res.data); } async function askAI(messages, hasImage) { const models = hasImage ? ["openai", "openai-large"] : MODELS; // ছবির জন্য শুধু vision মডেল for (const model of models) { for (let i = 0; i <= RETRIES; i++) { try { const out = await callPost(model, messages); if (out) return out; } catch (e) { const code = e.response?.status; if (code === 400 || code === 404) break; // এই মডেল কাজ করবে না, পরেরটায় যাও } await sleep(800 * (i + 1)); } if (!hasImage) { try { const out = await callGet(model, messages); if (out) return out; } catch (e) {} } } throw new Error("ALL_FAILED"); } /* ───────────── মেসেজ ভাগ করা ───────────── */ function splitText(text, size = MAX_CHARS) { const parts = []; let rest = text; while (rest.length > size) { let cut = rest.lastIndexOf("\n", size); if (cut < size * 0.5) cut = rest.lastIndexOf(" ", size); if (cut < size * 0.5) cut = size; parts.push(rest.slice(0, cut).trim()); rest = rest.slice(cut).trim(); } if (rest) parts.push(rest); return parts; } /* ───────────── মূল হ্যান্ডলার ───────────── */ const keyOf = e => `${e.threadID}_${e.senderID}`; function getImageUrl(event) { const lists = [event.attachments, event.messageReply?.attachments]; for (const list of lists) { if (!Array.isArray(list)) continue; const img = list.find(a => a.type === "photo" || a.type === "animated_image" || a.type === "sticker"); if (img?.url) return img.url; } return null; } function react(api, emoji, event) { try { api.setMessageReaction(emoji, event.messageID, () => {}, true); } catch (e) {} } async function sendParts(message, parts, commandName, author) { for (let i = 0; i < parts.length; i++) { const body = parts.length > 1 ? `${parts[i]}\n\n(${i + 1}/${parts.length})` : parts[i]; await new Promise(resolve => { message.reply(body, (err, info) => { // শেষ অংশে রিপ্লাই দিলে কথা চলবে if (!err && info && i === parts.length - 1) { global.GoatBot.onReply.set(info.messageID, { commandName, author, messageID: info.messageID }); } resolve(); }); }); } } async function handle({ api, event, message, prompt, commandName }) { const k = keyOf(event); if (busy.has(k)) return message.reply("⏳ আগের প্রশ্নের উত্তর তৈরি হচ্ছে, একটু অপেক্ষা করো।"); busy.add(k); react(api, "⏳", event); try { api.sendTypingIndicator(event.threadID, () => {}); } catch (e) {} const past = memory.get(k) || []; const imageUrl = getImageUrl(event); // ছবি থাকলে vision ফরম্যাটে পাঠানো const userContent = imageUrl ? [ { type: "text", text: prompt || "Describe this image in detail." }, { type: "image_url", image_url: { url: imageUrl } } ] : prompt; try { const messages = [{ role: "system", content: systemPrompt() }, ...past.slice(-MAX_TURNS), { role: "user", content: userContent }]; const answer = await askAI(messages, !!imageUrl); // মেমোরিতে ছবির লিংক না রেখে টেক্সট রাখা (যাতে পরের কল হালকা থাকে) past.push({ role: "user", content: imageUrl ? `[image attached] ${prompt}` : prompt }); past.push({ role: "assistant", content: answer }); memory.set(k, past.slice(-MAX_TURNS)); react(api, "✅", event); await sendParts(message, splitText(answer), commandName, event.senderID); } catch (e) { react(api, "❌", event); message.reply("❌ এই মুহূর্তে AI সার্ভার ব্যস্ত। ১০–২০ সেকেন্ড পর আবার চেষ্টা করো।"); } finally { busy.delete(k); } } /* ───────────── কমান্ড ───────────── */ module.exports = { config: { name: "claude", aliases: ["cl", "ai2"], version: "2.0", author: "Zihad", countDown: 3, role: 0, description: { en: "Full AI chat — ask anything (no API key needed)", bn: "পূর্ণ AI চ্যাট — যা খুশি জিজ্ঞেস করো (API key লাগে না)" }, category: "ai", guide: { en: "{pn} — ask anything\n" + "{pn} (reply to a photo) — ask about an image\n" + "{pn} clear — reset your conversation\n" + "Reply to the bot's answer to continue chatting", bn: "{pn} <প্রশ্ন> — যা খুশি জিজ্ঞেস করো\n" + "ছবিতে রিপ্লাই দিয়ে {pn} <প্রশ্ন> — ছবি সম্পর্কে জিজ্ঞেস\n" + "{pn} clear — কথোপকথন রিসেট\n" + "বটের উত্তরে রিপ্লাই দিলে কথা চলবে" } }, onStart: async function ({ api, event, args, message, commandName }) { try { const input = args.join(" ").trim(); const replied = event.messageReply?.body || ""; const hasImage = !!getImageUrl(event); if (!input && !replied && !hasImage) { return message.reply( "╭───「 CLAUDE AI 」\n" + "│ 💬 claude <তোমার প্রশ্ন>\n" + "│ 🖼️ ছবিতে রিপ্লাই দিয়ে: claude এটা কি?\n" + "│ 🧹 claude clear — রিসেট\n" + "│ ↩️ উত্তরে রিপ্লাই দিলে কথা চলবে\n" + "╰────────────" ); } if (["clear", "reset", "new"].includes(input.toLowerCase())) { memory.delete(keyOf(event)); return message.reply("🧹 কথোপকথন রিসেট হয়েছে।"); } let prompt = input; if (replied && input) prompt = `(Replied message: "${replied.slice(0, 1500)}")\n${input}`; else if (replied && !input) prompt = replied; return await handle({ api, event, message, prompt, commandName }); } catch (e) { return message.reply("❌ কিছু একটা সমস্যা হয়েছে, আবার চেষ্টা করো।"); } }, onReply: async function ({ api, event, message, Reply, commandName }) { try { if (event.senderID !== Reply.author) return; const prompt = (event.body || "").trim(); if (!prompt && !getImageUrl(event)) return; return await handle({ api, event, message, prompt, commandName }); } catch (e) { return message.reply("❌ কিছু একটা সমস্যা হয়েছে, আবার চেষ্টা করো।"); } } };