// code from goatstore // api: https://store.agi.bd // code from goatstore // api: https://store.agi.bd const axios = require("axios"); const Canvas = require("canvas"); const fs = require("fs"); const path = require("path"); module.exports = { config: { name: "pair4", version: "2.0.0", author: "𝐌𝐚𝐑𝐮𝐅", role: 0, countDown: 5, shortDescription: "Futuristic romantic pair system", category: "FUN & SOCIAL" }, onStart: async function ({ api, event, usersData }) { const { threadID, messageID, senderID, messageReply, mentions } = event; try { /* * ========================================== * TARGET SYSTEM * ========================================== * * Priority: * 1. Reply করা ব্যক্তির সাথে pair * 2. Mention করা ব্যক্তির সাথে pair * 3. Mention/Reply না থাকলে sender-এর জন্য pair */ let targetID = senderID; let targetName = null; // 1️⃣ REPLY SYSTEM if ( messageReply && messageReply.senderID ) { targetID = messageReply.senderID; try { const userData = await usersData.get(targetID); targetName = userData.name || "User"; } catch { targetName = "User"; } } // 2️⃣ MENTION SYSTEM else if ( mentions && Object.keys(mentions).length > 0 ) { targetID = Object.keys(mentions)[0]; try { const userData = await usersData.get(targetID); targetName = userData.name || "User"; } catch { targetName = "User"; } } const loading = await api.sendMessage( "💫 | Finding your perfect partner...", threadID ); /* * ========================================== * GET USER + GROUP DATA * ========================================== */ const [ senderData, threadInfo ] = await Promise.all([ usersData.get(targetID), api.getThreadInfo(threadID) ]); const senderName = targetName || senderData.name || "User"; const senderGender = senderData.gender; /* * ========================================== * GROUP MEMBERS * ========================================== */ const members = threadInfo.participantIDs.filter( uid => uid != targetID && uid != api.getCurrentUserID() ); if (!members.length) { if (loading?.messageID) { try { await api.unsendMessage( loading.messageID, threadID ); } catch {} } return api.sendMessage( "❌ No other members found in this group.", threadID, messageID ); } /* * ========================================== * TARGET GENDER * ========================================== */ let targetGender; if (senderGender === 1) { targetGender = 2; } else if (senderGender === 2) { targetGender = 1; } else { targetGender = Math.random() > 0.5 ? 1 : 2; } let partnerList = []; /* * ========================================== * RANDOM MEMBERS * ========================================== */ const randomMembers = members.sort( () => 0.5 - Math.random() ); /* * ========================================== * FIND PARTNER BY GENDER * ========================================== */ for (const uid of randomMembers) { try { const data = await usersData.get(uid); if ( data && data.gender === targetGender ) { partnerList.push({ id: uid, name: data.name || "Someone", gender: data.gender }); } } catch {} } let partner; /* * ========================================== * SELECT PARTNER * ========================================== */ if (partnerList.length > 0) { partner = partnerList[ Math.floor( Math.random() * partnerList.length ) ]; } else { let fallbackPartner = null; for (const uid of randomMembers) { try { const data = await usersData.get(uid); if ( data && data.gender !== senderGender && data.gender !== undefined ) { fallbackPartner = { id: uid, name: data.name || "Someone", gender: data.gender }; break; } } catch {} } if (fallbackPartner) { partner = fallbackPartner; } else { const fallbackId = randomMembers[ Math.floor( Math.random() * randomMembers.length ) ]; partner = { id: fallbackId, name: "Someone Special", gender: targetGender }; } } /* * ========================================== * FINAL GENDER CHECK * ========================================== */ if ( partner.gender === senderGender && senderGender !== undefined ) { for (const uid of randomMembers) { try { const data = await usersData.get(uid); if ( data && data.gender !== senderGender && data.gender !== undefined ) { partner = { id: uid, name: data.name || "Someone", gender: data.gender }; break; } } catch {} } } /* * ========================================== * COMPATIBILITY * ========================================== */ const match = Math.floor( Math.random() * 31 ) + 70; /* * ========================================== * CANVAS * ========================================== */ const canvas = Canvas.createCanvas( 1600, 900 ); const ctx = canvas.getContext("2d"); const width = canvas.width; const height = canvas.height; /* * ========================================== * BACKGROUND * ========================================== */ const bg = ctx.createLinearGradient( 0, 0, width, height ); bg.addColorStop( 0, "#050816" ); bg.addColorStop( 0.35, "#101b3d" ); bg.addColorStop( 0.65, "#24114d" ); bg.addColorStop( 1, "#050816" ); ctx.fillStyle = bg; ctx.fillRect( 0, 0, width, height ); /* * ========================================== * CYAN STARS * ========================================== */ for (let i = 0; i < 160; i++) { const x = Math.random() * width; const y = Math.random() * height; const size = Math.random() * 3 + 1; ctx.beginPath(); ctx.arc( x, y, size, 0, Math.PI * 2 ); ctx.fillStyle = `rgba(0, 230, 255, ${ Math.random() * 0.6 })`; ctx.fill(); } /* * ========================================== * PINK PARTICLES * ========================================== */ for (let i = 0; i < 70; i++) { const x = Math.random() * width; const y = Math.random() * height; ctx.fillStyle = `rgba(255, 0, 180, ${ Math.random() * 0.3 })`; ctx.fillRect( x, y, 2, 2 ); } /* * ========================================== * OUTER BORDER * ========================================== */ ctx.strokeStyle = "rgba(0, 240, 255, 0.7)"; ctx.lineWidth = 4; ctx.shadowBlur = 25; ctx.shadowColor = "#00eaff"; ctx.strokeRect( 20, 20, width - 40, height - 40 ); ctx.shadowBlur = 0; ctx.strokeStyle = "rgba(255, 0, 200, 0.35)"; ctx.lineWidth = 2; ctx.strokeRect( 32, 32, width - 64, height - 64 ); /* * ========================================== * HEADER * ========================================== */ ctx.textAlign = "center"; ctx.fillStyle = "#ffffff"; ctx.shadowColor = "#00eaff"; ctx.shadowBlur = 18; ctx.font = "bold 68px Arial"; ctx.fillText( "PAIR CONNECTION", width / 2, 105 ); ctx.shadowBlur = 0; ctx.fillStyle = "#00eaff"; ctx.font = "bold 28px Arial"; ctx.fillText( "✦ COMPATIBILITY ANALYSIS ✦", width / 2, 150 ); /* * ========================================== * FACEBOOK PROFILE PICTURES * ========================================== */ const token = "6628568379|c1e620fa708a1d5696fb991c1bde5662"; const avt1 = `https://graph.facebook.com/${targetID}/picture?width=1024&height=1024&access_token=${token}`; const avt2 = `https://graph.facebook.com/${partner.id}/picture?width=1024&height=1024&access_token=${token}`; async function loadImage(url) { const response = await axios.get( url, { responseType: "arraybuffer", headers: { "User-Agent": "Mozilla/5.0" }, timeout: 15000 } ); return Canvas.loadImage( response.data ); } const [ img1, img2 ] = await Promise.all([ loadImage(avt1), loadImage(avt2) ]); /* * ========================================== * DRAW TECH AVATAR * ========================================== */ function drawTechAvatar( img, x, y ) { const size = 330; ctx.save(); ctx.shadowColor = "#00eaff"; ctx.shadowBlur = 35; ctx.strokeStyle = "#00eaff"; ctx.lineWidth = 8; ctx.beginPath(); ctx.arc( x + size / 2, y + size / 2, size / 2 + 20, 0, Math.PI * 2 ); ctx.stroke(); ctx.shadowColor = "#ff00c8"; ctx.shadowBlur = 25; ctx.strokeStyle = "#ff00c8"; ctx.lineWidth = 5; ctx.beginPath(); ctx.arc( x + size / 2, y + size / 2, size / 2 + 8, 0, Math.PI * 2 ); ctx.stroke(); ctx.shadowBlur = 0; ctx.save(); ctx.beginPath(); ctx.arc( x + size / 2, y + size / 2, size / 2 - 5, 0, Math.PI * 2 ); ctx.clip(); ctx.drawImage( img, x, y, size, size ); ctx.restore(); ctx.strokeStyle = "rgba(255,255,255,0.9)"; ctx.lineWidth = 3; ctx.beginPath(); ctx.arc( x + size / 2, y + size / 2, size / 2 - 5, 0, Math.PI * 2 ); ctx.stroke(); ctx.restore(); ctx.fillStyle = "#00eaff"; ctx.font = "bold 25px Arial"; ctx.textAlign = "center"; ctx.fillText( "● CONNECTED", x + size / 2, y + size + 55 ); } drawTechAvatar( img1, 180, 250 ); drawTechAvatar( img2, 1090, 250 ); /* * ========================================== * HEART * ========================================== */ ctx.shadowColor = "#ff00c8"; ctx.shadowBlur = 30; ctx.fillStyle = "#ff00c8"; ctx.font = "bold 135px Arial"; ctx.fillText( "♥", width / 2, 390 ); ctx.shadowBlur = 0; /* * ========================================== * MATCH PERCENTAGE * ========================================== */ ctx.fillStyle = "#ffffff"; ctx.font = "bold 60px Arial"; ctx.fillText( `${match}%`, width / 2, 505 ); ctx.fillStyle = "#00eaff"; ctx.font = "bold 25px Arial"; const compatibility = match > 85 ? "PERFECT CONNECTION" : match > 75 ? "STRONG CONNECTION" : "GOOD CONNECTION"; ctx.fillText( compatibility, width / 2, 550 ); /* * ========================================== * PROGRESS CIRCLE * ========================================== */ ctx.strokeStyle = "rgba(0,234,255,0.25)"; ctx.lineWidth = 16; ctx.beginPath(); ctx.arc( width / 2, 465, 105, 0, Math.PI * 2 ); ctx.stroke(); const progress = (match / 100) * Math.PI * 2; ctx.strokeStyle = "#00eaff"; ctx.lineWidth = 16; ctx.beginPath(); ctx.arc( width / 2, 465, 105, -Math.PI / 2, -Math.PI / 2 + progress ); ctx.stroke(); /* * ========================================== * DISPLAY NAMES * ========================================== */ ctx.shadowColor = "#ff00c8"; ctx.shadowBlur = 15; ctx.fillStyle = "#ffffff"; ctx.font = "bold 42px Arial"; let displayName1 = String(senderName); let displayName2 = String(partner.name); if ( displayName1.length > 18 ) { displayName1 = displayName1.substring( 0, 18 ) + "..."; } if ( displayName2.length > 18 ) { displayName2 = displayName2.substring( 0, 18 ) + "..."; } ctx.fillText( displayName1, 345, 680 ); ctx.fillText( displayName2, 1255, 680 ); ctx.shadowBlur = 0; /* * ========================================== * VS * ========================================== */ ctx.fillStyle = "#ff00c8"; ctx.font = "bold 32px Arial"; ctx.fillText( "VS", width / 2, 680 ); /* * ========================================== * FOOTER * ========================================== */ ctx.fillStyle = "#ffffff"; ctx.font = "bold 36px Arial"; ctx.fillText( "✦ PERFECT PAIR ✦", width / 2, 750 ); ctx.fillStyle = "#00eaff"; ctx.font = "24px Arial"; ctx.fillText( "💫 TWO PROFILES • ONE CONNECTION 💫", width / 2, 795 ); ctx.fillStyle = "rgba(255,255,255,0.45)"; ctx.font = "18px Arial"; ctx.fillText( "PAIR4 SYSTEM", width / 2, 835 ); /* * ========================================== * CACHE * ========================================== */ const cacheDir = path.join( __dirname, "cache" ); if ( !fs.existsSync( cacheDir ) ) { fs.mkdirSync( cacheDir, { recursive: true } ); } const filePath = path.join( cacheDir, `pair4_${Date.now()}.png` ); fs.writeFileSync( filePath, canvas.toBuffer() ); /* * ========================================== * REMOVE LOADING * ========================================== */ if ( loading && loading.messageID ) { try { await api.unsendMessage( loading.messageID, threadID ); } catch {} } /* * ========================================== * RESULT MESSAGE * ========================================== */ const emoji = match > 85 ? "💞" : match > 75 ? "💗" : "💕"; const compatibilityText = match > 85 ? "Perfect" : match > 75 ? "Great" : "Good"; const genderEmoji1 = senderGender === 1 ? "👦" : senderGender === 2 ? "👧" : "👤"; const genderEmoji2 = partner.gender === 1 ? "👦" : partner.gender === 2 ? "👧" : "👤"; const msg = `${emoji} 𝐏𝐀𝐈𝐑 𝟒 ${genderEmoji1} ${senderName} ✦ ${genderEmoji2} ${partner.name} 📊 ${match}% ${compatibilityText} Match 💘 Status: Matched!`; /* * ========================================== * SEND RESULT * ========================================== */ return api.sendMessage( { body: msg, attachment: fs.createReadStream( filePath ) }, threadID, () => { if ( fs.existsSync( filePath ) ) { try { fs.unlinkSync( filePath ); } catch {} } }, messageID ); } catch (err) { console.log( "Pair4 Error:", err ); return api.sendMessage( "❌ | Pair system failed! Please try again.", threadID, messageID ); } } };