import { Context } from 'elysia' import axios from 'axios' import sharp from 'sharp' const parseIntParam = (value: string): number | null => { const parsed = Number(value) if (isNaN(parsed)) return null return parsed } const clamp = (n: number): number => Math.max(0, Math.min(255, n)) const recolor = async (imgBuffer: Buffer, color: number[]): Promise => { const [r, g, b] = color const image = sharp(imgBuffer) const raw = await image .ensureAlpha() .raw() .toBuffer({ resolveWithObject: true }) const pixels = raw.data const { width: w, height: h } = raw.info for (let i = 0; i < pixels.length; i += 4) { pixels[i] = Math.round((pixels[i] / 255) * r) pixels[i + 1] = Math.round((pixels[i + 1] / 255) * g) pixels[i + 2] = Math.round((pixels[i + 2] / 255) * b) } return sharp(pixels, { raw: { width: w, height: h!, channels: 4 } }) .png() .toBuffer() } export const handler = async (context: Context) => { let icon = Math.max(-4, Math.min(8, parseIntParam(context.query.icon) ?? 1)) let overlay = Math.max( 0, Math.min(14, parseIntParam(context.query.overlay) ?? 0) ) const birdColor = [ clamp(parseIntParam(context.query.birdR) ?? 255), clamp(parseIntParam(context.query.birdG) ?? 255), clamp(parseIntParam(context.query.birdB) ?? 255) ] const overlayColor = [ clamp(parseIntParam(context.query.overlayR) ?? 255), clamp(parseIntParam(context.query.overlayG) ?? 255), clamp(parseIntParam(context.query.overlayB) ?? 255) ] let overlayImg: Buffer | null = null let iconImg: Buffer | null = null if (overlay !== 0) { try { const result = await axios.get( `https://games-r2.lncvrt.xyz/game-assets/berrydash/overlays/overlay_${overlay}.png`, { responseType: 'arraybuffer' } ) overlayImg = Buffer.from(result.data) } catch {} } try { const result = await axios.get( `https://games-r2.lncvrt.xyz/game-assets/berrydash/icons/bird_${icon}.png`, { responseType: 'arraybuffer' } ) iconImg = Buffer.from(result.data) } catch {} if (!iconImg) { return new Response(null, { status: 400 }) } let result = await recolor(iconImg, birdColor) if (overlayImg) { const recoloredOverlay = await recolor(overlayImg, overlayColor) result = await sharp(result) .composite([ { input: recoloredOverlay, top: overlay == 8 ? 25 : 13, left: overlay == 8 ? 10 : 15, blend: 'over' } ]) .png() .toBuffer() } return new Response(result.buffer as ArrayBuffer, { headers: { 'Content-Type': 'image/png' } }) }