rippanteq7 commited on
Commit
3c6a32a
·
verified ·
1 Parent(s): 7ee0f64

Create index.js

Browse files
Files changed (1) hide show
  1. index.js +187 -0
index.js ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import bytes from 'bytes'
2
+ import carbon from 'carbon-now-scraper'
3
+ import cp from 'child_process'
4
+ import express from 'express'
5
+ import fs from 'fs'
6
+ import morgan from 'morgan'
7
+ import os from 'os'
8
+ import PDFDocument from 'pdfkit'
9
+ import sharp from 'sharp'
10
+ import util from 'util'
11
+
12
+ const app = express()
13
+ const tmpDir = os.tmpdir()
14
+
15
+ app.set('json spaces', 4)
16
+ app.use(morgan('dev'))
17
+ app.use(express.json({ limit: '200mb' }))
18
+ app.use(express.urlencoded({ extended: true, limit: '200mb' }))
19
+
20
+ app.use((_, __, next) => {
21
+ fs.readdirSync(tmpDir).map((file) => {
22
+ file = `${tmpDir}/${file}`
23
+ const stat = fs.statSync(file)
24
+ const exp = Date.now() - stat.mtimeMs >= 1000 * 60 * 30
25
+ if (stat.isFile() && exp) {
26
+ console.log('Deleted file', file)
27
+ fs.unlinkSync(file)
28
+ }
29
+ })
30
+ next()
31
+ })
32
+
33
+ app.use('/file', express.static(tmpDir))
34
+
35
+ app.all('/', (_, res) => {
36
+ const status = {}
37
+ status['diskUsage'] = cp.execSync('du -sh').toString().split('M')[0] + ' MB'
38
+
39
+ const used = process.memoryUsage()
40
+ for (let x in used) status[x] = formatSize(used[x])
41
+
42
+ const totalmem = os.totalmem()
43
+ const freemem = os.freemem()
44
+ status['memoryUsage'] = `${formatSize(totalmem - freemem)} / ${formatSize(totalmem)}`
45
+
46
+ res.json({
47
+ creator: `@${process.env['SPACE_AUTHOR_NAME'] || 'rippanteq7'}`,
48
+ message: 'Hello World!',
49
+ uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4],
50
+ status
51
+ })
52
+ })
53
+
54
+ app.all('/carbon', async (req, res) => {
55
+ if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' })
56
+
57
+ try {
58
+ const obj = req.method !== 'GET' ? req.body : req.query
59
+ if (!obj.code) return res.status(400).json({ success: false, message: 'Required parameter "code"' })
60
+
61
+ const filePath = `${tmpDir}/${randomName('.png')}`
62
+ const image = await carbon(obj.code, filePath, {
63
+ ...obj, puppeteer: { executablePath: process.env.CHROME_BIN }
64
+ })
65
+ const resultUrl = `https://${req.hostname}/${image.replace(tmpDir, 'file')}`
66
+ isTrue(obj.json) ? res.json({ success: true, result: resultUrl }) : res.send(resultUrl)
67
+ } catch (e) {
68
+ console.log(e)
69
+ res.status(500).json({ error: true, message: getError(e) })
70
+ }
71
+ })
72
+
73
+ app.all('/topdf', async (req, res) => {
74
+ if (req.method !== 'POST') return res.status(405).json({ success: false, message: 'Method Not Allowed' })
75
+
76
+ try {
77
+ const { images: urls, json } = req.body
78
+ if (!urls) return res.status(400).json({ success: false, message: 'Payload "images" requires an array of urls' })
79
+ if (!Array.isArray(urls)) urls = [urls]
80
+
81
+ const bufferPDF = await toPDF(urls)
82
+ if (!bufferPDF.length) return res.status(400).json({ success: false, message: 'Can\'t convert to pdf' })
83
+
84
+ const fileName = randomName('.pdf')
85
+ await fs.promises.writeFile(`${tmpDir}/${fileName}`, bufferPDF)
86
+
87
+ const resultUrl = `https://${req.hostname}/file/${fileName}`
88
+ isTrue(json) ? res.json({ success: true, result: resultUrl }) : res.send(resultUrl)
89
+ } catch (e) {
90
+ console.log(e)
91
+ res.status(500).json({ error: true, message: getError(e) })
92
+ }
93
+ })
94
+
95
+ app.all(/^\/webp2(gif|mp4|png)/, async (req, res) => {
96
+ if (req.method !== 'POST') return res.status(405).json({ success: false, message: 'Method Not Allowed' })
97
+
98
+ try {
99
+ const { file, json } = req.body
100
+ if (!file) return res.status(400).json({ success: false, message: 'Payload "file" requires base64 string' })
101
+ if (!isBase64(file)) return res.status(400).json({ success: false, message: 'Invalid base64 format' })
102
+
103
+ const type = req.params[0]
104
+ if (type === 'png') {
105
+ const fileName = randomName('.png')
106
+ const fileBuffer = await sharp(Buffer.from(file, 'base64')).png().toBuffer()
107
+ await fs.promises.writeFile(`${tmpDir}/${fileName}`, fileBuffer)
108
+
109
+ const resultUrl = `https://${req.hostname}/file/${fileName}`
110
+ isTrue(json) ? res.json({ success: true, result: resultUrl }) : res.send(resultUrl)
111
+ return
112
+ } else {
113
+ const fileName = randomName('.webp')
114
+ const filePath = `${tmpDir}/${fileName}`
115
+ await fs.promises.writeFile(filePath, Buffer.from(file, 'base64'))
116
+
117
+ const exec = util.promisify(cp.exec).bind(cp)
118
+ await exec(`convert ${filePath} ${filePath.replace('webp', 'gif')}`)
119
+
120
+ let resultUrl
121
+ if (type === 'gif') resultUrl = `https://${req.hostname}/file/${fileName.replace('webp', 'gif')}`
122
+ else {
123
+ 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')}`)
124
+ resultUrl = `https://${req.hostname}/file/${fileName.replace('webp', 'mp4')}`
125
+ }
126
+
127
+ isTrue(json) ? res.json({ success: true, result: resultUrl }) : res.send(resultUrl)
128
+ }
129
+ } catch (e) {
130
+ console.log(e)
131
+ res.status(500).json({ error: true, message: getError(e) })
132
+ }
133
+ })
134
+
135
+ app.listen(7860, () => console.log('App running on port 7860'))
136
+
137
+ function formatSize(n) {
138
+ return bytes(+n, { unitSeparator: ' ' })
139
+ }
140
+
141
+ function getError(e) {
142
+ e = String(e)
143
+ return e !== '[object Object]' ? e : 'Internal Server Error'
144
+ }
145
+
146
+ function isBase64(str) {
147
+ try {
148
+ return btoa(atob(str)) === str
149
+ } catch {
150
+ return false
151
+ }
152
+ }
153
+
154
+ function isTrue(str) {
155
+ return [true, 'true'].includes(str)
156
+ }
157
+
158
+ function randomName(ext = '') {
159
+ return Math.random().toString(36).slice(2) + ext
160
+ }
161
+
162
+ function toPDF(urls) {
163
+ return new Promise(async (resolve, reject) => {
164
+ const doc = new PDFDocument({ margin: 0, size: 'A4' })
165
+ const buffs = []
166
+
167
+ for (let x = 0; x < urls.length; x++) {
168
+ if (!/https:\/\//.test(urls[x])) continue
169
+ const url = new URL(urls[x])
170
+ let image = await fetch(url.toString(), { headers: { referer: url.origin } })
171
+ if (!image.ok) continue
172
+
173
+ const type = image.headers.get('content-type')
174
+ if (!/image/.test(type)) continue
175
+ image = Buffer.from(await image.arrayBuffer())
176
+ if (/(gif|webp)$/.test(type)) image = await sharp(image).png().toBuffer()
177
+
178
+ doc.image(image, 0, 0, { fit: [595.28, 841.89], align: 'center', valign: 'center' })
179
+ if (urls.length != x + 1) doc.addPage()
180
+ }
181
+
182
+ doc.on('data', (chunk) => buffs.push(chunk))
183
+ doc.on('end', () => resolve(Buffer.concat(buffs)))
184
+ doc.on('error', (err) => reject(err))
185
+ doc.end()
186
+ })
187
+ }