// code from goatstore // api: https://store.agi.bd const axios = require("axios"); const simsim = "https://rx.agi.bd/fun"; const triggerLocks = new Set(); async function sendTypingIndicatorV2(api, sendTyping, threadID) { try { if (typeof api.sendTypingIndicator === "function") { await api.sendTypingIndicator(threadID, sendTyping); } } catch (err) { console.log("โš ๏ธ Typing indicator error:", err.message); } } let botUID = null; function getBotUID(api) { if (botUID) return botUID; try { if (typeof api.getCurrentUserID === "function") { botUID = api.getCurrentUserID(); } } catch {} return botUID; } async function simsimiRequest(pathFn, options = {}) { const { method = "get", data = null, timeout = 15000 } = options; const url = pathFn(simsim); return method === "post" ? await axios.post(url, data, { timeout }) : await axios.get(url, { timeout }); } module.exports.config = { name: "baby", version: "4.2.0", role: 0, author: "rX", countTime: 0, category: "chat", shortDescription: "AI auto teach chat (Simsimi-style)", longDescription: "AI auto teach with Teach & List support + Typing effect", guide: "{pn} [query]\n{pn} list\n{pn} teach [Question] - [Reply]\n{pn} react [Question] - [Emoji]\n{pn} edit [Question] - [OldReply] - [NewReply]\n{pn} remove/rm [Question] - [Reply]\n{pn} del (reply to bot's wrong answer)\n{pn} msg [trigger]\n{pn} msg [trigger] -20 (custom show limit)\n{pn} autoteach on/off (per-thread)\n{pn} autoteach on/off global (all threads default)", aliases: ["maria", "hippi"], envConfig: {} }; async function getUserName(api, uid, usersData) { try { if (usersData && typeof usersData.getName === "function") { const name = await usersData.getName(uid); if (name) return name; } const info = await api.getUserInfo(uid); return (info && info[uid] && info[uid].name) || "User"; } catch { return "User"; } } module.exports.onStart = async function ({ api, event, args, usersData }) { const uid = event.senderID; const senderName = await getUserName(api, uid, usersData); const query = args.join(" ").toLowerCase(); try { if (args[0] === "autoteach") { const mode = args[1]; const scope = (args[2] || "").toLowerCase(); if (!["on", "off"].includes(mode)) return api.sendMessage("โœ… Use: baby autoteach on/off\nOr: baby autoteach on/off global", event.threadID, event.messageID); const status = mode === "on"; if (scope === "global") { await simsimiRequest((base) => `${base}/setting`, { method: "post", data: { autoTeach: status } }); return api.sendMessage(`โœ… Auto teach is now ${status ? "ON ๐ŸŸข" : "OFF ๐Ÿ”ด"} ๐†๐‹๐Ž๐๐€๐‹๐‹๐˜ (all threads without override)`, event.threadID, event.messageID); } const res = await simsimiRequest((base) => `${base}/setting`, { method: "post", data: { autoTeach: status, threadID: event.threadID } }); return api.sendMessage(`โœ… ${res.data.message} (๐ญ๐ก๐ข๐ฌ ๐ญ๐ก๐ซ๐ž๐š๐ ๐จ๐ง๐ฅ๐ฒ)`, event.threadID, event.messageID); } if (args[0] === "list") { const res = await simsimiRequest((base) => `${base}/list`); return api.sendMessage( `โ•ญโ”€โ•ผ๐ŸŒŸ ๐๐š๐›๐ฒ ๐€๐ˆ ๐’๐ญ๐š๐ญ๐ฎ๐ฌ\nโ”œ ๐Ÿ“ ๐“๐ž๐š๐œ๐ก๐ž๐ ๐๐ฎ๐ž๐ฌ๐ญ๐ข๐จ๐ง๐ฌ: ${res.data.totalQuestions}\nโ”œ ๐Ÿ“ฆ ๐’๐ญ๐จ๐ซ๐ž๐ ๐‘๐ž๐ฉ๐ฅ๐ข๐ž๐ฌ: ${res.data.totalReplies}\nโ•ฐโ”€โ•ผ๐Ÿ‘ค ๐ƒ๐ž๐ฏ๐ž๐ฅ๐จ๐ฉ๐ž๐ซ: ๐ซ๐— ๐€๐›๐๐ฎ๐ฅ๐ฅ๐š๐ก`, event.threadID, event.messageID ); } if (args[0] === "msg") { let trigger = args.slice(1).join(" ").trim(); if (!trigger) return api.sendMessage("โŒ | Use: !baby msg [trigger]\nOr: !baby msg [trigger] -20 (custom limit)", event.threadID, event.messageID); let customLimit = null; const limitMatch = trigger.match(/\s*-(\d+)\s*$/); if (limitMatch) { customLimit = parseInt(limitMatch[1], 10); trigger = trigger.replace(/\s*-(\d+)\s*$/, "").trim(); if (!trigger) return api.sendMessage("โŒ | Use: !baby msg [trigger] -20", event.threadID, event.messageID); } const res = await simsimiRequest((base) => `${base}/simsimi-list?ask=${encodeURIComponent(trigger)}`); if (!res.data.replies || res.data.replies.length === 0) return api.sendMessage("โŒ No replies found.", event.threadID, event.messageID); const REPLY_LIMIT = (customLimit && customLimit > 0) ? customLimit : 150; const allReplies = res.data.replies; const shownReplies = allReplies.slice(0, REPLY_LIMIT); const remaining = allReplies.length - shownReplies.length; const formatted = shownReplies.map((rep, i) => `โžค ${i + 1}. ${rep}`).join("\n"); const limitNote = remaining > 0 ? `\nโš ๏ธ ${REPLY_LIMIT} ๐ญ๐š ๐ซ๐ž๐ฉ๐ฅ๐ฒ ๐๐ž๐ค๐ก๐š๐ง๐จ ๐ก๐จ๐ฒ๐ž๐œ๐ก๐ž, ๐š๐ซ๐จ ${remaining} ๐ญ๐š ๐›๐š๐ค๐ข ๐š๐œ๐ก๐ž (๐๐ž๐ค๐ก๐š๐ง๐จ ๐ฃ๐š๐œ๐œ๐ก๐ž ๐ง๐š, ๐ญ๐š๐›๐ž ๐ค๐ข๐ฉ ๐ฌ๐ก๐ฎ๐›๐ก ๐ซ๐ž๐ฉ๐ฅ๐ข๐ซ ๐ฎ๐ฉ๐จ๐ซ ๐ค๐š๐ฃ ๐ค๐จ๐ซ๐›๐ž)เฅค\n` : ""; const msg = `๐Ÿ“Œ ๐—ง๐—ฟ๐—ถ๐—ด๐—ด๐—ฒ๐—ฟ: ${trigger.toUpperCase()}\n๐Ÿ“‹ ๐—ง๐—ผ๐˜๐—ฎ๐—น: ${res.data.total}\nโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n${formatted}\nโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”${limitNote}โœ๏ธ Reply with the numbers you want to KEEP (e.g. "2, 7") โ€” everything else will be removed.`; return api.sendMessage(msg, event.threadID, (err, info) => { if (!err) { global.GoatBot.onReply.set(info.messageID, { commandName: module.exports.config.name, messageID: info.messageID, author: event.senderID, type: "msgSelect", trigger }); } }, event.messageID); } if (args[0] === "teach") { const parts = query.replace("teach ", "").split(" - "); if (parts.length < 2) return api.sendMessage("โŒ | Use: teach [Question] - [Reply]", event.threadID, event.messageID); const [ask, ans] = parts; const res = await simsimiRequest((base) => `${base}/teach?ask=${encodeURIComponent(ask)}&ans=${encodeURIComponent(ans)}&senderID=${uid}&senderName=${encodeURIComponent(senderName)}`); return api.sendMessage(`โœ… ${res.data.message}`, event.threadID, event.messageID); } if (args[0] === "react") { const rawQuery = args.slice(1).join(" "); const parts = rawQuery.split(" - "); if (parts.length < 2) return api.sendMessage("โŒ | Use: react [Question] - [Emoji]", event.threadID, event.messageID); const [ask, emoji] = parts; if (!ask.trim() || !emoji.trim()) return api.sendMessage("โŒ | Use: react [Question] - [Emoji]", event.threadID, event.messageID); const res = await simsimiRequest((base) => `${base}/teachReact?ask=${encodeURIComponent(ask)}&emoji=${encodeURIComponent(emoji)}&senderName=${encodeURIComponent(senderName)}`); return api.sendMessage(`โœ… ${res.data.message}`, event.threadID, event.messageID); } if (args[0] === "edit") { const parts = query.replace("edit ", "").split(" - "); if (parts.length < 3) return api.sendMessage("โŒ | Use: edit [Question] - [OldReply] - [NewReply]", event.threadID, event.messageID); const [ask, oldR, newR] = parts; const res = await simsimiRequest((base) => `${base}/edit?ask=${encodeURIComponent(ask)}&old=${encodeURIComponent(oldR)}&new=${encodeURIComponent(newR)}`); return api.sendMessage(res.data.message, event.threadID, event.messageID); } if (["remove", "rm"].includes(args[0])) { const parts = query.replace(/^(remove|rm)\s*/, "").split(" - "); if (parts.length < 2) return api.sendMessage("โŒ | Use: remove [Question] - [Reply]", event.threadID, event.messageID); const [ask, ans] = parts; const res = await simsimiRequest((base) => `${base}/delete?ask=${encodeURIComponent(ask)}&ans=${encodeURIComponent(ans)}`); return api.sendMessage(res.data.message, event.threadID, event.messageID); } if (args[0] === "del") { return api.sendMessage( "โŒ | Reply to the bot's wrong answer message with \"!baby del\" to delete it.", event.threadID, event.messageID ); } if (!query) { const texts = ["Yes, I'm here ๐Ÿ˜˜"]; const reply = texts[Math.floor(Math.random() * texts.length)]; return api.sendMessage(reply, event.threadID); } return await deliverSimsimiResponse({ api, event, query, senderName }); } catch (e) { return api.sendMessage(`โŒ Error: ${e.message}`, event.threadID, event.messageID); } }; module.exports.onReply = async function ({ api, event, Reply, usersData }) { const senderName = await getUserName(api, event.senderID, usersData); const text = event.body?.trim(); const lowered = text?.toLowerCase(); if (event.attachments && event.attachments.length > 0) { const type = event.attachments[0].type; let reaction = null; if (type === "photo") reaction = "๐Ÿซฉ"; else if (type === "animated_image") reaction = "๐Ÿ˜ตโ€๐Ÿ’ซ"; else if (type === "video") reaction = "๐Ÿค”"; else if (type === "audio") reaction = "๐Ÿค•"; if (reaction) { try { await api.setMessageReaction(reaction, event.messageID, () => {}, true); } catch (e) { console.log("โš ๏ธ Attachment reaction error:", e.message); } return; } } if (!text) return; if (lowered === "del" || lowered === "!baby del") { try { const originalReply = Reply?.body; if (!originalReply) { return api.sendMessage("โŒ Couldn't read the original message to delete.", event.threadID, event.messageID); } const res = await simsimiRequest((base) => `${base}/deleteByReply?reply=${encodeURIComponent(originalReply)}`); return api.sendMessage(res.data.message, event.threadID, event.messageID); } catch (e) { return api.sendMessage(`โŒ Failed to delete: ${e.message}`, event.threadID, event.messageID); } } if (Reply?.type === "msgSelect") { if (event.senderID !== Reply.author) return; const numbers = text .split(",") .map(n => parseInt(n.trim(), 10)) .filter(n => Number.isInteger(n)); if (numbers.length === 0) { return api.sendMessage("โŒ Send numbers like: 2, 7", event.threadID, event.messageID); } try { const res = await simsimiRequest((base) => `${base}/keepOnly`, { method: "post", data: { ask: Reply.trigger, keepIndexes: numbers } }); return api.sendMessage(res.data.message, event.threadID, event.messageID); } catch (e) { return api.sendMessage(`โŒ Failed to update: ${e.message}`, event.threadID, event.messageID); } } try { return await deliverSimsimiResponse({ api, event, query: lowered, senderName }); } catch (e) { return api.sendMessage(`โŒ Error: ${e.message}`, event.threadID, event.messageID); } }; const greetingReplies = [ "๐€๐ฌ๐ฌ๐š๐ฅ๐š๐ฆ๐ฎ ๐ฐ๐š๐ฅ๐š๐ข๐ค๐ฎ๐ฆ โ™ฅ", "เฆฌเฆฒเง‡เฆจ sir__๐Ÿ˜Œ", "๐๐จ๐ฅ๐จ ๐ฃ๐š๐ง ๐ค๐ข ๐ค๐จ๐ซ๐ญ๐ž ๐ฉ๐š๐ซ๐ข ๐ญ๐จ๐ฆ๐ซ ๐ฃ๐จ๐ง๐ง๐จ ๐Ÿธ", "๐‹๐ž๐›๐ฎ ๐ค๐ก๐š๐ฐ ๐๐š๐ค๐ญ๐ž ๐๐š๐ค๐ญ๐ž ๐ญ๐จ ๐ก๐š๐ฉ๐š๐ฒ ๐ ๐ž๐ฌ๐จ", "๐†๐š๐ง๐ฃ๐š ๐ค๐ก๐š ๐ฆ๐š๐ง๐ฎ๐ฌ๐ก ๐ก๐จ ๐Ÿ", "๐‹๐ž๐ฆ๐จ๐ง ๐ญ๐ฎ๐ฌ ๐Ÿ‹", "เฆฎเงเฆกเฆผเฆฟ เฆ–เฆพเฆ“ ๐Ÿซฅ", ".__๐š๐ฆ๐ค๐ž ๐ฌ๐ž๐ซ๐ž ๐๐ž๐ฐ ๐š๐ฆ๐ข ๐š๐ฆ๐ฆ๐ฎ๐ซ ๐ค๐š๐ฌ๐ž ๐ฃ๐š๐›๐จ!!๐Ÿฅบ.....๐Ÿ˜—", "เฆฒเงเฆ™เงเฆ—เฆฟ เฆŸเฆพ เฆงเฆฐ เฆฎเงเฆคเง‡ เฆ†เฆธเฆฟ๐Ÿ™Š๐Ÿ™‰", "โ”€โ”€โ€Ž ๐‡๐ฎ๐Œ..? ๐Ÿ‘‰๐Ÿ‘ˆ", "เฆ†เฆฎ เฆ—เฆพเฆ›เง‡ เฆ†เฆฎ เฆจเฆพเฆ‡ เฆขเฆฟเฆฒ เฆ•เง‡เฆจ เฆฎเฆพเฆฐเง‹, เฆคเง‹เฆฎเฆพเฆฐ เฆธเฆพเฆฅเง‡ เฆชเงเฆฐเง‡เฆฎ เฆจเฆพเฆ‡ เฆฌเง‡เฆฌเฆฟ เฆ•เง‡เฆจ เฆกเฆพเฆ•เง‹ ๐Ÿ˜’๐Ÿธ", "เฆ•เฆฟ เฆนเฆฒเง‹, เฆฎเฆฟเฆธ เฆŸเฆฟเฆธ เฆ•เฆฐเฆšเงเฆ›เง‹ เฆจเฆพเฆ•เฆฟ ๐Ÿคฃ", "๐“๐ซ๐ฎ๐ฌ๐ญ ๐ฆ๐ž ๐ข๐š๐ฆ ๐ฆ๐š๐ซษช๐š ๐Ÿงƒ", "๐‡แด‡ส ๐—แด€ษด ๐ˆ'แด ๐Œ๐š๐ซษช๐š ๐๐š๐›๐ฒโœจ" ]; async function sendGreeting(api, event) { const reply = greetingReplies[Math.floor(Math.random() * greetingReplies.length)]; await sendTypingIndicatorV2(api, true, event.threadID); await new Promise(r => setTimeout(r, 5000)); await sendTypingIndicatorV2(api, false, event.threadID); return api.sendMessage(reply, event.threadID, (err, info) => { if (!err) { global.GoatBot.onReply.set(info.messageID, { commandName: module.exports.config.name, messageID: info.messageID, author: event.senderID, type: "simsimi" }); } }); } function withTimeout(promise, ms, label) { return Promise.race([ promise, new Promise((_, reject) => setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms) ) ]); } function sendMessageAsync(api, text, threadID, replyToID) { return new Promise((resolve, reject) => { const cb = (err, info) => (err ? reject(err) : resolve(info)); if (replyToID) { api.sendMessage(text, threadID, cb, replyToID); } else { api.sendMessage(text, threadID, cb); } }); } async function deliverSimsimiResponse({ api, event, query, senderName }) { await sendTypingIndicatorV2(api, true, event.threadID); let res; try { const minDelay = new Promise(r => setTimeout(r, 3000)); const apiCall = simsimiRequest((base) => `${base}/simsimi?text=${encodeURIComponent(query)}&senderName=${encodeURIComponent(senderName)}&threadID=${encodeURIComponent(event.threadID)}&senderID=${encodeURIComponent(event.senderID)}` ); [res] = await Promise.all([apiCall, minDelay]); } finally { await sendTypingIndicatorV2(api, false, event.threadID); } const data = res.data || {}; if (data.rateLimited) return; if (data.reaction && event.messageID) { withTimeout( api.setMessageReaction(data.reaction, event.messageID, () => {}, true), 3000, "setMessageReaction" ).catch(e => console.log("โš ๏ธ Reaction send error:", e.message)); } const replyText = data.response || data.result; if (replyText) { try { const info = await sendMessageAsync(api, replyText, event.threadID, event.messageID); global.GoatBot.onReply.set(info.messageID, { commandName: module.exports.config.name, messageID: info.messageID, author: event.senderID, type: "simsimi" }); } catch (e) { console.log("โŒ sendMessage error:", JSON.stringify(e)); try { const info2 = await sendMessageAsync(api, replyText, event.threadID); global.GoatBot.onReply.set(info2.messageID, { commandName: module.exports.config.name, messageID: info2.messageID, author: event.senderID, type: "simsimi" }); } catch (e2) { console.log("โŒ sendMessage failed after retry:", JSON.stringify(e2)); } } } } function isBotMentioned(event, uid) { if (!uid || !event.mentions) return false; return Object.prototype.hasOwnProperty.call(event.mentions, uid); } module.exports.onChat = async function ({ api, event, usersData }) { const text = event.body?.toLowerCase().trim(); const senderName = await getUserName(api, event.senderID, usersData); const triggers = ["baby", "bby", "bbz", "mari"]; const uid = getBotUID(api); if (isBotMentioned(event, uid)) { if (triggerLocks.has(event.threadID)) return; triggerLocks.add(event.threadID); try { return await sendGreeting(api, event); } finally { triggerLocks.delete(event.threadID); } } if (!text) return; if (triggers.includes(text)) { if (triggerLocks.has(event.threadID)) return; triggerLocks.add(event.threadID); try { return await sendGreeting(api, event); } finally { triggerLocks.delete(event.threadID); } } const matchPrefix = /^(baby|bby|bbz|mari)\s+/i; if (matchPrefix.test(text)) { const query = text.replace(matchPrefix, "").trim(); if (!query) return; if (triggerLocks.has(event.threadID)) return; triggerLocks.add(event.threadID); try { return await deliverSimsimiResponse({ api, event, query, senderName }); } catch (e) { return api.sendMessage(`โŒ Error: ${e.message}`, event.threadID, event.messageID); } finally { triggerLocks.delete(event.threadID); } } if (event.type === "message_reply") { try { const setting = await simsimiRequest((base) => `${base}/setting?threadID=${encodeURIComponent(event.threadID)}`); if (!setting.data.autoTeach) return; const ask = event.messageReply.body?.toLowerCase().trim(); const ans = event.body?.toLowerCase().trim(); if (!ask || !ans || ask === ans) return; setTimeout(async () => { try { await simsimiRequest((base) => `${base}/teach?ask=${encodeURIComponent(ask)}&ans=${encodeURIComponent(ans)}&senderName=${encodeURIComponent(senderName)}`); console.log("โœ… Auto-taught:", ask, "โ†’", ans, "(thread:", event.threadID + ")"); } catch (err) { console.error("โŒ Auto-teach internal error:", err.message); } }, 300); } catch (e) { console.log("โŒ Auto-teach setting error:", e.message); } } };