← back to browse
goat command

baby

AI auto teach chat (Simsimi-style)

2
views
0
likes
2
installs

Aliases: maria, hippi

raw source
const axios = require("axios");

let simsim = "";
// THIS CODE MADE BY RX @RX_ABDULLAH007

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);
  }
}

(async () => {
  try {
    const res = await axios.get("https://raw.githubusercontent.com/abdullahrx07/X-api/main/MaRiA/baseApiUrl.json");
    if (res.data && res.data.mari) simsim = res.data.mari;
  } catch {}
})();

let botUID = null;
function getBotUID(api) {
  if (botUID) return botUID;
  try {
    if (typeof api.getCurrentUserID === "function") {
      botUID = api.getCurrentUserID();
    }
  } catch {}
  return botUID;
}

module.exports.config = {
  name: "baby",
  version: "4.0.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 (!simsim) return api.sendMessage("❌ API not loaded yet.", event.threadID, event.messageID);

    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 axios.post(`${simsim}/setting`, { autoTeach: status });
        return api.sendMessage(`✅ Auto teach is now ${status ? "ON 🟢" : "OFF 🔴"} 𝐆𝐋𝐎𝐁𝐀𝐋𝐋𝐘 (all threads without override)`, event.threadID, event.messageID);
      }

      const res = await axios.post(`${simsim}/setting`, { autoTeach: status, threadID: event.threadID });
      return api.sendMessage(`✅ ${res.data.message} (𝐭𝐡𝐢𝐬 𝐭𝐡𝐫𝐞𝐚𝐝 𝐨𝐧𝐥𝐲)`, event.threadID, event.messageID);
    }

    if (args[0] === "list") {
      const res = await axios.get(`${simsim}/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 axios.get(`${simsim}/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 axios.get(`${simsim}/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 axios.get(`${simsim}/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 axios.get(`${simsim}/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 axios.get(`${simsim}/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 = ["Hey baby 💖", "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 || !simsim) 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 axios.get(`${simsim}/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 axios.post(`${simsim}/keepOnly`, {
        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 }) {
  const url = `${simsim}/simsimi?text=${encodeURIComponent(query)}&senderName=${encodeURIComponent(senderName)}&threadID=${encodeURIComponent(event.threadID)}&senderID=${encodeURIComponent(event.senderID)}`;

  await sendTypingIndicatorV2(api, true, event.threadID);
  let res;
  try {
    res = await axios.get(url);
  } 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));
  }

  if (data.response) {
    try {
      const info = await sendMessageAsync(api, data.response, 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, data.response, 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();
  if (!simsim) return;

  const senderName = await getUserName(api, event.senderID, usersData);
  const triggers = ["baby", "bby", "xan", "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|xan|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 axios.get(`${simsim}/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 axios.get(`${simsim}/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);
    }
  }
};

View raw file