// code from goatstore // api: https://store.agi.bd // code from goatstore // Fixed Pair5 // Reply / Mention Pair System const axios = require("axios"); const Canvas = require("canvas"); const fs = require("fs"); const path = require("path"); module.exports = { config: { name: "pair5", version: "3.0.0", author: "Jihad", role: 0, countDown: 5, shortDescription: "Romantic pair system", category: "FUN & SOCIAL", guide: { en: "{pn}" } }, onStart: async function ({ api, event, usersData }) { const { threadID, messageID, senderID } = event; try { /* * ========================================== * TARGET SYSTEM * ========================================== * Priority: * 1. Reply * 2. Mention */ const targetID = event.messageReply?.senderID || event.messageReply?.author || Object.keys(event.mentions || {})[0]; if (!targetID) { return api.sendMessage( "⚠️ কাউকে Reply অথবা Mention করে /pair5 দিন! 💗", threadID, messageID ); } /* * ========================================== * SELF PAIR PROTECTION * ========================================== */ if ( String(targetID) === String(senderID) ) { return api.sendMessage( "😅 নিজেকে Pair করা যাবে না!", threadID, messageID ); } /* * ========================================== * GET USER DATA * ========================================== */ const [ senderData, targetData ] = await Promise.all([ usersData.get(senderID), usersData.get(targetID) ]); const senderName = senderData?.name || "User"; const targetName = targetData?.name || "User"; const senderGender = senderData?.gender; const targetGender = targetData?.gender; /* * ========================================== * PARTNER * ========================================== * No random member. */ const partner = { id: targetID, name: targetName, gender: targetGender }; /* * ========================================== * LOADING * ========================================== */ const loading = await api.sendMessage( "💗 | Finding a special match...", threadID ); /* * ========================================== * COMPATIBILITY * ========================================== */ const match = Math.floor( Math.random() * 31 ) + 70; /* * ========================================== * CANVAS * ========================================== */ const canvas = Canvas.createCanvas( 1600, 900 ); const ctx = canvas.getContext("2d"); const width = 1600; const height = 900; /* * ========================================== * BACKGROUND * ========================================== */ const bg = ctx.createLinearGradient( 0, 0, width, height ); bg.addColorStop( 0, "#15131c" ); bg.addColorStop( 0.48, "#27202c" ); bg.addColorStop( 1, "#100e15" ); ctx.fillStyle = bg; ctx.fillRect( 0, 0, width, height ); /* * ========================================== * GLOW 1 * ========================================== */ const glow1 = ctx.createRadialGradient( 280, 170, 10, 280, 170, 420 ); glow1.addColorStop( 0, "rgba(222,155,187,0.24)" ); glow1.addColorStop( 1, "rgba(222,155,187,0)" ); ctx.fillStyle = glow1; ctx.fillRect( 0, 0, width, height ); /* * ========================================== * GLOW 2 * ========================================== */ const glow2 = ctx.createRadialGradient( 1350, 720, 10, 1350, 720, 450 ); glow2.addColorStop( 0, "rgba(139,119,180,0.20)" ); glow2.addColorStop( 1, "rgba(139,119,180,0)" ); ctx.fillStyle = glow2; ctx.fillRect( 0, 0, width, height ); /* * ========================================== * STARS * ========================================== */ for (let i = 0; i < 120; i++) { const x = Math.random() * width; const y = Math.random() * height; const r = Math.random() * 1.8 + 0.4; ctx.beginPath(); ctx.arc( x, y, r, 0, Math.PI * 2 ); ctx.fillStyle = `rgba(255,255,255,${ 0.15 + Math.random() * 0.5 })`; ctx.fill(); } /* * ========================================== * HEADER * ========================================== */ ctx.textAlign = "left"; ctx.fillStyle = "#f5eaf0"; ctx.font = "bold 42px Arial"; ctx.fillText( "PAIR", 85, 90 ); ctx.fillStyle = "#9f8995"; ctx.font = "18px Arial"; ctx.fillText( "CONNECTION", 88, 120 ); ctx.strokeStyle = "rgba(255,255,255,0.13)"; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo( 85, 150 ); ctx.lineTo( 1515, 150 ); ctx.stroke(); /* * ========================================== * ROUNDED RECT * ========================================== */ function roundedRect( x, y, w, h, r ) { ctx.beginPath(); ctx.moveTo( x + r, y ); ctx.lineTo( x + w - r, y ); ctx.quadraticCurveTo( x + w, y, x + w, y + r ); ctx.lineTo( x + w, y + h - r ); ctx.quadraticCurveTo( x + w, y + h, x + w - r, y + h ); ctx.lineTo( x + r, y + h ); ctx.quadraticCurveTo( x, y + h, x, y + h - r ); ctx.lineTo( x, y + r ); ctx.quadraticCurveTo( x, y, x + r, y ); ctx.closePath(); } /* * ========================================== * LOAD IMAGE * ========================================== */ function loadImage(url) { return axios .get( url, { responseType: "arraybuffer", headers: { "User-Agent": "Mozilla/5.0" }, timeout: 15000 } ) .then(res => Canvas.loadImage( res.data ) ); } /* * ========================================== * FACEBOOK PROFILE PICTURES * ========================================== */ const token = "6628568379|c1e620fa708a1d5696fb991c1bde5662"; // YOUR PROFILE const avt1 = `https://graph.facebook.com/${senderID}/picture?width=1024&height=1024&access_token=${token}`; // REPLY / MENTION USER const avt2 = `https://graph.facebook.com/${targetID}/picture?width=1024&height=1024&access_token=${token}`; const [ img1, img2 ] = await Promise.all([ loadImage(avt1), loadImage(avt2) ]); /* * ========================================== * DRAW PORTRAIT * ========================================== */ function drawPortrait( image, x, y, size ) { ctx.save(); ctx.shadowColor = "rgba(0,0,0,0.45)"; ctx.shadowBlur = 30; ctx.shadowOffsetY = 15; ctx.fillStyle = "#f8f1f4"; roundedRect( x - 18, y - 18, size + 36, size + 36, 18 ); ctx.fill(); ctx.shadowBlur = 0; ctx.shadowOffsetY = 0; ctx.save(); roundedRect( x, y, size, size, 12 ); ctx.clip(); ctx.drawImage( image, x, y, size, size ); ctx.restore(); ctx.strokeStyle = "rgba(255,255,255,0.75)"; ctx.lineWidth = 2; roundedRect( x, y, size, size, 12 ); ctx.stroke(); ctx.restore(); } /* * ========================================== * DRAW BOTH PORTRAITS * ========================================== */ drawPortrait( img1, 120, 220, 380 ); drawPortrait( img2, 1100, 220, 380 ); /* * ========================================== * NAMES * ========================================== */ ctx.textAlign = "center"; let name1 = String(senderName); let name2 = String(targetName); if ( name1.length > 18 ) { name1 = name1.substring( 0, 18 ) + "..."; } if ( name2.length > 18 ) { name2 = name2.substring( 0, 18 ) + "..."; } ctx.fillStyle = "#f6eaf0"; ctx.font = "bold 30px Arial"; ctx.fillText( name1, 310, 665 ); ctx.fillText( name2, 1290, 665 ); ctx.fillStyle = "#a9939e"; ctx.font = "17px Arial"; ctx.fillText( "PERSON 01", 310, 695 ); ctx.fillText( "PERSON 02", 1290, 695 ); /* * ========================================== * CONNECTION LINES * ========================================== */ ctx.strokeStyle = "rgba(255,255,255,0.12)"; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo( 535, 415 ); ctx.bezierCurveTo( 650, 350, 950, 350, 1065, 415 ); ctx.stroke(); ctx.beginPath(); ctx.moveTo( 535, 470 ); ctx.bezierCurveTo( 650, 540, 950, 540, 1065, 470 ); ctx.stroke(); /* * ========================================== * HEART * ========================================== */ ctx.shadowColor = "rgba(214,126,164,0.45)"; ctx.shadowBlur = 35; ctx.fillStyle = "#d88eab"; ctx.font = "100px Arial"; ctx.fillText( "♥", 800, 455 ); ctx.shadowBlur = 0; ctx.fillStyle = "#ead6df"; ctx.font = "15px Arial"; ctx.fillText( "TOGETHER", 800, 485 ); /* * ========================================== * COMPATIBILITY BOX * ========================================== */ ctx.fillStyle = "#211a22"; roundedRect( 650, 535, 300, 105, 52 ); ctx.fill(); ctx.strokeStyle = "#6e5966"; ctx.lineWidth = 1; roundedRect( 650, 535, 300, 105, 52 ); ctx.stroke(); ctx.fillStyle = "#f8edf2"; ctx.font = "bold 46px Arial"; ctx.fillText( `${match}%`, 800, 602 ); ctx.fillStyle = "#a9929f"; ctx.font = "15px Arial"; ctx.fillText( "COMPATIBILITY", 800, 625 ); /* * ========================================== * RESULT TEXT * ========================================== */ ctx.fillStyle = "#f0dce5"; ctx.font = "bold 24px Arial"; const resultText = match >= 90 ? "A RARE CONNECTION" : match >= 80 ? "A BEAUTIFUL CONNECTION" : "A SWEET CONNECTION"; ctx.fillText( resultText, 800, 735 ); ctx.fillStyle = "#9c8792"; ctx.font = "17px Arial"; ctx.fillText( "Two people • One unexpected connection", 800, 770 ); /* * ========================================== * FOOTER * ========================================== */ ctx.strokeStyle = "rgba(255,255,255,0.12)"; ctx.beginPath(); ctx.moveTo( 610, 810 ); ctx.lineTo( 990, 810 ); ctx.stroke(); ctx.fillStyle = "#8f7a86"; ctx.font = "14px Arial"; ctx.fillText( "✦", 590, 815 ); ctx.fillText( "✦", 1010, 815 ); ctx.fillText( "𝐉𝐈𝐇𝐀𝐃", 800, 840 ); /* * ========================================== * BORDER * ========================================== */ ctx.strokeStyle = "rgba(255,255,255,0.08)"; ctx.lineWidth = 2; roundedRect( 55, 45, width - 110, height - 90, 24 ); ctx.stroke(); /* * ========================================== * CACHE * ========================================== */ const cacheDir = path.join( __dirname, "cache" ); if ( !fs.existsSync(cacheDir) ) { fs.mkdirSync( cacheDir, { recursive: true } ); } const filePath = path.join( cacheDir, `pair5_${Date.now()}.png` ); fs.writeFileSync( filePath, canvas.toBuffer() ); /* * ========================================== * REMOVE LOADING * ========================================== */ if ( loading && loading.messageID ) { try { await api.unsendMessage( loading.messageID ); } 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 = targetGender === 1 ? "👦" : targetGender === 2 ? "👧" : "👤"; const msg = `${emoji} 𝐏𝐀𝐈𝐑 𝟓 ${genderEmoji1} ${senderName} × ${genderEmoji2} ${targetName} 📊 ${match}% ${compatibilityText} Match 💗 A beautiful connection`; /* * ========================================== * 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( "PAIR5 ERROR:", err ); return api.sendMessage( "❌ | Pair5 failed! Please try again.", threadID, messageID ); } } };