new commit
This commit is contained in:
commit
a66a344cc0
6 changed files with 199 additions and 0 deletions
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# dependencies (bun install)
|
||||
node_modules
|
||||
|
||||
# output
|
||||
out
|
||||
dist
|
||||
*.tgz
|
||||
|
||||
# code coverage
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# logs
|
||||
logs
|
||||
_.log
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# caches
|
||||
.eslintcache
|
||||
.cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# IntelliJ based IDEs
|
||||
.idea
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
cache/
|
||||
15
README.md
Normal file
15
README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# sanjuuni-api
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run:
|
||||
|
||||
```bash
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
This project was created using `bun init` in bun v1.2.13. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
||||
37
bun.lock
Normal file
37
bun.lock
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "sanjuuni-api",
|
||||
"dependencies": {
|
||||
"emoji-toolkit": "^9.0.1",
|
||||
"hono": "^4.8.4",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||
|
||||
"@types/node": ["@types/node@24.0.12", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-LtOrbvDf5ndC9Xi+4QZjVL0woFymF/xSTKZKPgrrl7H7XoeDvnD+E2IclKVDyaK9UM756W/3BXqSU+JEHopA9g=="],
|
||||
|
||||
"@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="],
|
||||
|
||||
"bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"emoji-toolkit": ["emoji-toolkit@9.0.1", "", {}, "sha512-sMMNqKNLVHXJfIKoPbrRJwtYuysVNC9GlKetr72zE3SSVbHqoeDLWVrxP0uM0AE0qvdl3hbUk+tJhhwXZrDHaw=="],
|
||||
|
||||
"hono": ["hono@4.8.4", "", {}, "sha512-KOIBp1+iUs0HrKztM4EHiB2UtzZDTBihDtOF5K6+WaJjCPeaW4Q92R8j63jOhvJI5+tZSMuKD9REVEXXY9illg=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||
}
|
||||
}
|
||||
68
index.ts
Normal file
68
index.ts
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import { Hono } from 'hono'
|
||||
const app = new Hono()
|
||||
const joypixels = require("emoji-toolkit");
|
||||
import { mkdirSync, writeFileSync, existsSync, exists, readFileSync } from 'fs'
|
||||
import { $ } from 'bun';
|
||||
|
||||
|
||||
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)
|
||||
if (!body?.emoji) {
|
||||
return c.text('Missing emoji in body', 400)
|
||||
}
|
||||
|
||||
let extraArgs = "-b"
|
||||
|
||||
if(body?.extraArgs) {
|
||||
if (typeof body.extraArgs !== 'string') {
|
||||
return c.text('extraArgs must be a string', 400)
|
||||
}
|
||||
extraArgs = body.extraArgs;
|
||||
}
|
||||
|
||||
const emojiHtml = joypixels.toImage(body.emoji)
|
||||
const urlMatch = emojiHtml.match(/src="([^"]*)"/)
|
||||
if (!urlMatch) {
|
||||
return c.text('Could not extract emoji URL', 500)
|
||||
}
|
||||
const emojiUrl = urlMatch[1]
|
||||
|
||||
const filename = "cache/" + emojiUrl.split('/').pop() ;
|
||||
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)
|
||||
}
|
||||
|
||||
if(!existsSync(filename+".bimg")) {
|
||||
await $`sanjuuni --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,
|
||||
}
|
||||
16
package.json
Normal file
16
package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "sanjuuni-api",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"emoji-toolkit": "^9.0.1",
|
||||
"hono": "^4.8.4"
|
||||
}
|
||||
}
|
||||
28
tsconfig.json
Normal file
28
tsconfig.json
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
// Environment setup & latest features
|
||||
"lib": ["ESNext"],
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue