← back to browse
goat command

leave

Group Cover BG & Dynamic Leave/Kick Card

0
views
0
likes
0
installs
raw source
const { createCanvas, loadImage } = require("canvas");
const fs = require("fs-extra");
const path = require("path");
const moment = require("moment-timezone");

module.exports = {
  config: {
    name: "leave",
    version: "7.0.0",
    author: "Protik Shah",
    category: "events",
    description: "Group Cover BG & Dynamic Leave/Kick Card"
  },

  onStart: async function ({ api, event }) {
    if (event.logMessageType !== "log:unsubscribe") return;

    const { threadID, logMessageData, author } = event;
    const leftParticipantFbId = logMessageData.leftParticipantFbId;

    if (leftParticipantFbId === api.getCurrentUserID()) return;

    try {
      const threadInfo = await api.getThreadInfo(threadID);
      const threadName = threadInfo.threadName || "Diablo Realm";
      const memberCount = threadInfo.participantIDs.length;
      const groupIconUrl = threadInfo.imageSrc || "https://i.ibb.co/L5k6NvZ/bg2.jpg";

      const userInfo = await api.getUserInfo(leftParticipantFbId);
      const userName = userInfo[leftParticipantFbId]?.name || "Facebook user";

      // Detect Self Leave vs Kicked by Admin
      const isKicked = author && author !== leftParticipantFbId;
      const mainHeader = isKicked ? "MEMBER KICKED!" : "GOODBYE MEMBER!";
      const subTag = isKicked ? "๐Ÿšซ MEMBER REMOVED ๐Ÿšซ" : "๐Ÿฅ€ MEMBER DEPARTED ๐Ÿฅ€";
      const statusMsg = isKicked ? "Removed from group by Admin." : "Has left the group chat.";
      const timeNow = moment().tz("Asia/Dhaka").format("hh:mm A | DD MMM YYYY");

      const canvas = createCanvas(1000, 500);
      const ctx = canvas.getContext("2d");

      // 1. Group Cover Background with Blur
      try {
        const bgImg = await loadImage(groupIconUrl);
        ctx.filter = "blur(12px)";
        ctx.drawImage(bgImg, -20, -20, canvas.width + 40, canvas.height + 40);
        ctx.filter = "none";
      } catch (e) {
        ctx.fillStyle = "#140508";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }

      // Dark Overlay
      ctx.fillStyle = "rgba(20, 5, 8, 0.88)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      // Divider Line
      ctx.strokeStyle = "rgba(255, 42, 69, 0.25)";
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(420, 0);
      ctx.lineTo(420, 500);
      ctx.stroke();

      // 2. Avatar Rendering
      const targetAvatarUrl = `https://graph.facebook.com/${leftParticipantFbId}/picture?height=500&width=500&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`;

      if (!isKicked) {
        // Self Leave: Single Centered Avatar
        try {
          const targetImg = await loadImage(targetAvatarUrl);
          ctx.save();
          ctx.shadowColor = "#ff2a45";
          ctx.shadowBlur = 25;
          ctx.beginPath();
          ctx.arc(210, 200, 85, 0, Math.PI * 2);
          ctx.clip();
          ctx.drawImage(targetImg, 125, 115, 170, 170);
          ctx.restore();

          ctx.strokeStyle = "#ff2a45";
          ctx.lineWidth = 4;
          ctx.beginPath();
          ctx.arc(210, 200, 85, 0, Math.PI * 2);
          ctx.stroke();
        } catch (e) {}
      } else {
        // Kicked: Dual Avatar (Admin + Kicked User)
        const adminAvatarUrl = `https://graph.facebook.com/${author}/picture?height=500&width=500&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`;

        try {
          const adminImg = await loadImage(adminAvatarUrl);
          ctx.save();
          ctx.beginPath();
          ctx.arc(150, 200, 60, 0, Math.PI * 2);
          ctx.clip();
          ctx.drawImage(adminImg, 90, 140, 120, 120);
          ctx.restore();

          ctx.strokeStyle = "#ffffff";
          ctx.lineWidth = 3;
          ctx.beginPath();
          ctx.arc(150, 200, 60, 0, Math.PI * 2);
          ctx.stroke();
        } catch (e) {}

        try {
          const targetImg = await loadImage(targetAvatarUrl);
          ctx.save();
          ctx.shadowColor = "#ff2a45";
          ctx.shadowBlur = 20;
          ctx.beginPath();
          ctx.arc(260, 200, 70, 0, Math.PI * 2);
          ctx.clip();
          ctx.drawImage(targetImg, 190, 130, 140, 140);
          ctx.restore();

          ctx.strokeStyle = "#ff2a45";
          ctx.lineWidth = 4;
          ctx.beginPath();
          ctx.arc(260, 200, 70, 0, Math.PI * 2);
          ctx.stroke();
        } catch (e) {}
      }

      // Sub Text
      ctx.fillStyle = "#ff2a45";
      ctx.font = "bold 18px 'Segoe UI', Sans-serif";
      ctx.textAlign = "center";
      ctx.fillText(subTag, 210, 350);

      // 3. Right Panel Content
      ctx.textAlign = "left";

      ctx.fillStyle = "#ffffff";
      ctx.font = "900 38px 'Segoe UI', Sans-serif";
      ctx.fillText(mainHeader, 460, 110);

      ctx.fillStyle = "#ff2a45";
      ctx.font = "bold 28px 'Segoe UI', Sans-serif";
      ctx.fillText(userName, 460, 160);

      // Strip 1: Action Status
      ctx.fillStyle = "rgba(255, 42, 69, 0.15)";
      ctx.beginPath();
      ctx.roundRect(460, 195, 480, 50, 12);
      ctx.fill();

      ctx.fillStyle = "#ffffff";
      ctx.font = "18px 'Segoe UI', Sans-serif";
      ctx.fillText(statusMsg, 480, 227);

      // Strip 2: Group Name
      ctx.fillStyle = "rgba(255, 42, 69, 0.15)";
      ctx.beginPath();
      ctx.roundRect(460, 265, 480, 50, 12);
      ctx.fill();

      ctx.fillStyle = "#ff2a45";
      ctx.font = "bold 18px 'Segoe UI', Sans-serif";
      ctx.fillText(`GROUP: ${threadName}`, 480, 297);

      // Badges
      ctx.fillStyle = "#ff2a45";
      ctx.beginPath();
      ctx.roundRect(460, 355, 210, 48, 12);
      ctx.fill();

      ctx.fillStyle = "#ffffff";
      ctx.font = "bold 18px 'Segoe UI', Sans-serif";
      ctx.fillText(`REMAINING: ${memberCount}`, 480, 385);

      ctx.fillStyle = "#221115";
      ctx.beginPath();
      ctx.roundRect(690, 355, 250, 48, 12);
      ctx.fill();

      ctx.fillStyle = "#a0aec0";
      ctx.font = "15px 'Segoe UI', Sans-serif";
      ctx.fillText(timeNow, 705, 384);

      const cardPath = path.join(__dirname, `cache_leave_${leftParticipantFbId}.png`);
      fs.writeFileSync(cardPath, canvas.toBuffer("image/png"));

      api.sendMessage(
        {
          body: isKicked ? `๐Ÿšซ ${userName} was removed from ${threadName}.` : `๐Ÿ’” ${userName} has left ${threadName}.`,
          attachment: fs.createReadStream(cardPath)
        },
        threadID,
        () => {
          if (fs.existsSync(cardPath)) fs.unlinkSync(cardPath);
        }
      );
    } catch (err) {
      console.error("Leave Error:", err);
    }
  }
};

View raw file