goat
command
pair
๐ Find your perfect match
0
views
0
likes
0
installs
raw source
const { createCanvas, loadImage } = require("canvas");
const fs = require("fs");
const path = require("path");
const axios = require("axios");
module.exports = {
config: {
name: "pair",
author: "Azadx69x",
version: "0.0.7",
role: 0,
category: "love",
shortDescription: {
en: "๐ Find your perfect match"
},
longDescription: {
en: "Discover your love compatibility with group members"
},
guide: {
en: "{p}pair"
}
},
onStart: async function ({ api, event, args, usersData }) {
try {
const threadInfo = await api.getThreadInfo(event.threadID);
const participants = threadInfo.participantIDs;
const filteredParticipants = participants.filter(id =>
id !== event.senderID && id !== api.getCurrentUserID()
);
if (filteredParticipants.length === 0) {
return api.sendMessage("โ No other members found to pair with!", event.threadID);
}
const randomIndex = Math.floor(Math.random() * filteredParticipants.length);
const matchID = filteredParticipants[randomIndex];
const senderInfo = await api.getUserInfo(event.senderID);
const matchInfo = await api.getUserInfo(matchID);
const senderName = senderInfo[event.senderID].name;
const matchName = matchInfo[matchID].name;
const lovePercent = Math.floor(Math.random() * 31) + 70;
const [senderAvatar, matchAvatar] = await Promise.all([
loadAvatar(event.senderID),
loadAvatar(matchID)
]);
const width = 1200;
const height = 675;
const canvas = createCanvas(width, height);
const ctx = canvas.getContext("2d");
const mainGradient = ctx.createLinearGradient(0, 0, width, height);
mainGradient.addColorStop(0, "#1a0b2e");
mainGradient.addColorStop(0.3, "#451a6f");
mainGradient.addColorStop(0.6, "#9c27b0");
mainGradient.addColorStop(1, "#e91e63");
ctx.fillStyle = mainGradient;
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = "#ffffff";
for (let i = 0; i < 200; i++) {
const x = Math.random() * width;
const y = Math.random() * height;
const size = Math.random() * 2 + 0.5;
const opacity = Math.random() * 0.8 + 0.2;
ctx.globalAlpha = opacity;
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fill();
}
ctx.globalAlpha = 1;
const nebulaColors = [
"rgba(156, 39, 176, 0.3)",
"rgba(233, 30, 99, 0.25)",
"rgba(103, 58, 183, 0.2)",
"rgba(255, 64, 129, 0.15)"
];
for (let i = 0; i < 15; i++) {
const x = Math.random() * width;
const y = Math.random() * height;
const radius = Math.random() * 200 + 100;
const color = nebulaColors[Math.floor(Math.random() * nebulaColors.length)];
const nebulaGradient = ctx.createRadialGradient(x, y, 0, x, y, radius);
nebulaGradient.addColorStop(0, color);
nebulaGradient.addColorStop(1, "transparent");
ctx.fillStyle = nebulaGradient;
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
}
ctx.strokeStyle = "rgba(255, 255, 255, 0.05)";
ctx.lineWidth = 1;
for (let x = 0; x <= width; x += 50) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
for (let y = 0; y <= height; y += 50) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}
const shapes = [];
for (let i = 0; i < 8; i++) {
const shape = {
x: Math.random() * width,
y: Math.random() * height,
size: Math.random() * 60 + 20,
rotation: Math.random() * Math.PI * 2,
type: Math.floor(Math.random() * 3)
};
shapes.push(shape);
}
shapes.forEach(shape => {
ctx.save();
ctx.translate(shape.x, shape.y);
ctx.rotate(shape.rotation);
ctx.fillStyle = "rgba(255, 255, 255, 0.05)";
ctx.strokeStyle = "rgba(255, 255, 255, 0.1)";
ctx.lineWidth = 2;
if (shape.type === 0) {
ctx.beginPath();
ctx.moveTo(0, -shape.size);
ctx.lineTo(shape.size * 0.866, shape.size * 0.5);
ctx.lineTo(-shape.size * 0.866, shape.size * 0.5);
ctx.closePath();
} else if (shape.type === 1) {
ctx.beginPath();
for (let i = 0; i < 6; i++) {
const angle = (Math.PI / 3) * i;
const x = Math.cos(angle) * shape.size;
const y = Math.sin(angle) * shape.size;
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
}
ctx.closePath();
} else {
ctx.beginPath();
ctx.moveTo(0, -shape.size);
ctx.lineTo(shape.size, 0);
ctx.lineTo(0, shape.size);
ctx.lineTo(-shape.size, 0);
ctx.closePath();
}
ctx.fill();
ctx.stroke();
ctx.restore();
});
const cardWidth = 1000;
const cardHeight = 450;
const cardX = (width - cardWidth) / 2;
const cardY = (height - cardHeight) / 2;
ctx.fillStyle = "rgba(255, 255, 255, 0.08)";
ctx.strokeStyle = "rgba(255, 255, 255, 0.15)";
ctx.lineWidth = 2;
ctx.filter = "blur(10px)";
ctx.fillRect(cardX - 10, cardY - 10, cardWidth + 20, cardHeight + 20);
ctx.filter = "none";
roundRect(ctx, cardX, cardY, cardWidth, cardHeight, 30);
ctx.fill();
ctx.stroke();
ctx.strokeStyle = "rgba(233, 30, 99, 0.3)";
ctx.lineWidth = 4;
roundRect(ctx, cardX + 2, cardY + 2, cardWidth - 4, cardHeight - 4, 28);
ctx.stroke();
const leftX = cardX + 100;
const leftY = cardY + 100;
const profileSize = 180;
const profileGradient = ctx.createLinearGradient(leftX, leftY, leftX + profileSize, leftY + profileSize);
profileGradient.addColorStop(0, "#e91e63");
profileGradient.addColorStop(1, "#9c27b0");
ctx.strokeStyle = profileGradient;
ctx.lineWidth = 6;
ctx.beginPath();
ctx.arc(leftX + profileSize/2, leftY + profileSize/2, profileSize/2 + 3, 0, Math.PI * 2);
ctx.stroke();
ctx.save();
ctx.beginPath();
ctx.arc(leftX + profileSize/2, leftY + profileSize/2, profileSize/2, 0, Math.PI * 2);
ctx.clip();
if (senderAvatar) {
ctx.drawImage(senderAvatar, leftX, leftY, profileSize, profileSize);
} else {
ctx.fillStyle = "#e91e63";
ctx.fillRect(leftX, leftY, profileSize, profileSize);
ctx.fillStyle = "white";
ctx.font = "bold 70px 'Arial'";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(senderName.charAt(0).toUpperCase(), leftX + profileSize/2, leftY + profileSize/2);
}
ctx.restore();
ctx.fillStyle = "#ffffff";
ctx.font = "bold 28px 'Segoe UI', Arial, sans-serif";
ctx.textAlign = "center";
ctx.fillText(truncateText(senderName, 20), leftX + profileSize/2, leftY + profileSize + 50);
const rightX = cardX + cardWidth - 100 - profileSize;
const rightY = cardY + 100;
const profileGradient2 = ctx.createLinearGradient(rightX, rightY, rightX + profileSize, rightY + profileSize);
profileGradient2.addColorStop(0, "#9c27b0");
profileGradient2.addColorStop(1, "#673ab7");
ctx.strokeStyle = profileGradient2;
ctx.lineWidth = 6;
ctx.beginPath();
ctx.arc(rightX + profileSize/2, rightY + profileSize/2, profileSize/2 + 3, 0, Math.PI * 2);
ctx.stroke();
ctx.save();
ctx.beginPath();
ctx.arc(rightX + profileSize/2, rightY + profileSize/2, profileSize/2, 0, Math.PI * 2);
ctx.clip();
if (matchAvatar) {
ctx.drawImage(matchAvatar, rightX, rightY, profileSize, profileSize);
} else {
ctx.fillStyle = "#9c27b0";
ctx.fillRect(rightX, rightY, profileSize, profileSize);
ctx.fillStyle = "white";
ctx.font = "bold 70px 'Arial'";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(matchName.charAt(0).toUpperCase(), rightX + profileSize/2, rightY + profileSize/2);
}
ctx.restore();
ctx.fillStyle = "#ffffff";
ctx.font = "bold 28px 'Segoe UI', Arial, sans-serif";
ctx.textAlign = "center";
ctx.fillText(truncateText(matchName, 20), rightX + profileSize/2, rightY + profileSize + 50);
const centerX = width / 2;
const centerY = cardY + 190;
ctx.strokeStyle = "#e91e63";
ctx.lineWidth = 4;
ctx.shadowColor = "#e91e63";
ctx.shadowBlur = 15;
ctx.beginPath();
ctx.moveTo(leftX + profileSize + 30, centerY);
ctx.bezierCurveTo(
leftX + profileSize + 100, centerY - 50,
rightX - 100, centerY - 50,
rightX - 30, centerY
);
ctx.stroke();
ctx.shadowBlur = 0;
for (let i = 0; i < 5; i++) {
const t = i / 4;
const x = bezierPoint(leftX + profileSize + 30, leftX + profileSize + 100, rightX - 100, rightX - 30, t);
const y = bezierPoint(centerY, centerY - 50, centerY - 50, centerY, t);
ctx.fillStyle = i % 2 === 0 ? "#e91e63" : "#9c27b0";
ctx.beginPath();
ctx.arc(x, y, 12, 0, Math.PI * 2);
ctx.fill();
ctx.shadowColor = i % 2 === 0 ? "#e91e63" : "#9c27b0";
ctx.shadowBlur = 10;
ctx.fill();
ctx.shadowBlur = 0;
}
const percentX = centerX;
const percentY = cardY + cardHeight - 120;
const percentSize = 120;
const percentGradient = ctx.createLinearGradient(
percentX - percentSize/2, percentY - percentSize/2,
percentX + percentSize/2, percentY + percentSize/2
);
percentGradient.addColorStop(0, "#e91e63");
percentGradient.addColorStop(1, "#673ab7");
ctx.strokeStyle = percentGradient;
ctx.lineWidth = 10;
ctx.beginPath();
ctx.arc(percentX, percentY, percentSize/2 + 5, 0, Math.PI * 2);
ctx.stroke();
ctx.fillStyle = "rgba(255, 255, 255, 0.1)";
ctx.beginPath();
ctx.arc(percentX, percentY, percentSize/2, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = "#ffffff";
ctx.font = "bold 40px 'Segoe UI', Arial, sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(`${lovePercent}%`, percentX, percentY);
ctx.fillStyle = "rgba(255, 255, 255, 0.7)";
ctx.font = "bold 22px 'Segoe UI', Arial, sans-serif";
ctx.fillText("MATCH", percentX, percentY + 100);
ctx.fillStyle = "#ffffff";
ctx.font = "bold 42px 'Montserrat', 'Segoe UI', sans-serif";
ctx.textAlign = "center";
ctx.fillText("PERFECT MATCH", centerX, cardY + 50);
ctx.fillStyle = "rgba(255, 255, 255, 0.7)";
ctx.font = "22px 'Segoe UI', Arial, sans-serif";
ctx.fillText("Two hearts, one connection", centerX, cardY + 85);
const imagePath = path.join(__dirname, "pair_match.png");
const buffer = canvas.toBuffer("image/png");
fs.writeFileSync(imagePath, buffer);
const message = `๐ธ ๐ ๐ฎ๐๐ฐ๐ต๐บ๐ฎ๐ธ๐ถ๐ป๐ด ๐๐ผ๐บ๐ฝ๐น๐ฒ๐๐ฒ ๐ธ\n\n` +
`๐ ${senderName}\n` +
`๐ ${matchName}\n\n` +
`๐ ${lovePercent}%`;
await api.sendMessage({
body: message,
attachment: fs.createReadStream(imagePath)
}, event.threadID);
fs.unlinkSync(imagePath);
} catch (error) {
console.error("Pair command error:", error);
api.sendMessage("โ An error occurred.", event.threadID);
}
}
};
async function loadAvatar(uid) {
try {
let imageBuffer;
const fbUrls = [
`https://graph.facebook.com/${uid}/picture?width=500&height=500&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`,
`https://graph.facebook.com/${uid}/picture?width=500&height=500`,
`https://graph.facebook.com/${uid}/picture?type=large`,
`https://graph.facebook.com/${uid}/picture`
];
for (const url of fbUrls) {
try {
const response = await axios.get(url, {
responseType: 'arraybuffer',
timeout: 5000,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'image/*',
'Referer': 'https://www.facebook.com/'
}
});
if (response.status === 200 && response.data) {
imageBuffer = Buffer.from(response.data);
break;
}
} catch (err) {
continue;
}
}
if (imageBuffer) {
return await loadImage(imageBuffer);
}
} catch (err) {
console.log("Avatar load failed for UID:", uid, err.message);
}
return null;
}
function roundRect(ctx, x, y, width, height, radius) {
if (width < 2 * radius) radius = width / 2;
if (height < 2 * radius) radius = height / 2;
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
}
function truncateText(text, maxLength) {
if (text.length <= maxLength) return text;
return text.substring(0, maxLength - 3) + "...";
}
function bezierPoint(p0, p1, p2, p3, t) {
const c = 1 - t;
return c*c*c*p0 + 3*c*c*t*p1 + 3*c*t*t*p2 + t*t*t*p3;
}