// code from goatstore // api: https://store.agi.bd const fs = require("fs-extra"); const path = require("path"); const os = require("os"); const { createCanvas } = require("canvas"); const { spawn } = require("child_process"); module.exports.config = { name: "gift", version: "2.0.0", author: "Zihad", aliases: ["animegift", "effect", "agift"], role: 0, category: "fun", shortDescription: "Anime gift video effect", longDescription: "Creates a simple anime neon gift animation.", guide: "{pn}" }; // ============================== // FFmpeg runner // ============================== function runFFmpeg(args) { return new Promise((resolve, reject) => { const ff = spawn("ffmpeg", args, { windowsHide: true }); let errorText = ""; ff.stderr.on("data", data => { errorText += data.toString(); }); ff.on("error", error => { reject( new Error( "FFmpeg পাওয়া যায়নি। Server-এ FFmpeg install করুন।" ) ); }); ff.on("close", code => { if (code === 0) { resolve(); } else { reject( new Error( "FFmpeg error: " + errorText.slice(-1000) ) ); } }); }); } // ============================== // Rounded rectangle // ============================== function roundRect(ctx, x, y, w, h, r) { r = Math.min(r, w / 2, h / 2); 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(); } // ============================== // Heart // ============================== function drawHeart(ctx, x, y, size, alpha) { ctx.save(); ctx.translate(x, y); ctx.scale(size, size); ctx.globalAlpha = alpha; ctx.beginPath(); ctx.moveTo(0, 0.35); ctx.bezierCurveTo( -0.55, -0.10, -0.45, -0.55, 0, -0.25 ); ctx.bezierCurveTo( 0.45, -0.55, 0.55, -0.10, 0, 0.35 ); ctx.closePath(); const gradient = ctx.createLinearGradient( -1, -1, 1, 1 ); gradient.addColorStop( 0, "#ffffff" ); gradient.addColorStop( 0.3, "#ff5bcf" ); gradient.addColorStop( 1, "#7c4dff" ); ctx.fillStyle = gradient; ctx.fill(); ctx.restore(); } // ============================== // Spark // ============================== function drawSpark(ctx, x, y, size, alpha) { ctx.save(); ctx.globalAlpha = alpha; ctx.translate(x, y); ctx.fillStyle = "#ffffff"; ctx.beginPath(); ctx.moveTo(0, -size); ctx.lineTo(size * 0.25, -size * 0.25); ctx.lineTo(size, 0); ctx.lineTo(size * 0.25, size * 0.25); ctx.lineTo(0, size); ctx.lineTo(-size * 0.25, size * 0.25); ctx.lineTo(-size, 0); ctx.lineTo(-size * 0.25, -size * 0.25); ctx.closePath(); ctx.fill(); ctx.restore(); } // ============================== // Draw animation frame // ============================== function drawFrame(ctx, W, H, frame, total) { const progress = frame / total; // Background const background = ctx.createLinearGradient( 0, 0, W, H ); background.addColorStop( 0, "#05000f" ); background.addColorStop( 0.5, "#17002d" ); background.addColorStop( 1, "#020006" ); ctx.fillStyle = background; ctx.fillRect(0, 0, W, H); // ============================ // Background glow // ============================ const glow = ctx.createRadialGradient( W / 2, H / 2, 20, W / 2, H / 2, 380 ); glow.addColorStop( 0, "rgba(255,70,220,0.28)" ); glow.addColorStop( 0.45, "rgba(125,60,255,0.12)" ); glow.addColorStop( 1, "rgba(0,0,0,0)" ); ctx.fillStyle = glow; ctx.fillRect( 0, 0, W, H ); // ============================ // Moving particles // ============================ for (let i = 0; i < 60; i++) { const x = (i * 83 + frame * (i % 3 + 1)) % W; const y = (i * 47 - frame * (i % 2 + 1) + H) % H; const radius = 1 + (i % 3); ctx.globalAlpha = 0.25 + (i % 4) * 0.12; ctx.fillStyle = i % 2 === 0 ? "#ffffff" : "#e18cff"; ctx.beginPath(); ctx.arc( x, y, radius, 0, Math.PI * 2 ); ctx.fill(); } ctx.globalAlpha = 1; // ============================ // Hearts // ============================ for (let i = 0; i < 10; i++) { const x = 45 + ((i * 119 + frame * 1.4) % (W - 90)); const y = H - ((frame * 2 + i * 90) % (H + 120)); drawHeart( ctx, x, y, 0.7 + (i % 3) * 0.15, 0.35 ); } // ============================ // Rings // ============================ for (let i = 0; i < 4; i++) { const radius = 120 + i * 55 + ((frame * 2) % 180); ctx.beginPath(); ctx.arc( W / 2, H / 2 + 30, radius, 0, Math.PI * 2 ); ctx.strokeStyle = `rgba(220,100,255,${0.12 - i * 0.02})`; ctx.lineWidth = 2; ctx.stroke(); } // ============================ // Gift animation // ============================ const bounce = Math.sin(frame * 0.12) * 7; const scale = 1 + Math.sin(frame * 0.10) * 0.035; ctx.save(); ctx.translate( W / 2, H / 2 + 40 + bounce ); ctx.scale( scale, scale ); // Gift glow const giftGlow = ctx.createRadialGradient( 0, 0, 20, 0, 0, 190 ); giftGlow.addColorStop( 0, "rgba(255,70,220,0.35)" ); giftGlow.addColorStop( 1, "rgba(255,70,220,0)" ); ctx.fillStyle = giftGlow; ctx.fillRect( -220, -190, 440, 380 ); // Box roundRect( ctx, -100, -5, 200, 125, 16 ); const box = ctx.createLinearGradient( -100, -5, 100, 120 ); box.addColorStop( 0, "#ff4fbd" ); box.addColorStop( 0.5, "#a84cff" ); box.addColorStop( 1, "#5031d8" ); ctx.fillStyle = box; ctx.fill(); // Vertical ribbon ctx.fillStyle = "#ffe56b"; ctx.fillRect( -15, -5, 30, 125 ); // Horizontal ribbon ctx.fillRect( -100, 25, 200, 28 ); // Lid roundRect( ctx, -120, -40, 240, 40, 12 ); const lid = ctx.createLinearGradient( -120, -40, 120, 0 ); lid.addColorStop( 0, "#ff72d5" ); lid.addColorStop( 1, "#7947ff" ); ctx.fillStyle = lid; ctx.fill(); // Bow ctx.fillStyle = "#ffe56b"; ctx.beginPath(); ctx.ellipse( -30, -57, 35, 20, -0.35, 0, Math.PI * 2 ); ctx.fill(); ctx.beginPath(); ctx.ellipse( 30, -57, 35, 20, 0.35, 0, Math.PI * 2 ); ctx.fill(); ctx.beginPath(); ctx.arc( 0, -57, 12, 0, Math.PI * 2 ); ctx.fill(); ctx.restore(); // ============================ // Sparkles // ============================ for (let i = 0; i < 14; i++) { const angle = (Math.PI * 2 * i) / 14 + frame * 0.025; const distance = 160 + Math.sin( frame * 0.08 + i ) * 25; const x = W / 2 + Math.cos(angle) * distance; const y = H / 2 + Math.sin(angle) * distance; drawSpark( ctx, x, y, 3 + (i % 3) * 2, 0.45 + (i % 3) * 0.12 ); } // ============================ // Top title // ============================ ctx.textAlign = "center"; const fade = Math.min( 1, progress * 5 ); ctx.shadowColor = "#ff4fd8"; ctx.shadowBlur = 20; ctx.font = "bold 50px Arial"; ctx.fillStyle = `rgba(255,255,255,${fade})`; ctx.fillText( "ZIHAD GIFT", W / 2, 90 ); ctx.shadowBlur = 0; ctx.font = "18px Arial"; ctx.fillStyle = `rgba(255,210,255,${fade * 0.8})`; ctx.fillText( "ANIME MAGIC", W / 2, 122 ); // ============================ // Bottom text // ============================ ctx.font = "bold 19px Arial"; ctx.fillStyle = `rgba(255,255,255,${fade * 0.75})`; ctx.fillText( "A LITTLE GIFT FOR YOU", W / 2, H - 55 ); // Flash near end if (frame > total - 6) { const flash = (frame - (total - 6)) / 6; ctx.fillStyle = `rgba(255,255,255,${flash * 0.25})`; ctx.fillRect( 0, 0, W, H ); } } // ============================== // Main command // ============================== module.exports.onStart = async function ({ api, event }) { const baseDir = path.join( os.tmpdir(), "zihad_gift_" + Date.now() ); const framesDir = path.join( baseDir, "frames" ); const output = path.join( baseDir, "zihad_gift.mp4" ); try { await fs.ensureDir( framesDir ); const W = 720; const H = 720; const FPS = 24; const seconds = 5; const totalFrames = FPS * seconds; const canvas = createCanvas(W, H); const ctx = canvas.getContext("2d"); // ============================ // Generate frames // ============================ for ( let frame = 0; frame < totalFrames; frame++ ) { drawFrame( ctx, W, H, frame, totalFrames ); const frameName = "frame_" + String(frame).padStart(4, "0") + ".png"; const framePath = path.join( framesDir, frameName ); await fs.writeFile( framePath, canvas.toBuffer("image/png") ); } // ============================ // Convert PNG → MP4 // ============================ await runFFmpeg([ "-y", "-framerate", String(FPS), "-i", path.join( framesDir, "frame_%04d.png" ), "-c:v", "libx264", "-preset", "ultrafast", "-crf", "28", "-pix_fmt", "yuv420p", "-movflags", "+faststart", output ]); // ============================ // Check output // ============================ if ( !(await fs.pathExists(output)) ) { throw new Error( "MP4 file তৈরি হয়নি।" ); } // ============================ // Send // ============================ await api.sendMessage( { body: "🎁 𝐀𝐍𝐈𝐌𝐄 𝐆𝐈𝐅𝐓\n\n" + "✨ Special effect created!\n" + "💜 Powered by Zihad", attachment: fs.createReadStream(output) }, event.threadID, event.messageID ); } catch (error) { console.error( "[GIFT ERROR]", error ); await api.sendMessage( "❌ Anime Gift তৈরি করা যায়নি!\n\n" + "সমস্যা: " + error.message + "\n\n" + "⚙️ Canvas + FFmpeg ঠিকভাবে install আছে কিনা দেখুন।", event.threadID, event.messageID ); } finally { // ============================ // Cleanup // ============================ setTimeout( async () => { try { await fs.remove( baseDir ); } catch (e) {} }, 15000 ); } };