goat
command
propose2
Stylish proposal card with profile pictures
0
views
0
likes
0
installs
raw source
const axios = require("axios");
const fs = require("fs-extra");
const path = require("path");
const { createCanvas, loadImage } = require("canvas");
module.exports = {
config: {
name: "propose2",
version: "1.0.0",
author: "Mohammad Maruf",
countDown: 10,
role: 0,
description: "Stylish proposal card with profile pictures",
category: "love",
guide: {
en: "{pn} @mention | Reply | [uid]"
}
},
onStart: async function ({
api,
event,
args,
usersData
}) {
const {
threadID,
messageID,
senderID,
mentions,
type,
messageReply
} = event;
// ==========================================
// FIND TARGET
// ==========================================
let targetID;
if (
type === "message_reply" &&
messageReply
) {
targetID = messageReply.senderID;
}
else if (
mentions &&
Object.keys(mentions).length > 0
) {
targetID = Object.keys(mentions)[0];
}
else if (args && args[0]) {
targetID = args[0];
}
if (!targetID) {
return api.sendMessage(
"💌 কাউকে Propose করতে হলে তাকে mention করো অথবা তার message-এ reply দাও! 💍",
threadID,
messageID
);
}
// ==========================================
// SELF CHECK
// ==========================================
if (String(targetID) === String(senderID)) {
return api.sendMessage(
"😂 নিজেকেই propose করছো?\n\nনিজেকে একটু সময় দাও আগে! 🫠❤️",
threadID,
messageID
);
}
try {
// ==========================================
// USER INFORMATION
// ==========================================
const [senderInfo, targetInfo] =
await Promise.all([
usersData.get(senderID),
usersData.get(targetID)
]);
const senderName =
senderInfo?.name || "Someone";
const targetName =
targetInfo?.name || "Someone";
const senderGender =
senderInfo?.gender;
// ==========================================
// AVATAR URL
// ==========================================
const getAvatar = (uid) =>
`https://graph.facebook.com/${uid}/picture` +
`?width=512&height=512` +
`&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`;
// ==========================================
// LOAD AVATARS
// ==========================================
const [senderAvatar, targetAvatar] =
await Promise.all([
loadImage(getAvatar(senderID)),
loadImage(getAvatar(targetID))
]);
// ==========================================
// CANVAS
// ==========================================
const WIDTH = 900;
const HEIGHT = 1100;
const canvas =
createCanvas(WIDTH, HEIGHT);
const ctx =
canvas.getContext("2d");
// ==========================================
// PREMIUM BACKGROUND
// ==========================================
const bg =
ctx.createLinearGradient(
0,
0,
WIDTH,
HEIGHT
);
bg.addColorStop(0, "#18001f");
bg.addColorStop(0.35, "#4b123f");
bg.addColorStop(0.7, "#8d315f");
bg.addColorStop(1, "#210016");
ctx.fillStyle = bg;
ctx.fillRect(
0,
0,
WIDTH,
HEIGHT
);
// ==========================================
// SOFT GLOW
// ==========================================
const glow =
ctx.createRadialGradient(
450,
500,
50,
450,
500,
500
);
glow.addColorStop(
0,
"rgba(255,120,190,0.35)"
);
glow.addColorStop(
1,
"rgba(255,0,100,0)"
);
ctx.fillStyle = glow;
ctx.fillRect(
0,
0,
WIDTH,
HEIGHT
);
// ==========================================
// HEART PARTICLES
// ==========================================
function drawHeart(
x,
y,
size,
alpha = 1
) {
ctx.save();
ctx.globalAlpha = alpha;
ctx.fillStyle = "#ffb6d9";
ctx.beginPath();
ctx.moveTo(
x,
y + size * 0.3
);
ctx.bezierCurveTo(
x - size * 0.8,
y - size * 0.2,
x - size * 0.7,
y - size,
x,
y - size * 0.45
);
ctx.bezierCurveTo(
x + size * 0.7,
y - size,
x + size * 0.8,
y - size * 0.2,
x,
y + size * 0.3
);
ctx.fill();
ctx.restore();
}
const hearts = [
[75, 100, 18, 0.7],
[150, 210, 12, 0.5],
[790, 115, 22, 0.75],
[735, 250, 14, 0.55],
[80, 560, 20, 0.5],
[820, 570, 18, 0.6],
[120, 800, 13, 0.5],
[780, 810, 16, 0.6],
[60, 930, 21, 0.5],
[840, 950, 14, 0.6]
];
hearts.forEach(h =>
drawHeart(
h[0],
h[1],
h[2],
h[3]
)
);
// ==========================================
// TOP TITLE
// ==========================================
ctx.textAlign = "center";
ctx.fillStyle = "#ffd9eb";
ctx.font =
"bold 27px Arial";
ctx.fillText(
"✦ A SPECIAL MESSAGE ✦",
WIDTH / 2,
70
);
ctx.fillStyle = "#ffffff";
ctx.font =
"bold 72px Arial";
ctx.fillText(
"PROPOSAL",
WIDTH / 2,
145
);
ctx.fillStyle = "#ff9dcc";
ctx.font =
"bold 31px Arial";
ctx.fillText(
"A MOMENT WORTH REMEMBERING ❤️",
WIDTH / 2,
195
);
// ==========================================
// AVATAR POSITIONS
// ==========================================
let leftAvatar;
let rightAvatar;
if (senderGender === 1) {
leftAvatar = {
img: senderAvatar,
name: senderName,
x: 220,
y: 390
};
rightAvatar = {
img: targetAvatar,
name: targetName,
x: 680,
y: 390
};
} else {
leftAvatar = {
img: targetAvatar,
name: targetName,
x: 220,
y: 390
};
rightAvatar = {
img: senderAvatar,
name: senderName,
x: 680,
y: 390
};
}
// ==========================================
// CONNECTING GLOW LINE
// ==========================================
ctx.save();
ctx.shadowColor =
"#ff75b7";
ctx.shadowBlur = 20;
ctx.strokeStyle =
"#ff9dcc";
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(
leftAvatar.x + 90,
leftAvatar.y
);
ctx.bezierCurveTo(
350,
300,
550,
300,
rightAvatar.x - 90,
rightAvatar.y
);
ctx.stroke();
ctx.restore();
// ==========================================
// AVATAR FUNCTION
// ==========================================
function drawAvatar(
person,
label
) {
const x = person.x;
const y = person.y;
const radius = 90;
// Outer glow
ctx.save();
ctx.shadowColor =
"#ff55a8";
ctx.shadowBlur = 35;
ctx.beginPath();
ctx.arc(
x,
y,
radius + 12,
0,
Math.PI * 2
);
ctx.fillStyle =
"#ff8fc7";
ctx.fill();
ctx.restore();
// White border
ctx.beginPath();
ctx.arc(
x,
y,
radius + 5,
0,
Math.PI * 2
);
ctx.fillStyle =
"#ffffff";
ctx.fill();
// Clip avatar
ctx.save();
ctx.beginPath();
ctx.arc(
x,
y,
radius,
0,
Math.PI * 2
);
ctx.clip();
ctx.drawImage(
person.img,
x - radius,
y - radius,
radius * 2,
radius * 2
);
ctx.restore();
// Label
ctx.textAlign = "center";
ctx.fillStyle =
"#ffffff";
ctx.font =
"bold 20px Arial";
ctx.fillText(
label,
x,
y + 135
);
}
// ==========================================
// DRAW AVATARS
// ==========================================
drawAvatar(
leftAvatar,
leftAvatar.name
);
drawAvatar(
rightAvatar,
rightAvatar.name
);
// ==========================================
// CENTER HEART
// ==========================================
ctx.save();
ctx.shadowColor =
"#ff006e";
ctx.shadowBlur = 35;
drawHeart(
450,
405,
65,
1
);
ctx.restore();
// ==========================================
// RING
// ==========================================
ctx.textAlign = "center";
ctx.fillStyle =
"#ffe4f1";
ctx.font =
"bold 28px Arial";
ctx.fillText(
"💍",
450,
520
);
// ==========================================
// MESSAGE CARD
// ==========================================
const cardX = 85;
const cardY = 590;
const cardW = 730;
const cardH = 250;
// Card shadow
ctx.save();
ctx.shadowColor =
"rgba(0,0,0,0.45)";
ctx.shadowBlur = 30;
ctx.fillStyle =
"rgba(255,255,255,0.10)";
ctx.beginPath();
ctx.roundRect(
cardX,
cardY,
cardW,
cardH,
30
);
ctx.fill();
ctx.restore();
// Card border
ctx.strokeStyle =
"rgba(255,190,220,0.55)";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.roundRect(
cardX,
cardY,
cardW,
cardH,
30
);
ctx.stroke();
// ==========================================
// CARD TEXT
// ==========================================
ctx.textAlign = "center";
ctx.fillStyle =
"#ffffff";
ctx.font =
"bold 25px Arial";
ctx.fillText(
`${senderName} → ${targetName}`,
WIDTH / 2,
650
);
ctx.fillStyle =
"#ffd4e8";
ctx.font =
"italic 27px Arial";
ctx.fillText(
"Will you be the special one",
WIDTH / 2,
710
);
ctx.fillText(
"in my story? ❤️",
WIDTH / 2,
755
);
ctx.fillStyle =
"#ff9dcc";
ctx.font =
"bold 24px Arial";
ctx.fillText(
"💗 SAY YES • SAY MAYBE • RUN 😂",
WIDTH / 2,
810
);
// ==========================================
// BOTTOM AREA
// ==========================================
ctx.fillStyle =
"#ffffff";
ctx.font =
"bold 22px Arial";
ctx.fillText(
"❤️ MADE WITH COURAGE & A LITTLE BIT OF CRAZINESS ❤️",
WIDTH / 2,
900
);
ctx.fillStyle =
"#ffb6d9";
ctx.font =
"20px Arial";
ctx.fillText(
"If this message made you smile, the mission is complete ✨",
WIDTH / 2,
940
);
// ==========================================
// FOOTER
// ==========================================
ctx.fillStyle =
"rgba(0,0,0,0.30)";
ctx.fillRect(
0,
990,
WIDTH,
110
);
ctx.fillStyle =
"#ffd9eb";
ctx.font =
"bold 21px Arial";
ctx.fillText(
"✦ SPECIAL PROPOSAL CARD ✦",
WIDTH / 2,
1030
);
ctx.fillStyle =
"#ffffff";
ctx.font =
"16px Arial";
ctx.fillText(
"Powered by Mohammad Maruf",
WIDTH / 2,
1060
);
// ==========================================
// OUTER BORDER
// ==========================================
ctx.strokeStyle =
"#ff9dcc";
ctx.lineWidth = 5;
ctx.strokeRect(
15,
15,
WIDTH - 30,
HEIGHT - 30
);
// ==========================================
// SAVE
// ==========================================
const cacheDir =
path.join(
__dirname,
"cache"
);
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(
cacheDir,
{ recursive: true }
);
}
const cachePath =
path.join(
cacheDir,
`propose_${Date.now()}.png`
);
fs.writeFileSync(
cachePath,
canvas.toBuffer("image/png")
);
// ==========================================
// SEND MESSAGE
// ==========================================
return api.sendMessage(
{
body:
`💌 PROPOSAL ALERT 💌\n\n` +
`💗 ${senderName} has a special message for ${targetName}!\n\n` +
`💍 What will the answer be? 👀❤️`,
attachment:
fs.createReadStream(
cachePath
)
},
threadID,
() => {
try {
if (
fs.existsSync(cachePath)
) {
fs.unlinkSync(cachePath);
}
} catch (err) {
console.error(
"Cache cleanup error:",
err
);
}
},
messageID
);
} catch (error) {
console.error(
"Propose Error:",
error
);
return api.sendMessage(
"❌ Proposal image তৈরি করতে সমস্যা হয়েছে। আবার চেষ্টা করো! ❤️",
threadID,
messageID
);
}
}
};