Spaces:
Running
Running
const fs = require('fs') | |
const os = require('os') | |
const util = require('util') | |
const axios = require('axios') | |
const bytes = require('bytes') | |
const sharp = require('sharp') | |
const morgan = require('morgan') | |
const express = require('express') | |
const cp = require('child_process') | |
const PDFDocument = require('pdfkit') | |
const playwright = require('playwright-extra') | |
// const stealth = require('puppeteer-extra-plugin-stealth') | |
// playwright.chromium.use(stealth()) | |
const app = express() | |
app.set('json spaces', 4) | |
app.use(morgan('dev')) | |
const limitSize = '500mb' | |
app.use(express.json({ limit: limitSize })) | |
app.use(express.urlencoded({ extended: true, limit: limitSize })) | |
const tmpFolder = os.tmpdir() | |
app.use((req, res, next) => { | |
fs.readdirSync(tmpFolder).map(file => { | |
file = `${tmpFolder}/${file}` | |
let stats = fs.statSync(file) | |
if (!stats.isFile()) return | |
if (Date.now() - stats.mtimeMs >= 1000 * 60 * 30) { | |
fs.unlinkSync(file) | |
console.log('Deleted file', file) | |
} | |
}) | |
next() | |
}) | |
app.use('/file', express.static(tmpFolder)) | |
app.all('/', (req, res) => { | |
const status = {} | |
const used = process.memoryUsage() | |
for (let key in used) status[key] = formatSize(used[key]) | |
const disk = cp.execSync('du -sh').toString().split('M')[0] | |
status.diskUsage = `${disk} MB` | |
const totalmem = os.totalmem() | |
const freemem = os.freemem() | |
status.memoryUsage = `${formatSize(totalmem - freemem)} / ${formatSize(totalmem)}` | |
res.json({ | |
creator: '@rippanteq7', | |
message: 'Hello World', | |
uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4], | |
status | |
}) | |
}) | |
app.all('/imagetopdf', async (req, res) => { | |
if (!['POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
try { | |
console.log(new Date().toLocaleString('id', { timeZone: 'Asia/Jakarta' }), '\n', req.body) | |
const { images } = req.body | |
if (!(images && Array.isArray(images))) return res.json({ success: false, message: 'Required an array image url' }) | |
const buffer = await toPDF(images) | |
res.setHeader('Content-Disposition', `attachment; filename=${Math.random().toString(36).slice(2)}.pdf`) | |
res.setHeader('Content-Type', 'application/pdf') | |
res.setHeader('Content-Length', buffer.byteLength) | |
res.send(buffer) | |
} catch (e) { | |
console.log(e) | |
e = String(e) | |
res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
} | |
}) | |
app.all('/webp2png', async (req, res) => { | |
if (!['POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
try { | |
const { file } = req.body | |
if (!(file && isBase64(file))) return res.json({ success: false, message: 'Payload body file must be filled in base64 format' }) | |
const fileBuffer = Buffer.from(file, 'base64') | |
const fileName = `${Math.random().toString(36).slice(2)}.png` | |
const convertData = await sharp(fileBuffer).png().toBuffer() | |
await fs.promises.writeFile(`${tmpFolder}/${fileName}`, convertData) | |
res.send(`https://${req.get('host')}/file/${fileName}`) | |
} catch (e) { | |
console.log(e) | |
e = String(e) | |
res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
} | |
}) | |
app.all(['/webp2gif', '/webp2mp4'], async (req, res) => { | |
if (!['POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
try { | |
const { file } = req.body | |
if (!(file && isBase64(file))) return res.json({ success: false, message: 'Payload body file must be filled in base64 format' }) | |
const fileBuffer = Buffer.from(file, 'base64') | |
const fileName = `${Math.random().toString(36).slice(2)}.webp` | |
const filePath = `${tmpFolder}/${fileName}` | |
await fs.promises.writeFile(filePath, fileBuffer) | |
const exec = util.promisify(cp.exec).bind(cp) | |
await exec(`convert ${filePath} ${filePath.replace('.webp', '.gif')}`) | |
if (/gif/.test(req.path)) return res.send(`https://${req.get('host')}/file/${fileName.replace('.webp', '.gif')}`) | |
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|.gif/g, '')}.mp4`) | |
res.send(`https://${req.get('host')}/file/${fileName.replace('.webp', '.mp4')}`) | |
} catch (e) { | |
console.log(e) | |
e = String(e) | |
res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
} | |
}) | |
app.all(['/enhance', '/hd', '/upscale'], async (req, res) => { | |
if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
try { | |
const { url } = req.method !== 'GET' ? req.body : req.query | |
if (!url) return res.json({ success: false, message: 'Required parameter url' }) | |
const result = await enhanceImage(url) | |
res.json({ success: true, result }) | |
} catch (e) { | |
console.log(e) | |
e = String(e) | |
res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
} | |
}) | |
app.all('/animelast', async (req, res) => { | |
const result = await scrapeAnimeInfo(); | |
res.json({ | |
creator: '@Kyouka', | |
message: 'Success', | |
uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4], | |
result | |
}); | |
}); | |
app.all('/stablediff/illusion', async (req, res) => { | |
if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
try { | |
const { | |
prompt, | |
negative_prompt = 'low quality', | |
image_url, | |
num_inference_steps = 25, | |
controlnet_conditioning_scale = 1 | |
} = req.method !== 'GET' ? req.body : req.query | |
if (!(prompt && image_url)) return res.json({ success: false, message: 'Required parameter prompt & image_url' }) | |
const headers = { | |
'Content-Type': 'application/json', | |
Authorization: `Key ${process.env.falAIKey}` | |
} | |
const { detail, response_url } = await (await fetch('https://54285744-illusion-diffusion.gateway.alpha.fal.ai/fal/queue/submit', { | |
method: 'POST', | |
body: JSON.stringify({ | |
prompt, negative_prompt, image_url, | |
num_inference_steps, controlnet_conditioning_scale | |
}), | |
headers | |
})).json() | |
if (detail) return res.json({ success: false, message: detail }) | |
let retry = 0 | |
while (true) { | |
await new Promise(resolve => setTimeout(resolve, 2500)) | |
const prediction = await (await fetch(response_url, { headers })).json() | |
console.log(prediction) | |
if (retry > 10) return res.json({ success: false, message: prediction.detail || 'Max retry has reached' }) | |
if (prediction.image) return res.json({ success: true, result: prediction }) | |
retry += 1 | |
} | |
} catch (e) { | |
console.log(e) | |
e = String(e) | |
res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
} | |
}) | |
const PORT = process.env.PORT || 7860 | |
app.listen(PORT, () => console.log('App running on port', PORT)) | |
function formatSize(num) { | |
return bytes(+num || 0, { unitSeparator: ' ' }) | |
} | |
function isBase64(str) { | |
try { | |
return btoa(atob(str)) === str | |
} catch { | |
return false | |
} | |
} | |
function toPDF(urls) { | |
return new Promise(async (resolve, reject) => { | |
try { | |
if (!Array.isArray(urls)) urls = [urls] | |
const doc = new PDFDocument({ margin: 0, size: 'A4' }) | |
const buffers = [] | |
for (let i = 0; i < urls.length; i++) { | |
const response = await fetch(urls[i], { headers: { referer: urls[i] }}) | |
if (!response.ok) continue | |
const type = response.headers.get('content-type') | |
if (!/image/.test(type)) continue | |
let buffer = Buffer.from(await response.arrayBuffer()) | |
if (/gif|webp/.test(type)) buffer = await sharp(buffer).png().toBuffer() | |
doc.image(buffer, 0, 0, { fit: [595.28, 841.89], align: 'center', valign: 'center' }) | |
if (urls.length !== i + 1) doc.addPage() | |
} | |
doc.on('data', (chunk) => buffers.push(chunk)) | |
doc.on('end', () => resolve(Buffer.concat(buffers))) | |
doc.on('error', reject) | |
doc.end() | |
} catch (e) { | |
console.log(e) | |
reject(e) | |
} | |
}) | |
} | |
async function scrapeAnimeInfo() { | |
const browser = await playwright.chromium.launch({ | |
headless: true, | |
executablePath: '/usr/bin/chromium', | |
args: ['--no-sandbox'] | |
}) | |
const page = await browser.newPage(); | |
const url = 'https://154.26.137.28/rilisan-anime-terbaru/'; | |
await page.goto(url); | |
await page.waitForSelector('.postbody'); | |
const articlesInfo = await page.$$eval('.postbody .is-anime', articles => { | |
return articles.map(article => { | |
const title = article.querySelector('h2').textContent.trim(); | |
const thumbnailUrl = article.querySelector('img').src; | |
const uploadTime = article.querySelector('span x-ts').textContent.trim(); | |
const episodeUrl = article.querySelector('a').href; | |
return { | |
title, | |
thumbnailUrl, | |
uploadTime, | |
episodeUrl | |
}; | |
}); | |
}); | |
await browser.close(); | |
return articlesInfo; | |
} | |
async function enhanceImage(url) { | |
const browser = await playwright.chromium.launch({ | |
headless: true, | |
executablePath: '/usr/bin/chromium', | |
args: ['--no-sandbox'] | |
}) | |
const page = await browser.newPage() | |
await page.goto('https://snapedit.app/id/enhance/upload') | |
await page.waitForLoadState('domcontentloaded') | |
const arrayBuffer = await (await fetch(url)).arrayBuffer() | |
page.on('filechooser', (fileChooser) => { | |
const fileObject = { | |
name: 'file.jpg', | |
mimeType: 'image/jpg', | |
buffer: Buffer.from(arrayBuffer) | |
} | |
fileChooser.setFiles([fileObject]) | |
}) | |
await page.getByRole('button', { name: 'Unggah gambar', exact: true }).click() | |
const response = await page.waitForResponse(res => { | |
console.log(res.url()) | |
return res.url().includes('api/enhance/v1') | |
}, { timeout: 60 * 1000 }) | |
const json = await response.json() | |
await browser.close() | |
return json | |
} |