aseli commited on
Commit
35dc92a
1 Parent(s): ba63c9f

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +321 -134
index.js CHANGED
@@ -17,8 +17,13 @@ const app = express()
17
  const tmpDir = os.tmpdir()
18
 
19
  app.set('json spaces', 4)
20
- app.use(express.json({ limit: '200mb' }))
21
- app.use(express.urlencoded({ extended: true, limit: '200mb' }))
 
 
 
 
 
22
  app.use(favicon(path.join(import.meta.dirname, 'favicon.ico')))
23
  app.use(morgan('combined'))
24
 
@@ -40,14 +45,14 @@ app.use('/file', express.static(tmpDir))
40
  app.all('/', (_, res) => {
41
  const status = {}
42
  status['diskUsage'] = cp.execSync('du -sh').toString().split('M')[0] + ' MB'
43
-
44
  const used = process.memoryUsage()
45
  for (let x in used) status[x] = formatSize(used[x])
46
-
47
  const totalmem = os.totalmem()
48
  const freemem = os.freemem()
49
  status['memoryUsage'] = `${formatSize(totalmem - freemem)} / ${formatSize(totalmem)}`
50
-
51
  res.json({
52
  creator: `@${process.env['SPACE_AUTHOR_NAME'] || 'rippanteq7'}`,
53
  message: 'Hello World!',
@@ -57,188 +62,343 @@ app.all('/', (_, res) => {
57
  })
58
 
59
  app.all('/carbon', async (req, res) => {
60
- if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' })
61
-
 
 
 
62
  try {
63
  const obj = req.method !== 'GET' ? req.body : req.query
64
- if (!obj.code) return res.status(400).json({ success: false, message: 'Required parameter \'code\'' })
65
-
 
 
 
66
  const filePath = `${tmpDir}/${randomName('.png')}`
67
  const image = await carbon(obj.code, filePath, {
68
- ...obj, puppeteer: { executablePath: process.env.CHROME_BIN }
 
 
 
69
  })
70
  const resultUrl = `https://${req.hostname}/${image.replace(tmpDir, 'file')}`
71
- isTrue(obj.json) ? res.json({ success: true, result: resultUrl }) : res[isTrue(obj.raw) ? 'send' : 'redirect'](resultUrl)
 
 
 
72
  } catch (e) {
73
  console.log(e)
74
- res.status(500).json({ error: true, message: getError(e) })
 
 
 
75
  }
76
  })
77
  app.get('/animagine', async (req, res) => {
78
- let { prompt, negative, model } = req.query
 
 
 
 
79
  if (!prompt) return res.send('give me prompt');
80
-
81
- async function animagine(obj) {
82
- let o = generateHash();
83
- let baseURI = "https://cagliostrolab-animagine-xl-3-1.hf.space/";
84
- let models = ["(None)", "Cinematic", "Photographic", "Anime", "Manga", "Digital Art", "Pixel art", "Fantasy art", "Neonpunk", "3D Model"]
85
- .find(v => v.toLowerCase() == (obj.model || "(none)").toLowerCase());
86
-
87
- const axiosInstance = axios.create({
88
- baseURL: baseURI,
89
- headers: {
90
- "user-agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
91
- accept: "*/*",
92
- origin: "https://cagliostrolab-animagine-xl-3-1.hf.space",
93
- referer: "https://cagliostrolab-animagine-xl-3-1.hf.space/",
94
- "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"
95
- }
96
- });
97
-
98
- let see = async () => {
99
- try {
100
- let response = await axiosInstance.post("run/predict", {
101
- ...o,
102
- "event_data": null,
103
- "fn_index": 4,
104
- "trigger_id": 49,
105
- "data": [0, true]
106
- });
107
- let data = response.data.data;
108
- return { status: 200, seed: data.pop() };
109
- } catch (e) {
110
- return { status: 200, seed: 24114393 };
111
- }
112
- };
113
-
114
- let process = async (obj) => {
115
- await axiosInstance.post("queue/join", {
116
- "data": [
117
- obj.prompt,
118
- 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",
119
- (await see()).seed,
120
- 1024, 1024, 7, 28, "DPM++ 2M SDE Karras", "896 x 1152", models, "Light v3.1", false, 0.55, 1.5, true
121
- ],
122
- ...o,
123
- "event_data": null,
124
- "fn_index": 5,
125
- "trigger_id": 49
126
- });
127
-
128
- };
129
- await process(obj);
130
- console.log('processinv')
131
- try {
132
- let response = await axiosInstance.get('queue/data?session_hash=' + o.session_hash);
133
- console.log(" process done")
134
- return response.data.split(/data\: /).filter(v => v.includes('process_completed')).map(v => JSON.parse(v));
135
- } catch (e) {
136
- return { status: 500 };
137
- }
138
- }
139
 
140
- function generateHash() {
141
- const chars = "qwertyuopasdfghjklizxcvbnm0123456789";
142
- let hash = "";
143
- for (let i = 0; i < 11; i++) {
144
- hash += chars[Math.floor(Math.random() * chars.length)];
145
- }
146
- return { session_hash: hash, fn_index: 2 };
147
- }
148
- return res.send(await animagine({prompt, negative, model}))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  })
150
 
151
  app.all('/topdf', async (req, res) => {
152
- if (req.method !== 'POST') return res.status(405).json({ success: false, message: 'Method Not Allowed' })
153
-
 
 
 
154
  try {
155
- const { images: urls, json, raw } = req.body
156
- if (!urls) return res.status(400).json({ success: false, message: 'Payload \'images\' requires an array of urls' })
 
 
 
 
 
 
 
157
  if (!Array.isArray(urls)) urls = [urls]
158
-
159
  const bufferPDF = await toPDF(urls)
160
- if (!bufferPDF.length) return res.status(400).json({ success: false, message: 'Can\'t convert to pdf' })
161
-
 
 
 
162
  const fileName = randomName('.pdf')
163
  await fs.promises.writeFile(`${tmpDir}/${fileName}`, bufferPDF)
164
-
165
  const resultUrl = `https://${req.hostname}/file/${fileName}`
166
- isTrue(json) ? res.json({ success: true, result: resultUrl }) : res[isTrue(raw) ? 'send' : 'redirect'](resultUrl)
 
 
 
167
  } catch (e) {
168
  console.log(e)
169
- res.status(500).json({ error: true, message: getError(e) })
 
 
 
170
  }
171
  })
172
 
173
  app.all(/^\/webp2(gif|mp4|png)/, async (req, res) => {
174
- if (req.method !== 'POST') return res.status(405).json({ success: false, message: 'Method Not Allowed' })
175
-
 
 
 
176
  try {
177
- const { file, json, raw } = req.body
178
- if (!file) return res.status(400).json({ success: false, message: 'Payload \'file\' requires base64 string' })
179
- if (!isBase64(file)) return res.status(400).json({ success: false, message: 'Invalid base64 format' })
180
-
 
 
 
 
 
 
 
 
 
 
181
  const type = req.params[0]
182
  if (type === 'png') {
183
  const fileName = randomName('.png')
184
  const fileBuffer = await sharp(Buffer.from(file, 'base64')).png().toBuffer()
185
  await fs.promises.writeFile(`${tmpDir}/${fileName}`, fileBuffer)
186
-
187
  const resultUrl = `https://${req.hostname}/file/${fileName}`
188
- isTrue(json) ? res.json({ success: true, result: resultUrl }) : res[isTrue(raw) ? 'send' : 'redirect'](resultUrl)
 
 
 
189
  return
190
  } else {
191
  const fileName = randomName('.webp')
192
  const filePath = `${tmpDir}/${fileName}`
193
  await fs.promises.writeFile(filePath, Buffer.from(file, 'base64'))
194
-
195
  const exec = util.promisify(cp.exec).bind(cp)
196
  await exec(`convert ${filePath} ${filePath.replace('webp', 'gif')}`)
197
-
198
  let resultUrl
199
  if (type === 'gif') resultUrl = `https://${req.hostname}/file/${fileName.replace('webp', 'gif')}`
200
  else {
201
  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')}`)
202
  resultUrl = `https://${req.hostname}/file/${fileName.replace('webp', 'mp4')}`
203
  }
204
-
205
- isTrue(json) ? res.json({ success: true, result: resultUrl }) : res[isTrue(raw) ? 'send' : 'redirect'](resultUrl)
 
 
 
206
  }
207
  } catch (e) {
208
  console.log(e)
209
- res.status(500).json({ error: true, message: getError(e) })
 
 
 
210
  }
211
  })
212
 
213
  // /yt /yt/ /yt/dl /yt/download /yt/search /youtube/dl /youtube/download /youtube/search
214
  app.all(/^\/y(outube|t)(\/(d(ownload|l)|search)?)?/, async (req, res) => {
215
- if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' })
216
-
 
 
 
217
  try {
218
  const type = req.params[2] || ''
219
-
220
  const obj = req.method !== 'GET' ? req.body : req.query
221
  if (type === 'search') {
222
- if (!obj.query) return res.status(400).json({ success: false, message: 'Required parameter \'query\'' })
223
-
 
 
 
224
  const result = await yts(obj)
225
- if (!(result.all?.length || result?.url)) return res.status(400).json({ success: false, message: 'Video unavailable' })
226
-
227
- res.json({ success: true, result })
 
 
 
 
 
 
228
  return
229
  } else if (['dl', 'download'].includes(type)) {
230
- if (!obj.url) return res.status(400).json({ success: false, message: 'Required parameter \'url\'' })
231
- if (!ytdl.validateURL(obj.url)) return res.status(400).json({ success: false, message: 'Invalid url' })
232
-
 
 
 
 
 
 
233
  // obj.filter = 'audioandvideo'
234
  const stream = ytdl(obj.url, obj)
235
  stream.on('error', (e) => {
236
  console.log(e)
237
- res.status(500).json({ error: true, message: getError(e) })
 
 
 
238
  })
239
-
240
  stream.on('info', async (info, formats) => {
241
- const req = await fetch(formats.url, { method: 'HEAD' })
 
 
242
  const contentLength = req.headers.get('content-length') || formats.contentLength
243
  const fileName = `${encodeURIComponent(info.videoDetails.title)}.${formats.container}`
244
  res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`)
@@ -249,12 +409,20 @@ app.all(/^\/y(outube|t)(\/(d(ownload|l)|search)?)?/, async (req, res) => {
249
  // stream.pipe(res)
250
  return
251
  } else {
252
- if (!obj.query) return res.status(400).json({ success: false, message: 'Required parameter \'query\'' })
253
-
254
- let result = await yts(ytdl.validateURL(obj.query) ? { videoId: ytdl.getVideoID(obj.query) } : obj.query)
 
 
 
 
 
255
  result = result.videos ? result.videos[0] : result
256
- if (!result?.url) return res.status(400).json({ success: false, message: 'Video unavailable' })
257
-
 
 
 
258
  const dlUrl = `https://${req.hostname}/yt/dl?url=${result.url}`
259
  const download = {
260
  audio: `${dlUrl}&filter=audioonly&quality=highestaudio`,
@@ -262,19 +430,27 @@ app.all(/^\/y(outube|t)(\/(d(ownload|l)|search)?)?/, async (req, res) => {
262
  }
263
  res.json({
264
  success: true,
265
- result: { ...result, download }
 
 
 
266
  })
267
  }
268
  } catch (e) {
269
  console.log(e)
270
- res.status(500).json({ error: true, message: getError(e) })
 
 
 
271
  }
272
  })
273
 
274
  app.listen(7860, () => console.log('App running on port 7860'))
275
 
276
  function formatSize(n) {
277
- return bytes(+n, { unitSeparator: ' ' })
 
 
278
  }
279
 
280
  function getError(e) {
@@ -301,24 +477,35 @@ function randomName(ext = '') {
301
  function toPDF(urls) {
302
  return new Promise(async (resolve, reject) => {
303
  try {
304
- const doc = new PDFDocument({ margin: 0, size: 'A4' })
 
 
 
305
  const buffs = []
306
-
307
  for (let x = 0; x < urls.length; x++) {
308
  if (!/https:\/\//.test(urls[x])) continue
309
  const url = new URL(urls[x])
310
- let image = await fetch(url.toString(), { headers: { referer: url.origin } })
 
 
 
 
311
  if (!image.ok) continue
312
-
313
  const type = image.headers.get('content-type')
314
  if (!/image/.test(type)) continue
315
  image = Buffer.from(await image.arrayBuffer())
316
  if (/(gif|webp)$/.test(type)) image = await sharp(image).png().toBuffer()
317
-
318
- doc.image(image, 0, 0, { fit: [595.28, 841.89], align: 'center', valign: 'center' })
 
 
 
 
319
  if (urls.length != x + 1) doc.addPage()
320
  }
321
-
322
  doc.on('data', (chunk) => buffs.push(chunk))
323
  doc.on('end', () => resolve(Buffer.concat(buffs)))
324
  doc.on('error', (err) => reject(err))
@@ -328,4 +515,4 @@ function toPDF(urls) {
328
  reject(e)
329
  }
330
  })
331
- }
 
17
  const tmpDir = os.tmpdir()
18
 
19
  app.set('json spaces', 4)
20
+ app.use(express.json({
21
+ limit: '200mb'
22
+ }))
23
+ app.use(express.urlencoded({
24
+ extended: true,
25
+ limit: '200mb'
26
+ }))
27
  app.use(favicon(path.join(import.meta.dirname, 'favicon.ico')))
28
  app.use(morgan('combined'))
29
 
 
45
  app.all('/', (_, res) => {
46
  const status = {}
47
  status['diskUsage'] = cp.execSync('du -sh').toString().split('M')[0] + ' MB'
48
+
49
  const used = process.memoryUsage()
50
  for (let x in used) status[x] = formatSize(used[x])
51
+
52
  const totalmem = os.totalmem()
53
  const freemem = os.freemem()
54
  status['memoryUsage'] = `${formatSize(totalmem - freemem)} / ${formatSize(totalmem)}`
55
+
56
  res.json({
57
  creator: `@${process.env['SPACE_AUTHOR_NAME'] || 'rippanteq7'}`,
58
  message: 'Hello World!',
 
62
  })
63
 
64
  app.all('/carbon', async (req, res) => {
65
+ if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({
66
+ success: false,
67
+ message: 'Method Not Allowed'
68
+ })
69
+
70
  try {
71
  const obj = req.method !== 'GET' ? req.body : req.query
72
+ if (!obj.code) return res.status(400).json({
73
+ success: false,
74
+ message: 'Required parameter \'code\''
75
+ })
76
+
77
  const filePath = `${tmpDir}/${randomName('.png')}`
78
  const image = await carbon(obj.code, filePath, {
79
+ ...obj,
80
+ puppeteer: {
81
+ executablePath: process.env.CHROME_BIN
82
+ }
83
  })
84
  const resultUrl = `https://${req.hostname}/${image.replace(tmpDir, 'file')}`
85
+ isTrue(obj.json) ? res.json({
86
+ success: true,
87
+ result: resultUrl
88
+ }) : res[isTrue(obj.raw) ? 'send' : 'redirect'](resultUrl)
89
  } catch (e) {
90
  console.log(e)
91
+ res.status(500).json({
92
+ error: true,
93
+ message: getError(e)
94
+ })
95
  }
96
  })
97
  app.get('/animagine', async (req, res) => {
98
+ let {
99
+ prompt,
100
+ negative,
101
+ model
102
+ } = req.query
103
  if (!prompt) return res.send('give me prompt');
104
+ async function animagine(obj) {
105
+ let o = generateHash();
106
+ let baseURI = "https://cagliostrolab-animagine-xl-3-1.hf.space/";
107
+ let models = ["(None)", "Cinematic", "Photographic", "Anime", "Manga", "Digital Art", "Pixel art", "Fantasy art", "Neonpunk", "3D Model"]
108
+ .find(v => v.toLowerCase() == (obj.model || "(none)").toLowerCase());
109
+ let ips = getRandomPrivateIP();
110
+ const axiosInstance = axios.create({
111
+ baseURL: baseURI,
112
+ headers: {
113
+ "user-agent": "WhatsApp/2.23.20.0",
114
+ accept: "*/*",
115
+ origin: "https://cagliostrolab-animagine-xl-3-1.hf.space",
116
+ referer: "https://cagliostrolab-animagine-xl-3-1.hf.space/",
117
+ "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",
118
+ "X-Real-Client-IP": ips,
119
+ "X-Real-IP": ips,
120
+ "X-Remote-Addr": ips,
121
+ "X-Remote-IP": ips,
122
+ "X-Forwarder": ips,
123
+ "X-Forwarder-For": ips,
124
+ "X-Forwarder-Host": ips,
125
+ "X-Forwarding": ips,
126
+ "X-Forwarding-For": ips,
127
+ "Forwarded": ips,
128
+ "Forwarded-For": ips,
129
+ "Forwarded-Host": ips,
130
+ }
131
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
+ function getRandomPrivateIP() {
134
+ const privateIPRanges = [
135
+ "10.0.0.0/8",
136
+ "172.16.0.0/12",
137
+ "192.168.0.0/16"
138
+ ];
139
+
140
+ const randomIPRange = privateIPRanges[Math.floor(Math.random() * privateIPRanges.length)];
141
+
142
+ const ipParts = randomIPRange.split("/");
143
+ const ipPrefix = ipParts[0].split(".");
144
+ const subnetMask = parseInt(ipParts[1], 10);
145
+ for (let i = 0; i < 4; i++) {
146
+ if (subnetMask >= 8) {
147
+ ipPrefix[i] = Math.floor(Math.random() * 256);
148
+
149
+ } else if (subnetMask > 0) {
150
+ const remainingBits = 8 - subnetMask;
151
+ const randomBits = Math.floor(Math.random() * (1 << remainingBits));
152
+ ipPrefix[i] &= ~(255 >> subnetMask);
153
+ ipPrefix[i] |= randomBits;
154
+ subnetMask -= remainingBits;
155
+ } else {
156
+ ipPrefix[i] = 0;
157
+ }
158
+ }
159
+
160
+ return ipPrefix.join(".");
161
+ }
162
+
163
+
164
+ let see = async () => {
165
+ try {
166
+ let response = await axiosInstance.post("run/predict", {
167
+ ...o,
168
+ "event_data": null,
169
+ "fn_index": 4,
170
+ "trigger_id": 49,
171
+ "data": [0, true]
172
+ });
173
+ let data = response.data.data;
174
+ return {
175
+ status: 200,
176
+ seed: data.pop()
177
+ };
178
+ } catch (e) {
179
+ return {
180
+ status: 200,
181
+ seed: 24114393
182
+ };
183
+ }
184
+ };
185
+
186
+ let process = async (obj) => {
187
+ await axiosInstance.post("queue/join", {
188
+ "data": [
189
+ obj.prompt,
190
+ 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",
191
+ (await see()).seed,
192
+ 1024, 1024, 7, 28, "DPM++ 2M SDE Karras", "896 x 1152", models, "Light v3.1", false, 0.55, 1.5, true
193
+ ],
194
+ ...o,
195
+ "event_data": null,
196
+ "fn_index": 5,
197
+ "trigger_id": 49
198
+ });
199
+
200
+ };
201
+ await process(obj);
202
+ console.log('processinv')
203
+ try {
204
+ let response = await axiosInstance.get('queue/data?session_hash=' + o.session_hash);
205
+ console.log(" process done")
206
+ return response.data.split(/data\: /).filter(v => v.includes('process_completed')).map(v => JSON.parse(v));
207
+ } catch (e) {
208
+ return {
209
+ status: 500
210
+ };
211
+ }
212
+ }
213
+
214
+ function generateHash() {
215
+ const chars = "qwertyuopasdfghjklizxcvbnm0123456789";
216
+ let hash = "";
217
+ for (let i = 0; i < 11; i++) {
218
+ hash += chars[Math.floor(Math.random() * chars.length)];
219
+ }
220
+ return {
221
+ session_hash: hash,
222
+ fn_index: 2
223
+ };
224
+ }
225
+ let u = (await animagine({
226
+ prompt,
227
+ negative,
228
+ model
229
+ })).pop()
230
+ console.log(u)
231
+ if (!u.success || !u.output.data[0][0].image) return res.send({
232
+ status: 500,
233
+ message: 'error'
234
+ })
235
+ let me = await fetch(u.output.data.shift().shift().image.url)
236
+ if (!me.ok || me.status !== 200) return res.send({
237
+ status: 500,
238
+ message: 'Can\'t buffer url'
239
+ })
240
+ if (!/image/.test(me.headers.get('content-type'))) return res.send({
241
+ status: 500,
242
+ message: 'error'
243
+ })
244
+ return res.type('png').send(Buffer.from((await me.arrayBuffer())))
245
  })
246
 
247
  app.all('/topdf', async (req, res) => {
248
+ if (req.method !== 'POST') return res.status(405).json({
249
+ success: false,
250
+ message: 'Method Not Allowed'
251
+ })
252
+
253
  try {
254
+ const {
255
+ images: urls,
256
+ json,
257
+ raw
258
+ } = req.body
259
+ if (!urls) return res.status(400).json({
260
+ success: false,
261
+ message: 'Payload \'images\' requires an array of urls'
262
+ })
263
  if (!Array.isArray(urls)) urls = [urls]
264
+
265
  const bufferPDF = await toPDF(urls)
266
+ if (!bufferPDF.length) return res.status(400).json({
267
+ success: false,
268
+ message: 'Can\'t convert to pdf'
269
+ })
270
+
271
  const fileName = randomName('.pdf')
272
  await fs.promises.writeFile(`${tmpDir}/${fileName}`, bufferPDF)
273
+
274
  const resultUrl = `https://${req.hostname}/file/${fileName}`
275
+ isTrue(json) ? res.json({
276
+ success: true,
277
+ result: resultUrl
278
+ }) : res[isTrue(raw) ? 'send' : 'redirect'](resultUrl)
279
  } catch (e) {
280
  console.log(e)
281
+ res.status(500).json({
282
+ error: true,
283
+ message: getError(e)
284
+ })
285
  }
286
  })
287
 
288
  app.all(/^\/webp2(gif|mp4|png)/, async (req, res) => {
289
+ if (req.method !== 'POST') return res.status(405).json({
290
+ success: false,
291
+ message: 'Method Not Allowed'
292
+ })
293
+
294
  try {
295
+ const {
296
+ file,
297
+ json,
298
+ raw
299
+ } = req.body
300
+ if (!file) return res.status(400).json({
301
+ success: false,
302
+ message: 'Payload \'file\' requires base64 string'
303
+ })
304
+ if (!isBase64(file)) return res.status(400).json({
305
+ success: false,
306
+ message: 'Invalid base64 format'
307
+ })
308
+
309
  const type = req.params[0]
310
  if (type === 'png') {
311
  const fileName = randomName('.png')
312
  const fileBuffer = await sharp(Buffer.from(file, 'base64')).png().toBuffer()
313
  await fs.promises.writeFile(`${tmpDir}/${fileName}`, fileBuffer)
314
+
315
  const resultUrl = `https://${req.hostname}/file/${fileName}`
316
+ isTrue(json) ? res.json({
317
+ success: true,
318
+ result: resultUrl
319
+ }) : res[isTrue(raw) ? 'send' : 'redirect'](resultUrl)
320
  return
321
  } else {
322
  const fileName = randomName('.webp')
323
  const filePath = `${tmpDir}/${fileName}`
324
  await fs.promises.writeFile(filePath, Buffer.from(file, 'base64'))
325
+
326
  const exec = util.promisify(cp.exec).bind(cp)
327
  await exec(`convert ${filePath} ${filePath.replace('webp', 'gif')}`)
328
+
329
  let resultUrl
330
  if (type === 'gif') resultUrl = `https://${req.hostname}/file/${fileName.replace('webp', 'gif')}`
331
  else {
332
  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')}`)
333
  resultUrl = `https://${req.hostname}/file/${fileName.replace('webp', 'mp4')}`
334
  }
335
+
336
+ isTrue(json) ? res.json({
337
+ success: true,
338
+ result: resultUrl
339
+ }) : res[isTrue(raw) ? 'send' : 'redirect'](resultUrl)
340
  }
341
  } catch (e) {
342
  console.log(e)
343
+ res.status(500).json({
344
+ error: true,
345
+ message: getError(e)
346
+ })
347
  }
348
  })
349
 
350
  // /yt /yt/ /yt/dl /yt/download /yt/search /youtube/dl /youtube/download /youtube/search
351
  app.all(/^\/y(outube|t)(\/(d(ownload|l)|search)?)?/, async (req, res) => {
352
+ if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({
353
+ success: false,
354
+ message: 'Method Not Allowed'
355
+ })
356
+
357
  try {
358
  const type = req.params[2] || ''
359
+
360
  const obj = req.method !== 'GET' ? req.body : req.query
361
  if (type === 'search') {
362
+ if (!obj.query) return res.status(400).json({
363
+ success: false,
364
+ message: 'Required parameter \'query\''
365
+ })
366
+
367
  const result = await yts(obj)
368
+ if (!(result.all?.length || result?.url)) return res.status(400).json({
369
+ success: false,
370
+ message: 'Video unavailable'
371
+ })
372
+
373
+ res.json({
374
+ success: true,
375
+ result
376
+ })
377
  return
378
  } else if (['dl', 'download'].includes(type)) {
379
+ if (!obj.url) return res.status(400).json({
380
+ success: false,
381
+ message: 'Required parameter \'url\''
382
+ })
383
+ if (!ytdl.validateURL(obj.url)) return res.status(400).json({
384
+ success: false,
385
+ message: 'Invalid url'
386
+ })
387
+
388
  // obj.filter = 'audioandvideo'
389
  const stream = ytdl(obj.url, obj)
390
  stream.on('error', (e) => {
391
  console.log(e)
392
+ res.status(500).json({
393
+ error: true,
394
+ message: getError(e)
395
+ })
396
  })
397
+
398
  stream.on('info', async (info, formats) => {
399
+ const req = await fetch(formats.url, {
400
+ method: 'HEAD'
401
+ })
402
  const contentLength = req.headers.get('content-length') || formats.contentLength
403
  const fileName = `${encodeURIComponent(info.videoDetails.title)}.${formats.container}`
404
  res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`)
 
409
  // stream.pipe(res)
410
  return
411
  } else {
412
+ if (!obj.query) return res.status(400).json({
413
+ success: false,
414
+ message: 'Required parameter \'query\''
415
+ })
416
+
417
+ let result = await yts(ytdl.validateURL(obj.query) ? {
418
+ videoId: ytdl.getVideoID(obj.query)
419
+ } : obj.query)
420
  result = result.videos ? result.videos[0] : result
421
+ if (!result?.url) return res.status(400).json({
422
+ success: false,
423
+ message: 'Video unavailable'
424
+ })
425
+
426
  const dlUrl = `https://${req.hostname}/yt/dl?url=${result.url}`
427
  const download = {
428
  audio: `${dlUrl}&filter=audioonly&quality=highestaudio`,
 
430
  }
431
  res.json({
432
  success: true,
433
+ result: {
434
+ ...result,
435
+ download
436
+ }
437
  })
438
  }
439
  } catch (e) {
440
  console.log(e)
441
+ res.status(500).json({
442
+ error: true,
443
+ message: getError(e)
444
+ })
445
  }
446
  })
447
 
448
  app.listen(7860, () => console.log('App running on port 7860'))
449
 
450
  function formatSize(n) {
451
+ return bytes(+n, {
452
+ unitSeparator: ' '
453
+ })
454
  }
455
 
456
  function getError(e) {
 
477
  function toPDF(urls) {
478
  return new Promise(async (resolve, reject) => {
479
  try {
480
+ const doc = new PDFDocument({
481
+ margin: 0,
482
+ size: 'A4'
483
+ })
484
  const buffs = []
485
+
486
  for (let x = 0; x < urls.length; x++) {
487
  if (!/https:\/\//.test(urls[x])) continue
488
  const url = new URL(urls[x])
489
+ let image = await fetch(url.toString(), {
490
+ headers: {
491
+ referer: url.origin
492
+ }
493
+ })
494
  if (!image.ok) continue
495
+
496
  const type = image.headers.get('content-type')
497
  if (!/image/.test(type)) continue
498
  image = Buffer.from(await image.arrayBuffer())
499
  if (/(gif|webp)$/.test(type)) image = await sharp(image).png().toBuffer()
500
+
501
+ doc.image(image, 0, 0, {
502
+ fit: [595.28, 841.89],
503
+ align: 'center',
504
+ valign: 'center'
505
+ })
506
  if (urls.length != x + 1) doc.addPage()
507
  }
508
+
509
  doc.on('data', (chunk) => buffs.push(chunk))
510
  doc.on('end', () => resolve(Buffer.concat(buffs)))
511
  doc.on('error', (err) => reject(err))
 
515
  reject(e)
516
  }
517
  })
518
+ }