import { Hono } from 'hono' const app = new Hono() const joypixels = require("emoji-toolkit"); import { mkdirSync, writeFileSync, existsSync, rmSync, readFileSync, readFile } from 'fs' import { $ } from 'bun'; import ytSearch from 'yt-search'; let ytdlpPath = "yt-dlp" if(existsSync("./yt-dlp")) { ytdlpPath = "./yt-dlp" } app.post("/youtube", async (c) => { const auth = c.req.header('Authorization') if (auth !== process.env.PASSWORD) { return c.text('Unauthorized', 401) } const body = await c.req.json().catch(() => null); if (!body || typeof body.title !== 'string' || typeof body.artist !== 'string') { return c.text('Missing or invalid title/artist', 400); } let title = body.title; let artist = body.artist; if(!existsSync("cache/" + title + " - " + artist + ".dfpwm")) { const searchResult = await ytSearch(`${artist} ${title}`); const video = searchResult.videos[0]; if (!video) throw new Error("No video found"); console.log(video) await $`${ytdlpPath} --audio-format opus -x ${video.url} -o test`; await $`ffmpeg -i test.opus -af "highpass=f=60, lowpass=f=15000, dynaudnorm" -ar 48000 -ac 1 -f dfpwm "cache/${title} - ${artist}.dfpwm"`; rmSync("test.opus") } return c.body(readFileSync(`cache/${title} - ${artist}.dfpwm`), { headers: { 'Content-Type': 'audio/vnd.dfpwm', 'Content-Disposition': `attachment; filename="${title} - ${artist}.dfpwm"`, }, }); }) app.post('/render', async (c) => { const auth = c.req.header('Authorization') if (auth !== process.env.PASSWORD) { return c.text('Unauthorized', 401) } const body = await c.req.json().catch(() => null) let extraArgs = "-b" let filename; let size; if (body.size) { if (typeof body.size !== 'string' || !/^\d{1,4}x\d{1,4}$/.test(body.size)) { return c.text('size must be a string in the format x', 400); } const [w, h] = body.size.split('x').map(Number); if ( isNaN(w) || isNaN(h) || w < 1 || h < 1 || w > 1000 || h > 1000 ) { return c.text('size must be in the format x with max 1000x1000', 400); } size = { width: w, height: h }; extraArgs += ` -W ${w} -H ${h}`; } if(body?.extraArgs) { if (typeof body.extraArgs !== 'string') { return c.text('extraArgs must be a string', 400) } extraArgs = body.extraArgs; } if(body.emoji) { if(size) { const inputSize = Math.min(size.width, size.height); const allowedSizes = [32, 64, 128]; let closest = allowedSizes.reduce((prev, curr) => Math.abs(curr - inputSize) < Math.abs(prev - inputSize) ? curr : prev ); joypixels.emojiSize = closest; } const emojiHtml = joypixels.toImage(body.emoji) const urlMatch = emojiHtml.match(/src="([^"]*)"/) if (!urlMatch) { return c.text('Could not extract emoji URL', 500) } let emojiUrl = urlMatch[1] console.log(emojiUrl) filename = "cache/" + emojiUrl.split('/').pop().split(".")[0] + `-${size ? body.size : joypixels.emojiSize}.png`; if(!existsSync(filename)) { // Download the image const res = await fetch(emojiUrl) if (!res.ok) { return c.text('Failed to download emoji image', 500) } const arrayBuffer = await res.arrayBuffer() const buffer = Buffer.from(arrayBuffer) // Ensure cache directory exists if (!existsSync('cache')) { mkdirSync('cache') } // Get filename from URL writeFileSync(filename, buffer) } } else if(body.imageUrl) { const imageUrl = body.imageUrl; filename = `cache/${imageUrl.split('/').pop()}-${size ? body.size : "original"}`; if (!existsSync(filename)) { const res = await fetch(imageUrl); if (!res.ok) { return c.text('Failed to download image', 500); } const arrayBuffer = await res.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); if (!existsSync('cache')) { mkdirSync('cache'); } writeFileSync(filename, buffer); } } else { return c.text('Please provide either emoji or imageUrl', 400); } if(!existsSync(filename+".bimg")) { let sanjuuniPath = "sanjuuni"; if(existsSync("./sanjuuni")) { sanjuuniPath = "./sanjuuni"; } console.log(`${sanjuuniPath} --disable-opencl ${extraArgs} -i ${filename} -o ${filename+".bimg"}`) await $`${sanjuuniPath} --disable-opencl ${extraArgs} -i ${filename} -o ${filename+".bimg"}` } const bimg = readFileSync(filename + ".bimg", "utf8"); return c.text(bimg) }) export default { port: 7427, host: "127.0.0.1", fetch: app.fetch, }