File size: 15,079 Bytes
44c9fcd
095af13
9008ed0
e868aa0
095af13
 
 
 
9008ed0
095af13
3667424
7180a58
 
f958b8c
 
 
095af13
 
 
 
178b776
 
 
 
095af13
9008ed0
64dcc49
 
 
 
 
 
 
 
 
 
 
 
 
9008ed0
44c9fcd
095af13
 
 
 
 
64dcc49
 
 
095af13
 
 
 
 
 
 
 
 
 
 
 
9008ed0
 
 
095af13
44c9fcd
095af13
9008ed0
095af13
 
59f11b4
095af13
 
 
 
 
 
9008ed0
095af13
 
 
44c9fcd
 
21d123c
 
44c9fcd
 
21d123c
44c9fcd
3667424
44c9fcd
21d123c
9008ed0
44c9fcd
21d123c
 
 
 
 
 
 
64dcc49
9008ed0
 
 
 
 
 
 
64dcc49
9008ed0
 
 
 
64dcc49
 
9008ed0
64dcc49
9008ed0
 
 
 
 
 
 
 
53d2eb4
 
 
 
 
 
 
 
 
 
3667424
 
 
 
 
afb83df
 
3667424
 
 
 
 
 
 
 
 
f91f35a
2bfc655
f91f35a
 
 
 
 
 
 
 
f958b8c
 
 
 
 
 
 
 
 
 
 
e7ec152
d3b5da5
 
 
 
 
 
 
 
 
e7ec152
6179fa0
9008ed0
 
6179fa0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8fcec76
6179fa0
 
 
 
 
 
8fcec76
6179fa0
 
 
 
 
8fcec76
6179fa0
 
 
 
 
 
 
 
 
 
 
 
 
7d5bc71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac11386
374057f
 
 
 
 
ac11386
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
095af13
 
 
 
4ca849c
095af13
 
44c9fcd
 
 
 
 
 
 
 
095af13
 
 
 
 
 
 
4ca849c
ceeb8a8
4ca849c
095af13
 
4ca849c
095af13
 
 
 
 
4ca849c
 
095af13
 
 
 
 
 
 
 
 
 
8c53df2
3667424
91906f9
c1c8c21
aca9c68
c1c8c21
 
 
 
91906f9
c1c8c21
f209e03
 
c1c8c21
 
f209e03
c1c8c21
 
 
 
 
 
 
 
 
91906f9
 
 
c1c8c21
 
 
 
 
91906f9
 
c1c8c21
3667424
 
 
 
 
 
 
 
 
468a2d5
3667424
 
 
 
 
 
 
 
 
 
 
 
57f2510
0738a9b
57f2510
468a2d5
3667424
 
 
 
d3b5da5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3667424
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
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 { NinexbuddySource, NinexbuddyScraper } = require("./lib/buddy.js")
const kyou = new NinexbuddyScraper()


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.get('/fetch', async (req, res) => {
	try {
		if (!req.query.url) return res.json({ message: 'Required an url' })
		let json = await axios.get(req.query.url)
		res.json(json.data)
	} catch (e) {
		res.send(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('/dood', async (req, res) => {
        const { url } = req.query
		if (!url) return res.json({ success: false, message: 'Required parameter url' })
        const result = await kyou.execWithArgs(url)  
        res.json({
            creator: '@Kyouka',
            message: 'Success',
            uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4],
            result
        });
});

app.get('/igstalk', async (req, res) => {
	try {
		if (!req.query.user) return res.json({ message: 'Required an username' })
		let result = await igStalk(req.query.user)
		res.json({ result })
	} catch (e) {
		res.send(e)
	}
})

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 })
	}
})

app.get('/dongo', async (req, res) => {
  const { url } = req.query
		if (!url) return res.json({ success: false, message: 'Required parameter url' })
  const browser = await playwright.chromium.launch({
		headless: true,
		executablePath: '/usr/bin/chromium',
		args: ['--no-sandbox']
	})
  const context = await browser.newContext({
    extraHTTPHeaders: {
      'accept': '*/*',
      'accept-language': 'en-US,en;q=0.9,id;q=0.8',
      'cache-control': 'no-cache',
      'origin': url,
      'pragma': 'no-cache',
      'referer': url,
      'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
      'sec-ch-ua-mobile': '?0',
      'sec-ch-ua-platform': '"Windows"',
      'sec-fetch-dest': 'script',
      'sec-fetch-mode': 'cors',
      'sec-fetch-site': 'cross-site',
      'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
    }
  });

  const page = await context.newPage();
  await page.goto(url);

  const content = await page.content(); // Get the page content as HTML

  await browser.close();

  res.send(content); // Send the page content as response
});

