fourmovie commited on
Commit
9d5ffec
·
1 Parent(s): 2d0d285
Files changed (2) hide show
  1. endpoints/recaptchav3.js +82 -0
  2. index.js +20 -112
endpoints/recaptchav3.js ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ async function recaptchav3({ domain, siteKey, proxy, action = 'homepage' }, page) {
2
+ if (!domain) throw new Error("Missing domain parameter");
3
+ if (!siteKey) throw new Error("Missing siteKey parameter");
4
+
5
+ const timeout = global.timeOut || 60000;
6
+ let isResolved = false;
7
+
8
+ const cl = setTimeout(async () => {
9
+ if (!isResolved) {
10
+ throw new Error("Timeout Error");
11
+ }
12
+ }, timeout);
13
+
14
+ try {
15
+ if (proxy?.username && proxy?.password) {
16
+ await page.authenticate({
17
+ username: proxy.username,
18
+ password: proxy.password,
19
+ });
20
+ }
21
+
22
+ const htmlContent = `
23
+ <!DOCTYPE html>
24
+ <html lang="en">
25
+ <head>
26
+ <script src="https://www.google.com/recaptcha/api.js?render=${siteKey}"></script>
27
+ </head>
28
+ <body>
29
+ <input type="hidden" id="recaptchav3Token" name="recaptchav3">
30
+ <script>
31
+ grecaptcha.ready(function() {
32
+ grecaptcha.execute("${siteKey}", {action: "${action}"}).then(function(token) {
33
+ document.getElementById("recaptchav3Token").value = token;
34
+ });
35
+ });
36
+ </script>
37
+ </body>
38
+ </html>
39
+ `;
40
+
41
+ await page.setRequestInterception(true);
42
+ page.removeAllListeners("request");
43
+ page.on("request", async (request) => {
44
+ if ([domain, domain + "/"].includes(request.url()) && request.resourceType() === "document") {
45
+ await request.respond({
46
+ status: 200,
47
+ contentType: "text/html",
48
+ body: htmlContent,
49
+ });
50
+ } else {
51
+ await request.continue();
52
+ }
53
+ });
54
+
55
+ await page.goto(domain, { waitUntil: "domcontentloaded" });
56
+
57
+ await page.waitForFunction(() => {
58
+ const tokenInput = document.getElementById("recaptchav3Token");
59
+ return tokenInput && tokenInput.value.length > 10;
60
+ }, { timeout });
61
+
62
+ const token = await page.evaluate(() => {
63
+ try {
64
+ return document.getElementById("recaptchav3Token").value;
65
+ } catch {
66
+ return null;
67
+ }
68
+ });
69
+
70
+ isResolved = true;
71
+ clearTimeout(cl);
72
+
73
+ if (!token || token.length < 10) throw new Error("Failed to get token");
74
+ return token;
75
+
76
+ } catch (e) {
77
+ clearTimeout(cl);
78
+ throw e;
79
+ }
80
+ }
81
+
82
+ module.exports = recaptchav3;
index.js CHANGED
@@ -2,19 +2,15 @@ const express = require('express')
2
  const { connect } = require("puppeteer-real-browser")
3
  const fs = require("fs")
4
  const path = require("path")
5
- const os = require('os')
6
 
7
  const app = express()
8
- const port = process.env.PORT || 7860
9
  const authToken = process.env.authToken || null
10
  const DOMAIN = 'https://rezaharis-cf.hf.space'
11
 
12
  global.browserLimit = Number(process.env.browserLimit) || 20
13
  global.timeOut = Number(process.env.timeOut) || 60000
14
 
15
- let hitCount = 0
16
- const startTime = Date.now()
17
-
18
  const CACHE_DIR = path.join(__dirname, "cache")
19
  const CACHE_FILE = path.join(CACHE_DIR, "cache.json")
20
  const CACHE_TTL = 5 * 60 * 1000
@@ -50,31 +46,14 @@ function writeCache(key, value) {
50
  saveCache(cache)
51
  }
52
 
