goat
command
match
No description
0
views
0
likes
0
installs
raw source
const fs = require("fs-extra");
const path = require("path");
const axios = require("axios");
const { createCanvas, loadImage, registerFont } = require("canvas");
module.exports = {
config: {
name: "match",
version: "2.0",
author: "PROTIK SHAH",
countDown: 10,
role: 0,
description: {
bn: "লোকাল ক্যানভাস ব্যবহার করে পারফেক্ট ম্যাচ কার্ড তৈরি করুন",
en: "Find your match with local canvas image rendering",
vi: "Tìm mảnh ghép hoàn hảo bằng Local Canvas"
},
category: "love",
guide: {
bn: ' {pn}: আপনার ম্যাচ কার্ড তৈরি করতে ব্যবহার করুন',
en: ' {pn}: Use to generate your local pair match card',
vi: ' {pn}: Sử dụng để tạo thẻ ghép đôi'
}
},
langs: {
bn: {
noGender: "× বেবি, আপনার জেন্ডার প্রোফাইলে সেট করা নেই",
noMatch: "× দুঃখিত, এই গ্রুপে আপনার জন্য কোনো বিপরীত লিঙ্গের ম্যাচ পাওয়া যায়নি",
success: "💞 𝐒𝐮𝐜𝐜𝐞𝐬𝐬𝐟𝐮𝐥 𝐏𝐚𝐢𝐫𝐢𝐧𝐠\n• %1\n• %2\n\n𝐋𝐨𝐯𝐞 𝐏𝐞𝐫𝐜𝐞𝐧𝐭𝐚𝐠𝐞: %3%",
error: "× সমস্যা হয়েছে: %1"
},
en: {
noGender: "× Baby, your gender is not defined in your profile",
noMatch: "× Sorry, no match found for you in this group",
success: "💞 𝐒𝐮𝐜𝐜𝐞𝐬𝐬𝐟𝐮𝐥 𝐏𝐚𝐢𝐫𝐢𝐧𝐠\n• %1\n• %2\n\n𝐋𝐨𝐯𝐞 𝐏𝐞𝐫𝐜𝐞𝐧𝐭𝐚𝐠𝐞: %3%",
error: "× Error: %1"
}
},
onStart: async function ({ api, event, message, getLang }) {
const outputPath = path.join(__dirname, "cache", `pair_${event.senderID}_${Date.now()}.png`);
if (!fs.existsSync(path.dirname(outputPath))) fs.mkdirSync(path.dirname(outputPath), { recursive: true });
try {
api.setMessageReaction("😽", event.messageID, () => {}, true);
const threadData = await api.getThreadInfo(event.threadID);
const users = threadData.userInfo;
const myData = users.find((u) => u.id === event.senderID);
if (!myData || !myData.gender) return message.reply(getLang("noGender"));
const myGender = myData.gender.toUpperCase();
let matchCandidates = [];
if (myGender === "MALE") {
matchCandidates = users.filter((u) => u.gender === "FEMALE" && u.id !== event.senderID);
} else if (myGender === "FEMALE") {
matchCandidates = users.filter((u) => u.gender === "MALE" && u.id !== event.senderID);
} else {
matchCandidates = users.filter((u) => u.id !== event.senderID);
}
if (matchCandidates.length === 0) {
api.setMessageReaction("🥺", event.messageID, () => {}, true);
return message.reply(getLang("noMatch"));
}
const selectedMatch = matchCandidates[Math.floor(Math.random() * matchCandidates.length)];
const name1 = myData.name || "User 1";
const name2 = selectedMatch.name || "User 2";
const matchPercentage = Math.floor(Math.random() * 51) + 50; // ৫০% থেকে ১০০% এর মধ্যে
// প্রোফাইল পিকচার ডাউনলোড ফাংশন
const getAvatarBuffer = async (uid) => {
const avatarUrl = `https://graph.facebook.com/${uid}/picture?height=500&width=500&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`;
const res = await axios.get(avatarUrl, { responseType: "arraybuffer" });
return Buffer.from(res.data);
};
const [avatar1Buf, avatar2Buf] = await Promise.all([
getAvatarBuffer(event.senderID),
getAvatarBuffer(selectedMatch.id)
]);
// --- 🎨 Canvas ইমেজিং কোড শুরু ---
const width = 1000;
const height = 562;
const canvas = createCanvas(width, height);
const ctx = canvas.getContext("2d");
// ১. ব্যাকগ্রাউন্ড গ্রেডিয়েন্ট ও নোড পার্টিকেল তৈরি
const bgGradient = ctx.createLinearGradient(0, 0, width, height);
bgGradient.addColorStop(0, "#2c023d");
bgGradient.addColorStop(0.5, "#6b1178");
bgGradient.addColorStop(1, "#d91e63");
ctx.fillStyle = bgGradient;
ctx.fillRect(0, 0, width, height);
// সূক্ষ্ম স্টারি ফিল্টার / ডট ট্রায়াঙ্গেল
ctx.fillStyle = "rgba(255, 255, 255, 0.2)";
for (let i = 0; i < 40; i++) {
const rx = Math.random() * width;
const ry = Math.random() * height;
const rsize = Math.random() * 3 + 1;
ctx.beginPath();
ctx.arc(rx, ry, rsize, 0, Math.PI * 2);
ctx.fill();
}
// ২. মেইন ট্রান্সপারেন্ট গ্লাস কার্ড (Glassmorphism Effect)
ctx.save();
ctx.fillStyle = "rgba(255, 255, 255, 0.08)";
ctx.strokeStyle = "rgba(255, 255, 255, 0.25)";
ctx.lineWidth = 2;
const rectX = 70, rectY = 80, rectW = 860, rectH = 400, cornerRadius = 25;
ctx.beginPath();
ctx.roundRect(rectX, rectY, rectW, rectH, cornerRadius);
ctx.fill();
ctx.stroke();
ctx.restore();
// ৩. টাইটেল ও সাব-টাইটেল টেক্সট
ctx.textAlign = "center";
ctx.fillStyle = "#FFFFFF";
ctx.font = "bold 38px sans-serif";
ctx.fillText("PERFECT MATCH", width / 2, 135);
ctx.fillStyle = "#E0C3FC";
ctx.font = "italic 18px sans-serif";
ctx.fillText("Two hearts, one connection", width / 2, 168);
// ৪. কানেক্টিং আর্চ লাইন ও ডটস (Connecting Curved Line)
ctx.save();
ctx.beginPath();
ctx.strokeStyle = "#FF3366";
ctx.lineWidth = 4;
ctx.moveTo(340, 250);
ctx.quadraticCurveTo(width / 2, 200, 660, 250);
ctx.stroke();
// পয়েন্ট ডটস
const dotsX = [340, 420, 500, 580, 660];
dotsX.forEach((dx, idx) => {
ctx.beginPath();
ctx.fillStyle = idx === 2 ? "#FF0055" : (idx % 2 === 0 ? "#FF3366" : "#8A2BE2");
const dy = idx === 2 ? 225 : (idx === 1 || idx === 3 ? 232 : 250);
ctx.arc(dx, dy, idx === 2 ? 10 : 7, 0, Math.PI * 2);
ctx.fill();
});
ctx.restore();
// ৫. প্রোফাইল পিকচার ড্রয়িং ফাংশন (Circular Crop with Border)
const drawCircularAvatar = async (imgBuffer, x, y, radius, borderColor) => {
const img = await loadImage(imgBuffer);
ctx.save();
// বর্ডার
ctx.beginPath();
ctx.arc(x, y, radius + 6, 0, Math.PI * 2);
ctx.fillStyle = borderColor;
ctx.fill();
// ক্লিপিং সার্কেল
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.clip();
ctx.drawImage(img, x - radius, y - radius, radius * 2, radius * 2);
ctx.restore();
};
const avatarY = 260;
const avatarRadius = 80;
await drawCircularAvatar(avatar1Buf, 240, avatarY, avatarRadius, "#E040FB");
await drawCircularAvatar(avatar2Buf, 760, avatarY, avatarRadius, "#9C27B0");
// ৬. ইউজারদের নাম
ctx.fillStyle = "#FFFFFF";
ctx.font = "bold 26px sans-serif";
ctx.textAlign = "center";
// নাম লম্বা হলে ট্রিম করে দেওয়া
const trimText = (txt) => txt.length > 13 ? txt.substring(0, 11) + ".." : txt;
ctx.fillText(trimText(name1), 240, 385);
ctx.fillText(trimText(name2), 760, 385);
// ৭. পার্সেন্টেজ রিং অ্যান্ড টেক্সট (Percentage Ring Indicator)
const ringX = width / 2;
const ringY = 350;
const ringRadius = 55;
// ব্যাকগ্রাউন্ড ট্র্যাক রিং
ctx.beginPath();
ctx.arc(ringX, ringY, ringRadius, 0, Math.PI * 2);
ctx.strokeStyle = "rgba(255, 255, 255, 0.15)";
ctx.lineWidth = 12;
ctx.stroke();
// প্রোগ্রেস আর্চ রিং
const startAngle = -Math.PI / 2;
const endAngle = startAngle + (Math.PI * 2 * (matchPercentage / 100));
const ringGrad = ctx.createLinearGradient(ringX - ringRadius, ringY, ringX + ringRadius, ringY);
ringGrad.addColorStop(0, "#FF007F");
ringGrad.addColorStop(1, "#7B2CBF");
ctx.beginPath();
ctx.arc(ringX, ringY, ringRadius, startAngle, endAngle);
ctx.strokeStyle = ringGrad;
ctx.lineWidth = 12;
ctx.lineCap = "round";
ctx.stroke();
// পার্সেন্টেজ টেক্সট
ctx.fillStyle = "#FFFFFF";
ctx.font = "bold 28px sans-serif";
ctx.fillText(`${matchPercentage}%`, ringX, ringY + 9);
ctx.fillStyle = "#D8B4FE";
ctx.font = "bold 18px sans-serif";
ctx.fillText("MATCH", ringX, ringY + 80);
// --- 🎨 Canvas ইমেজিং শেষ ---
// ইমেজ ক্যাশ ফাইল সেভ
const buffer = canvas.toBuffer("image/png");
fs.writeFileSync(outputPath, buffer);
return message.reply({
body: getLang("success", name1, name2, matchPercentage),
attachment: fs.createReadStream(outputPath)
}, () => {
api.setMessageReaction("✅", event.messageID, () => {}, true);
if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath);
});
} catch (err) {
console.error("Local Pair Canvas Error:", err);
api.setMessageReaction("❌", event.messageID, () => {}, true);
if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath);
return message.reply(getLang("error", err.message));
}
}
};