app.get('/fetch-page', async (req, res) => {
  const browser = await playwright.chromium.launch({
		headless: true,
		executablePath: '/usr/bin/chromium',
		args: ['--no-sandbox']
	})
  const context = await browser.newContext({
    extraHTTPHeaders: {
      'accept': '*/*',
      'accept-language': 'en-US,en;q=0.9,id;q=0.8',
      'cache-control': 'no-cache',
      'origin': 'https://doujindesu.tv',
      'pragma': 'no-cache',
      'referer': 'https://doujindesu.tv',
      'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
      'sec-ch-ua-mobile': '?0',
      'sec-ch-ua-platform': '"Windows"',
      'sec-fetch-dest': 'script',
      'sec-fetch-mode': 'cors',
      'sec-fetch-site': 'cross-site',
      'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
    }
  });

  const page = await context.newPage();
  await page.goto('https://doujindesu.tv');

  const content = await page.content(); // Get the page content as HTML

  await browser.close();

  res.send(content); // Send the page content as response
});

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() {
  try {
    const browser = await playwright.chromium.launch({
      headless: true,
      executablePath: '/usr/bin/chromium',
      args: ['--no-sandbox']
    });
    const page = await browser.newPage();
    await page.goto('http://66.29.129.161/?filter=latest&cat=1');
    const pageContent = await page.content();
    console.log(pageContent);
    // Wait for the list of videos to load
    await page.waitForSelector('.videos-list');

    // Extract data from all articles
    const videoData = await page.$$eval('.videos-list article', articles => {
      return articles.map(article => {
        const thumbnail = article.querySelector('.post-thumbnail img').src;
        const title = article.querySelector('header.entry-header span').textContent;
        const url = article.querySelector('a').href;
        const duration = article.querySelector('.duration').textContent.trim();
        return { thumbnail, title, url, duration };
      });
    });

    await browser.close();
    return videoData;
  } catch (error) {
    console.error('An error occurred during scraping:', error);
    return []; // Return an empty array in case of error
  }
}


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
}


async function igStalk(user) {
	const getDetailPost = async url => {
		let html = (await axios.get(url, { headers: { 'Referer': 'https://www.picuki.com/', 'User-Agent': fakeua.mobile() }})).data 
		let $ = cheerio.load(html), obj = {}
		obj.caption = $('title').text().trim().split(' Instagram post ')[1].split(' - Picuki.com')[0]
		obj.ago = $('div.single-photo-info').find('div.single-photo-time').text()
		obj.likes = $('div.info-bottom').find('span.icon-thumbs-up-alt').text()
		obj.comments = $('div.info-bottom').find('span.icon-chat').text()
		obj.url = $('div.single-photo.owl-carousel.owl-theme > div.item').get().map((x) => $(x).find('img').attr('src') || $(x).find('video').attr('src'))
		if (!obj.url.length) obj.url = [$('div.single-photo').find('img').attr('src') || $('div.single-photo').find('video').attr('src')]
		return obj
	}
	let html = (await axios.get('https://www.picuki.com/profile/' + user, { headers: { 'Referer': 'https://www.picuki.com/', 'User-Agent': fakeua.mobile() }})).data
	let $ = cheerio.load(html), obj = {}, arr = []
	let urlPost = $('div.content > ul > li').get().map((x) => $(x).find('a').attr('href'))
	for (let x of urlPost) {
		if (x) arr.push(await getDetailPost(x))
	}
	obj.avatar = $('div.profile-avatar').find('a').attr('href')
	obj.username = $('div.profile-name > h1').text()
	obj.fullname = $('div.profile-name > h2').text()
	obj.description = $('div.profile-description').text().trim()
	obj.followers = $('div.content-title').find('span.followed_by').text()
	obj.following = $('div.content-title').find('span.follows').text()
	obj.post = arr
	return obj
}