53
- function getRuntimeInfo() {
54
- const mem = process.memoryUsage()
55
- const totalMem = os.totalmem()
56
- const usedMem = totalMem - os.freemem()
57
-
58
- return {
59
- os: os.type(),
60
- platform: os.platform(),
61
- architecture: os.arch(),
62
- cpuCount: os.cpus().length,
63
- uptime: `${process.uptime().toFixed(2)} seconds`,
64
- memoryUsage: `${Math.round(usedMem / 1024 / 1024)} MB used of ${Math.round(totalMem / 1024 / 1024)} MB`
65
- }
66
- }
67
-
68
  app.use(express.json())
69
  app.use(express.urlencoded({ extended: true }))
70
 
71
  app.get('/', (req, res) => {
72
- hitCount++
73
  res.json({
74
- author: "fourstore",
75
- hit: hitCount,
76
- message: "Gunakan: curl -X POST https://rezaharis-cf.hf.space/cloudflare -H 'Content-Type: application/json' -d '{\"mode\":\"turnstile\",\"sitekey\":\"xxx\",\"url\":\"https://example.com\"}'",
77
- runtime: getRuntimeInfo()
78
  })
79
  })
80
 
@@ -124,62 +103,25 @@ const turnstile = require('./endpoints/turnstile')
124
  const cloudflare = require('./endpoints/cloudflare')
125
 
