Skip to content

Instantly share code, notes, and snippets.

@ayashiiiyo
Created April 25, 2026 14:10
Show Gist options
  • Select an option

  • Save ayashiiiyo/48e09cad5d4819e7597e279188b757b6 to your computer and use it in GitHub Desktop.

Select an option

Save ayashiiiyo/48e09cad5d4819e7597e279188b757b6 to your computer and use it in GitHub Desktop.
import { Canvas, loadImage, FontLibrary } from 'skia-canvas'
import fs from 'fs'
async function ensureFile(url, path) {
if (!fs.existsSync(path)) {
const res = await fetch(url)
const buf = Buffer.from(await res.arrayBuffer())
fs.writeFileSync(path, buf)
}
}
async function generate(pp, name, text) {
if (!fs.existsSync('./font')) fs.mkdirSync('./font')
await ensureFile('https://raw.githubusercontent.com/uploader762/dat2/main/uploads/957068-1777109622178.ttf', './font/Nuninto-SemiBold.ttf')
await ensureFile('https://raw.githubusercontent.com/uploader762/dat1/main/uploads/5206ca-1777112931358.otf', './font/Cooper-black.ttf')
await ensureFile('https://raw.githubusercontent.com/uploader762/dat4/main/uploads/036484-1777108103055.jpg', './bg-fakeigstory.jpg')
FontLibrary.use('Nuninto-SemiBold', ['./font/Nuninto-SemiBold.ttf'])
FontLibrary.use('Cooper-Black', ['./font/Cooper-black.ttf'])
let p = {
t: { x: 126, y: 239 },
b: { x: 144, y: 359 },
l: { x: 72, y: 299 },
r: { x: 191, y: 293 }
}
let left = 120, right = 1196, topY = 428, bottomY = 1549
let boxX = (left + right) / 2
let boxY = (topY + bottomY) / 2
let bg = await loadImage('./bg-fakeigstory.jpg')
let avatar = await loadImage(pp)
let canvas = new Canvas(bg.width, bg.height)
let ctx = canvas.getContext('2d')
ctx.imageSmoothingEnabled = true
ctx.imageSmoothingQuality = 'high'
ctx.drawImage(bg, 0, 0)
let cx = (p.l.x + p.r.x) / 2 + 2
let cy = (p.t.y + p.b.y) / 2
let r = (p.r.x - p.l.x) / 2
let s = Math.min(avatar.width, avatar.height)
let sx = (avatar.width - s) / 2
let sy = (avatar.height - s) / 2
ctx.save()
ctx.beginPath()
ctx.arc(cx, cy, r, 0, Math.PI * 2)
ctx.closePath()
ctx.clip()
ctx.drawImage(avatar, sx, sy, s, s, cx - r, cy - r, r * 2, r * 2)
ctx.restore()
ctx.font = 'bold 48px "Nuninto-SemiBold"'
ctx.fillStyle = '#ffffff'
ctx.textBaseline = 'middle'
ctx.textAlign = 'left'
ctx.fillText(name, cx + r + 19, cy)
function wrap(ctx, text, maxW) {
let w = text.split(' '), line = '', lines = []
for (let i = 0; i < w.length; i++) {
let t = line + w[i] + ' '
if (ctx.measureText(t).width > maxW && i > 0) {
lines.push(line)
line = w[i] + ' '
} else line = t
}
lines.push(line)
return lines
}
function autoText(ctx, text) {
let maxW = right - left
let maxH = bottomY - topY
let fsz = 74, lines, lh, th
do {
ctx.font = `bold ${fsz}px "Cooper-Black"`
lines = wrap(ctx, text, maxW)
lh = fsz * 1.1
th = lines.length * lh
fsz -= 2
} while ((th > maxH || Math.max(...lines.map(l => ctx.measureText(l).width)) > maxW) && fsz > 20)
ctx.font = `bold ${fsz}px "Cooper-Black"`
ctx.fillStyle = '#ffffff'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
let startY = boxY - (lines.length * lh / 2) + (lh / 2)
lines.forEach((l, i) => ctx.fillText(l, boxX, startY + (i * lh)))
}
autoText(ctx, text)
return await canvas.toBuffer('png')
}
let handler = async (m, { conn, args, command }) => {
try {
if (!args[0]) return m.reply(`Example : .${command} Halo Dunia`)
m.reply(global.wait)
let pp = await conn.profilePictureUrl(m.sender, 'image').catch(_ => 'https://raw.githubusercontent.com/uploader762/dat4/main/uploads/e0f993-1777126212302.jpg')
let res = await generate(pp, m.pushName || 'User', args.join(' '))
await conn.sendMessage(m.chat, { image: res }, { quoted: m })
} catch (e) {
m.reply(e.message)
}
}
handler.help = ['igstory <text>']
handler.command = ['igstory']
handler.tags = ['maker']
export default handler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment