|
import bytes from 'bytes' |
|
import carbon from 'carbon-now-scraper' |
|
import cp from 'child_process' |
|
import express from 'express' |
|
import favicon from 'serve-favicon' |
|
import fs from 'fs' |
|
import morgan from 'morgan' |
|
import os from 'os' |
|
import path from 'path' |
|
import PDFDocument from 'pdfkit' |
|
import sharp from 'sharp' |
|
import util from 'util' |
|
import ytdl from 'ytdl-core' |
|
import yts from 'yt-search' |
|
import axios from 'axios' |
|
const app = express() |
|
const tmpDir = os.tmpdir() |
|
|
|
app.set('json spaces', 4) |
|
app.use(express.json({ limit: '200mb' })) |
|
app.use(express.urlencoded({ extended: true, limit: '200mb' })) |
|
app.use(favicon(path.join(import.meta.dirname, 'favicon.ico'))) |
|
app.use(morgan('combined')) |
|
|
|
app.use((_, __, next) => { |
|
fs.readdirSync(tmpDir).map((file) => { |
|
file = `${tmpDir}/${file}` |
|
const stat = fs.statSync(file) |
|
const exp = Date.now() - stat.mtimeMs >= 1000 * 60 * 30 |
|
if (stat.isFile() && exp) { |
|
console.log('Deleted file', file) |
|
fs.unlinkSync(file) |
|
} |
|
}) |
|
next() |
|
}) |
|
|
|
app.use('/file', express.static(tmpDir)) |
|
|
|
app.all('/', (_, res) => { |
|
const status = {} |
|
status['diskUsage'] = cp.execSync('du -sh').toString().split('M')[0] + ' MB' |
|
|
|
const used = process.memoryUsage() |
|
for (let x in used) status[x] = formatSize(used[x]) |
|
|
|
const totalmem = os.totalmem() |
|
const freemem = os.freemem() |
|
status['memoryUsage'] = `${formatSize(totalmem - freemem)} / ${formatSize(totalmem)}` |
|
|
|
res.json({ |
|
creator: `@${process.env['SPACE_AUTHOR_NAME'] || 'rippanteq7'}`, |
|
message: 'Hello World!', |
|
uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4], |
|
status |
|
}) |
|
}) |
|
|
|
app.all('/carbon', async (req, res) => { |
|
if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) |
|
|
|
try { |
|
const obj = req.method !== 'GET' ? req.body : req.query |
|
if (!obj.code) return res.status(400).json({ success: false, message: 'Required parameter \'code\'' }) |
|
|
|
const filePath = `${tmpDir}/${randomName('.png')}` |
|
const image = await carbon(obj.code, filePath, { |
|
...obj, puppeteer: { executablePath: process.env.CHROME_BIN } |
|
}) |
|
const resultUrl = `https://${req.hostname}/${image.replace(tmpDir, 'file')}` |
|
isTrue(obj.json) ? res.json({ success: true, result: resultUrl }) : res[isTrue(obj.raw) ? 'send' : 'redirect'](resultUrl) |
|
} catch (e) { |
|
console.log(e) |
|
res.status(500).json({ error: true, message: getError(e) }) |
|
} |
|
}) |
|
app.get('/animagine', async (req, res) => { |
|
let { prompt, negative, model } = re.query |
|
if (!prompt) return res.send('give me prompt'); |
|
|
|
async function animagine(obj) { |
|
let o = generateHash(); |
|
let baseURI = "https://cagliostrolab-animagine-xl-3-1.hf.space/"; |
|
let models = ["(None)", "Cinematic", "Photographic", "Anime", "Manga", "Digital Art", "Pixel art", "Fantasy art", "Neonpunk", "3D Model"] |
|
.find(v => v.toLowerCase() == (obj.model || "(none)").toLowerCase()); |
|
|
|
const axiosInstance = axios.create({ |
|
baseURL: baseURI, |
|
headers: { |
|
"user-agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36", |
|
accept: "*/*", |
|
origin: "https://cagliostrolab-animagine-xl-3-1.hf.space", |
|
referer: "https://cagliostrolab-animagine-xl-3-1.hf.space/", |
|
"accept-language": "id,en-GB;q=0.9,en-US;q=0.8,en;q=0.7,jv;q=0.6,zh-TW;q=0.5,zh;q=0.4,am;q=0.3,ms;q=0.2,ja;q=0.1" |
|
} |
|
}); |
|
|
|
let see = async () => { |
|
try { |
|
let response = await axiosInstance.post("run/predict", { |
|
...o, |
|
"event_data": null, |
|
"fn_index": 4, |
|
"trigger_id": 49, |
|
"data": [0, true] |
|
}); |
|
let data = response.data.data; |
|
return { status: 200, seed: data.pop() }; |
|
} catch (e) { |
|
return { status: 200, seed: 24114393 }; |
|
} |
|
}; |
|
|
|
let process = async (obj) => { |
|
await axiosInstance.post("queue/join", { |
|
"data": [ |
|
obj.prompt, |
|
obj.negative || "painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured, nsfw, (low quality, worst quality:1.2), very displeasing, 3d, watermark, signature, ugly, poorly drawn", |
|
(await see()).seed, |
|
1024, 1024, 7, 28, "DPM++ 2M SDE Karras", "896 x 1152", models, "Light v3.1", false, 0.55, 1.5, true |
|
], |
|
...o, |
|
"event_data": null, |
|
"fn_index": 5, |
|
"trigger_id": 49 |
|
}); |
|
}; |
|
|
|
await process(obj); |
|
|
|
try { |
|
let response = await axiosInstance.get('queue/data?session_hash=' + o.session_hash); |
|
return response.data.split(/data\: /).filter(v => v.includes('process_completed')).map(v => JSON.parse(v)); |
|
} catch (e) { |
|
return { status: 500 }; |
|
} |
|
} |
|
|
|
function generateHash() { |
|
const chars = "qwertyuopasdfghjklizxcvbnm0123456789"; |
|
let hash = ""; |
|
for (let i = 0; i < 11; i++) { |
|
hash += chars[Math.floor(Math.random() * chars.length)]; |
|
} |
|
return { session_hash: hash, fn_index: 2 }; |
|
} |
|
return res.send(await imagine({prompt, negative, model})) |
|
}) |
|
|
|
app.all('/topdf', async (req, res) => { |
|
if (req.method !== 'POST') return res.status(405).json({ success: false, message: 'Method Not Allowed' }) |
|
|
|
try { |
|
const { images: urls, json, raw } = req.body |
|
if (!urls) return res.status(400).json({ success: false, message: 'Payload \'images\' requires an array of urls' }) |
|
if (!Array.isArray(urls)) urls = [urls] |
|
|
|
const bufferPDF = await toPDF(urls) |
|
if (!bufferPDF.length) return res.status(400).json({ success: false, message: 'Can\'t convert to pdf' }) |
|
|
|
const fileName = randomName('.pdf') |
|
await fs.promises.writeFile(`${tmpDir}/${fileName}`, bufferPDF) |
|
|
|
const resultUrl = `https://${req.hostname}/file/${fileName}` |
|
isTrue(json) ? res.json({ success: true, result: resultUrl }) : res[isTrue(raw) ? 'send' : 'redirect'](resultUrl) |
|
} catch (e) { |
|
console.log(e) |
|
res.status(500).json({ error: true, message: getError(e) }) |
|
} |
|
}) |
|
|
|
app.all(/^\/webp2(gif|mp4|png)/, async (req, res) => { |
|
if (req.method !== 'POST') return res.status(405).json({ success: false, message: 'Method Not Allowed' }) |
|
|
|
try { |
|
const { file, json, raw } = req.body |
|
if (!file) return res.status(400).json({ success: false, message: 'Payload \'file\' requires base64 string' }) |
|
if (!isBase64(file)) return res.status(400).json({ success: false, message: 'Invalid base64 format' }) |
|
|
|
const type = req.params[0] |
|
if (type === 'png') { |
|
const fileName = randomName('.png') |
|
const fileBuffer = await sharp(Buffer.from(file, 'base64')).png().toBuffer() |
|
await fs.promises.writeFile(`${tmpDir}/${fileName}`, fileBuffer) |
|
|
|
const resultUrl = `https://${req.hostname}/file/${fileName}` |
|
isTrue(json) ? res.json({ success: true, result: resultUrl }) : res[isTrue(raw) ? 'send' : 'redirect'](resultUrl) |
|
return |
|
} else { |
|
const fileName = randomName('.webp') |
|
const filePath = `${tmpDir}/${fileName}` |
|
await fs.promises.writeFile(filePath, Buffer.from(file, 'base64')) |
|
|
|
const exec = util.promisify(cp.exec).bind(cp) |
|
await exec(`convert ${filePath} ${filePath.replace('webp', 'gif')}`) |
|
|
|
let resultUrl |
|
if (type === 'gif') resultUrl = `https://${req.hostname}/file/${fileName.replace('webp', 'gif')}` |
|
else { |
|
await exec(`ffmpeg -i ${filePath.replace('webp', 'gif')} -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" ${filePath.replace('webp', 'mp4')}`) |
|
resultUrl = `https://${req.hostname}/file/${fileName.replace('webp', 'mp4')}` |
|
} |
|
|
|
isTrue(json) ? res.json({ success: true, result: resultUrl }) : res[isTrue(raw) ? 'send' : 'redirect'](resultUrl) |
|
} |
|
} catch (e) { |
|
console.log(e) |
|
res.status(500).json({ error: true, message: getError(e) }) |
|
} |
|
}) |
|
|
|
|
|
app.all(/^\/y(outube|t)(\/(d(ownload|l)|search)?)?/, async (req, res) => { |
|
if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) |
|
|
|
try { |
|
const type = req.params[2] || '' |
|
|
|
const obj = req.method !== 'GET' ? req.body : req.query |
|
if (type === 'search') { |
|
if (!obj.query) return res.status(400).json({ success: false, message: 'Required parameter \'query\'' }) |
|
|
|
const result = await yts(obj) |
|
if (!(result.all?.length || result?.url)) return res.status(400).json({ success: false, message: 'Video unavailable' }) |
|
|
|
res.json({ success: true, result }) |
|
return |
|
} else if (['dl', 'download'].includes(type)) { |
|
if (!obj.url) return res.status(400).json({ success: false, message: 'Required parameter \'url\'' }) |
|
if (!ytdl.validateURL(obj.url)) return res.status(400).json({ success: false, message: 'Invalid url' }) |
|
|
|
|
|
const stream = ytdl(obj.url, obj) |
|
stream.on('error', (e) => { |
|
console.log(e) |
|
res.status(500).json({ error: true, message: getError(e) }) |
|
}) |
|
|
|
stream.on('info', async (info, formats) => { |
|
const req = await fetch(formats.url, { method: 'HEAD' }) |
|
const contentLength = req.headers.get('content-length') || formats.contentLength |
|
const fileName = `${encodeURIComponent(info.videoDetails.title)}.${formats.container}` |
|
res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`) |
|
res.setHeader('Content-Length', contentLength || 0) |
|
res.setHeader('Content-Type', formats.mimeType) |
|
stream.pipe(res) |
|
}) |
|
|
|
return |
|
} else { |
|
if (!obj.query) return res.status(400).json({ success: false, message: 'Required parameter \'query\'' }) |
|
|
|
let result = await yts(ytdl.validateURL(obj.query) ? { videoId: ytdl.getVideoID(obj.query) } : obj.query) |
|
result = result.videos ? result.videos[0] : result |
|
if (!result?.url) return res.status(400).json({ success: false, message: 'Video unavailable' }) |
|
|
|
const dlUrl = `https://${req.hostname}/yt/dl?url=${result.url}` |
|
const download = { |
|
audio: `${dlUrl}&filter=audioonly&quality=highestaudio`, |
|
video: `${dlUrl}&quality=highestvideo` |
|
} |
|
res.json({ |
|
success: true, |
|
result: { ...result, download } |
|
}) |
|
} |
|
} catch (e) { |
|
console.log(e) |
|
res.status(500).json({ error: true, message: getError(e) }) |
|
} |
|
}) |
|
|
|
app.listen(7860, () => console.log('App running on port 7860')) |
|
|
|
function formatSize(n) { |
|
return bytes(+n, { unitSeparator: ' ' }) |
|
} |
|
|
|
function getError(e) { |
|
e = String(e) |
|
return e !== '[object Object]' ? e : 'Internal Server Error' |
|
} |
|
|
|
function isBase64(str) { |
|
try { |
|
return btoa(atob(str)) === str |
|
} catch { |
|
return false |
|
} |
|
} |
|
|
|
function isTrue(str) { |
|
return [true, 'true'].includes(str) |
|
} |
|
|
|
function randomName(ext = '') { |
|
return Math.random().toString(36).slice(2) + ext |
|
} |
|
|
|
function toPDF(urls) { |
|
return new Promise(async (resolve, reject) => { |
|
try { |
|
const doc = new PDFDocument({ margin: 0, size: 'A4' }) |
|
const buffs = [] |
|
|
|
for (let x = 0; x < urls.length; x++) { |
|
if (!/https:\/\//.test(urls[x])) continue |
|
const url = new URL(urls[x]) |
|
let image = await fetch(url.toString(), { headers: { referer: url.origin } }) |
|
if (!image.ok) continue |
|
|
|
const type = image.headers.get('content-type') |
|
if (!/image/.test(type)) continue |
|
image = Buffer.from(await image.arrayBuffer()) |
|
if (/(gif|webp)$/.test(type)) image = await sharp(image).png().toBuffer() |
|
|
|
doc.image(image, 0, 0, { fit: [595.28, 841.89], align: 'center', valign: 'center' }) |
|
if (urls.length != x + 1) doc.addPage() |
|
} |
|
|
|
doc.on('data', (chunk) => buffs.push(chunk)) |
|
doc.on('end', () => resolve(Buffer.concat(buffs))) |
|
doc.on('error', (err) => reject(err)) |
|
doc.end() |
|
} catch (e) { |
|
console.log(e) |
|
reject(e) |
|
} |
|
}) |
|
} |
|
|