mirror of
https://github.com/tanjiro517/cf-bypass-fast.git
synced 2025-12-05 13:48:01 +01:00
170 lines
4.0 KiB
JavaScript
170 lines
4.0 KiB
JavaScript
const express = require('express')
|
|
const { connect } = require("puppeteer-real-browser")
|
|
const fs = require("fs")
|
|
const path = require("path")
|
|
|
|
const app = express()
|
|
const port = process.env.PORT || 8080
|
|
const authToken = process.env.authToken || null
|
|
|
|
global.browserLimit = Number(process.env.browserLimit) || 20
|
|
global.timeOut = Number(process.env.timeOut) || 60000
|
|
|
|
const CACHE_DIR = path.join(__dirname, "cache")
|
|
const CACHE_FILE = path.join(CACHE_DIR, "cache.json")
|
|
const CACHE_TTL = 5 * 60 * 1000
|
|
|
|
function loadCache() {
|
|
if (!fs.existsSync(CACHE_FILE)) return {}
|
|
try {
|
|
return JSON.parse(fs.readFileSync(CACHE_FILE, "utf-8"))
|
|
} catch {
|
|
return {}
|
|
}
|
|
}
|
|
|
|
function saveCache(cache) {
|
|
if (!fs.existsSync(CACHE_DIR)) {
|
|
fs.mkdirSync(CACHE_DIR, { recursive: true })
|
|
}
|
|
fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8")
|
|
}
|
|
|
|
function readCache(key) {
|
|
const cache = loadCache()
|
|
const entry = cache[key]
|
|
if (entry && Date.now() - entry.timestamp < CACHE_TTL) {
|
|
return entry.value
|
|
}
|
|
return null
|
|
}
|
|
|
|
function writeCache(key, value) {
|
|
const cache = loadCache()
|
|
cache[key] = { timestamp: Date.now(), value }
|
|
saveCache(cache)
|
|
}
|
|
|
|
app.use(express.json())
|
|
app.use(express.urlencoded({ extended: true }))
|
|
|
|
if (process.env.NODE_ENV !== 'development') {
|
|
let server = app.listen(port, () => {
|
|
console.log(`Server running on port ${port}`)
|
|
})
|
|
try {
|
|
server.timeout = global.timeOut
|
|
} catch {}
|
|
}
|
|
|
|
async function createBrowser(proxyServer = null) {
|
|
const connectOptions = {
|
|
headless: false,
|
|
turnstile: true,
|
|
connectOption: { defaultViewport: null },
|
|
disableXvfb: false,
|
|
}
|
|
|
|
if (proxyServer) {
|
|
connectOptions.args = [`--proxy-server=${proxyServer}`]
|
|
}
|
|
|
|
const { browser } = await connect(connectOptions)
|
|
|
|
const pages = await browser.pages()
|
|
const page = pages[0]
|
|
|
|
await page.goto('about:blank')
|
|
|
|
await page.setRequestInterception(true)
|
|
page.on('request', (req) => {
|
|
const type = req.resourceType()
|
|
if (["image", "stylesheet", "font", "media"].includes(type)) {
|
|
req.abort()
|
|
} else {
|
|
req.continue()
|
|
}
|
|
})
|
|
|
|
return { browser, page }
|
|
}
|
|
|
|
const turnstile = require('./endpoints/turnstile')
|
|
const cloudflare = require('./endpoints/cloudflare')
|
|
|
|
app.post('/cloudflare', async (req, res) => {
|
|
const data = req.body
|
|
if (!data || typeof data.mode !== 'string') {
|
|
return res.status(400).json({ message: 'Bad Request: missing or invalid mode' })
|
|
}
|
|
if (authToken && data.authToken !== authToken) {
|
|
return res.status(401).json({ message: 'Unauthorized' })
|
|
}
|
|
|
|
if (global.browserLimit <= 0) {
|
|
return res.status(429).json({ message: 'Too Many Requests' })
|
|
}
|
|
|
|
let cacheKey, cached
|
|
if (data.mode === "iuam") {
|
|
|
|
cacheKey = JSON.stringify(data)
|
|
cached = readCache(cacheKey)
|
|
if (cached) {
|
|
return res.status(200).json({ ...cached, cached: true })
|
|
}
|
|
}
|
|
|
|
global.browserLimit--
|
|
let result
|
|
let browser, page
|
|
|
|
try {
|
|
const proxyServer = data.proxy ? `${data.proxy.hostname}:${data.proxy.port}` : null
|
|
const ctx = await createBrowser(proxyServer)
|
|
browser = ctx.browser
|
|
page = ctx.page
|
|
|
|
await page.goto('about:blank')
|
|
|
|
switch (data.mode) {
|
|
case "turnstile":
|
|
|
|
result = await turnstile(data, page)
|
|
.then(token => ({ token }))
|
|
.catch(err => ({ code: 500, message: err.message }))
|
|
break
|
|
|
|
case "iuam":
|
|
|
|
result = await cloudflare(data, page)
|
|
.then(r => ({ ...r }))
|
|
.catch(err => ({ code: 500, message: err.message }))
|
|
|
|
if (!result.code || result.code === 200) {
|
|
writeCache(cacheKey, result)
|
|
}
|
|
break
|
|
|
|
default:
|
|
result = { code: 400, message: 'Invalid mode' }
|
|
}
|
|
} catch (err) {
|
|
result = { code: 500, message: err.message }
|
|
} finally {
|
|
if (browser) {
|
|
try { await browser.close() } catch {}
|
|
}
|
|
global.browserLimit++
|
|
}
|
|
|
|
res.status(result.code ?? 200).json(result)
|
|
})
|
|
|
|
app.use((req, res) => {
|
|
res.status(404).json({ message: 'Not Found' })
|
|
})
|
|
|
|
if (process.env.NODE_ENV === 'development') {
|
|
module.exports = app
|
|
} |