126
  app.post('/cloudflare', async (req, res) => {
127
- hitCount++
128
  const data = req.body
129
-
130
- if (!data || !data.mode) {
131
- return res.status(400).json({
132
- author: "fourstore",
133
- hit: hitCount,
134
- message: "Parameter 'mode' diperlukan",
135
- runtime: getRuntimeInfo(),
136
- status: "failed"
137
- })
138
- }
139
-
140
- if (!data.sitekey || !data.url) {
141
- return res.status(400).json({
142
- author: "fourstore",
143
- hit: hitCount,
144
- message: "Parameter 'sitekey' dan 'url' diperlukan",
145
- runtime: getRuntimeInfo(),
146
- status: "failed"
147
- })
148
  }
149
-
150
  if (authToken && data.authToken !== authToken) {
151
- return res.status(401).json({
152
- author: "fourstore",
153
- hit: hitCount,
154
- message: "Unauthorized",
155
- runtime: getRuntimeInfo(),
156
- status: "failed"
157
- })
158
  }
159
 
160
  if (global.browserLimit <= 0) {
161
- return res.status(429).json({
162
- author: "fourstore",
163
- hit: hitCount,
164
- message: "Too Many Requests",
165
- runtime: getRuntimeInfo(),
166
- status: "failed"
167
- })
168
  }
169
 
170
  let cacheKey, cached
171
  if (data.mode === "iuam") {
 
172
  cacheKey = JSON.stringify(data)
173
  cached = readCache(cacheKey)
174
  if (cached) {
175
- return res.status(200).json({
176
- author: "fourstore",
177
- hit: hitCount,
178
- ...cached,
179
- cached: true,
180
- runtime: getRuntimeInfo(),
181
- status: "success"
182
- })
183
  }
184
  }
185
 
@@ -197,29 +139,17 @@ app.post('/cloudflare', async (req, res) => {
197
 
198
  switch (data.mode) {
199
  case "turnstile":
 
200
  result = await turnstile(data, page)
201
- .then(token => ({
202
- token,
203
- status: "success"
204
- }))
205
- .catch(err => ({
206
- code: 500,
207
- message: err.message,
208
- status: "failed"
209
- }))
210
  break
211
 
212
  case "iuam":
 
213
  result = await cloudflare(data, page)
214
- .then(r => ({
215
- ...r,
216
- status: "success"
217
- }))
218
- .catch(err => ({
219
- code: 500,
220
- message: err.message,
221
- status: "failed"
222
- }))
223
 
224
  if (!result.code || result.code === 200) {
225
  writeCache(cacheKey, result)
@@ -227,18 +157,10 @@ app.post('/cloudflare', async (req, res) => {
227
  break
228
 
229
  default:
230
- result = {
231
- code: 400,
232
- message: 'Invalid mode',
233
- status: "failed"
234
- }
235
  }
236
  } catch (err) {
237
- result = {
238
- code: 500,
239
- message: err.message,
240
- status: "failed"
241
- }
242
  } finally {
243
  if (browser) {
244
  try { await browser.close() } catch {}
@@ -246,25 +168,11 @@ app.post('/cloudflare', async (req, res) => {
246
  global.browserLimit++
247
  }
248
 
249
- const response = {
250
- author: "fourstore",
251
- hit: hitCount,
252
- ...result,
253
- runtime: getRuntimeInfo()
254
- }
255
-
256
- res.status(result.code ?? 200).json(response)
257
  })
258
 
259
  app.use((req, res) => {
260
- hitCount++
261
- res.status(404).json({
262
- author: "fourstore",
263
- hit: hitCount,
264
- message: "Not Found",
265
- runtime: getRuntimeInfo(),
266
- status: "failed"
267
- })
268
  })
269
 
270
  if (process.env.NODE_ENV === 'development') {
 
2
  const { connect } = require("puppeteer-real-browser")
3
  const fs = require("fs")
4
  const path = require("path")
 
5
 
6
  const app = express()
7
+ const port = process.env.PORT || 8080
8
  const authToken = process.env.authToken || null
9
  const DOMAIN = 'https://rezaharis-cf.hf.space'
10
 
11
  global.browserLimit = Number(process.env.browserLimit) || 20
12
  global.timeOut = Number(process.env.timeOut) || 60000
13
 
 
 
 
14
  const CACHE_DIR = path.join(__dirname, "cache")
15
  const CACHE_FILE = path.join(CACHE_DIR, "cache.json")
16
  const CACHE_TTL = 5 * 60 * 1000
 
46
  saveCache(cache)
47
  }
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  app.use(express.json())
50
  app.use(express.urlencoded({ extended: true }))
51
 
52
  app.get('/', (req, res) => {
 
53
  res.json({
54
+ message: 'Server is running',
55
+ domain: DOMAIN,
56
+ status: 'active'
 
57
  })
58
  })
59
 
 
103
  const cloudflare = require('./endpoints/cloudflare')
104
 
105
  app.post('/cloudflare', async (req, res) => {
 
106
  const data = req.body
107
+ if (!data || typeof data.mode !== 'string') {
108
+ return res.status(400).json({ message: 'Bad Request: missing or invalid mode' })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  }
 
110
  if (authToken && data.authToken !== authToken) {
111
+ return res.status(401).json({ message: 'Unauthorized' })
 
 
 
 
 
 
112
  }
113
 
114
  if (global.browserLimit <= 0) {
115
+ return res.status(429).json({ message: 'Too Many Requests' })
 
 
 
 
 
 
116
  }
117
 
118
  let cacheKey, cached
119
  if (data.mode === "iuam") {
120
+
121
  cacheKey = JSON.stringify(data)
122
  cached = readCache(cacheKey)
123
  if (cached) {
124
+ return res.status(200).json({ ...cached, cached: true })
 
 
 
 
 
 
 
125
  }
126
  }
127
 
 
139
 
140
  switch (data.mode) {
141
  case "turnstile":
142
+
143
  result = await turnstile(data, page)
144
+ .then(token => ({ token }))
145
+ .catch(err => ({ code: 500, message: err.message }))
 
 
 
 
 
 
 
146
  break
147
 
148
  case "iuam":
149
+
150
  result = await cloudflare(data, page)
151
+ .then(r => ({ ...r }))
152
+ .catch(err => ({ code: 500, message: err.message }))
 
 
 
 
 
 
 
153
 
154
  if (!result.code || result.code === 200) {
155
  writeCache(cacheKey, result)
 
157
  break
158
 
159
  default:
160
+ result = { code: 400, message: 'Invalid mode' }
 
 
 
 
161
  }
162
  } catch (err) {
163
+ result = { code: 500, message: err.message }
 
 
 
 
164
  } finally {
165
  if (browser) {
166
  try { await browser.close() } catch {}
 
168
  global.browserLimit++
169
  }
170
 
171
+ res.status(result.code ?? 200).json(result)
 
 
 
 
 
 
 
172
  })
173
 
174
  app.use((req, res) => {
175
+ res.status(404).json({ message: 'Not Found' })
 
 
 
 
 
 
 
176
  })
177
 
178
  if (process.env.NODE_ENV === 'development') {