├── wrangler.toml ├── Tenboro.png ├── README.md ├── package.json ├── copying ├── privacy_policy.txt ├── _worker.js └── index.html /wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "exhentai-igneous-generator" 2 | pages_build_output_dir = "./" 3 | -------------------------------------------------------------------------------- /Tenboro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UjuiUjuMandan/exhentai-igneous-generator/HEAD/Tenboro.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](Tenboro.png) 2 | 3 | # ExHentai Igneous 生成器 4 | 5 | 通过 PaaS 网络代理访问 ExHentai 获取 igneous。 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "exhentai-igneous-generator", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "_worker.js", 6 | "scripts": { 7 | "deploy": "wrangler deploy", 8 | "build": "wrangler deploy --dry-run", 9 | "dev": "wrangler dev --remote" 10 | }, 11 | "author": "", 12 | "license": "WTFPL", 13 | "devDependencies": { 14 | "@cloudflare/workers-types": "^4.20230710.1", 15 | "wrangler": "^3.2.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /copying: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /privacy_policy.txt: -------------------------------------------------------------------------------- 1 | I and the default services would not log or use any of your provided information. 2 | 3 | Your information is encrypted with TLS before being processed and is not likely to be captured by any third party. 4 | 5 | The default services are hosted on many third parties, which have their own privacy policy. 6 | 7 | This webpage uses Cloudflare Web Analytics, which means the following information that you will not actively provide will be collected and logged: 8 | 9 | 1. Your web browser's User-Agent in the HTTP header, which includes your operating system, web browser, and device type (mobile or desktop). 10 | 2. Your country based on IP address. 11 | 12 | Last edited: Thu Dec 5 20:16:53 CST 2024 13 | -------------------------------------------------------------------------------- /_worker.js: -------------------------------------------------------------------------------- 1 | export default { 2 | async fetch(request, env) { 3 | const url = new URL(request.url); 4 | 5 | if (url.pathname === "/api") { 6 | let ipbMemberId, ipbPassHash; 7 | try { 8 | if (request.method === "GET") { 9 | ipbMemberId = url.searchParams.get("ipb_member_id"); 10 | ipbPassHash = url.searchParams.get("ipb_pass_hash"); 11 | } else if (request.method === "POST") { 12 | const body = await request.json(); 13 | ipbMemberId = body.ipb_member_id; 14 | ipbPassHash = body.ipb_pass_hash; 15 | } else if (request.method === "OPTIONS") { 16 | return new Response(null, { 17 | status: 204, 18 | headers: { 19 | "Access-Control-Allow-Origin": "*", 20 | "Access-Control-Allow-Methods": "GET, POST, OPTIONS", 21 | "Access-Control-Allow-Headers": "Content-Type", 22 | }, 23 | }); 24 | } else { 25 | return new Response("Only GET, POST, and OPTIONS methods are supported", { status: 405 }); 26 | } 27 | 28 | if (!ipbMemberId || !ipbPassHash) { 29 | return new Response("Missing required parameters: ipb_member_id and ipb_pass_hash", { status: 400 }); 30 | } 31 | 32 | const cookie = `ipb_member_id=${ipbMemberId}; ipb_pass_hash=${ipbPassHash}`; 33 | const headers = new Headers(); 34 | headers.set("Cookie", cookie); 35 | 36 | const targetUrl = "https://exhentai.org/"; 37 | const uconfigUrl = "https://e-hentai.org/uconfig.php"; 38 | const forumsUrl = "https://forums.e-hentai.org"; 39 | 40 | const forumsResponse = await fetch(forumsUrl, { method: "GET", headers }); 41 | const forumsHtml = await forumsResponse.text(); 42 | 43 | const banMatch = forumsHtml.match( 44 | /
\s*

The error returned was:<\/h4>\s*

Your account has been temporarily suspended\. This suspension is due to end on (.*?)\.<\/p>/ 45 | ); 46 | 47 | if (banMatch) { 48 | const banEndDate = banMatch[1]; 49 | 50 | return new Response( 51 | JSON.stringify( 52 | { 53 | accountStatus: "banned", 54 | banEndDate: banEndDate, 55 | }, 56 | null, 57 | 2 58 | ), 59 | { 60 | status: 200, 61 | headers: { 62 | "Content-Type": "application/json", 63 | "Access-Control-Allow-Origin": "*", 64 | }, 65 | } 66 | ); 67 | } 68 | 69 | const response = await fetch(targetUrl, { method: "GET", headers }); 70 | const headersObject = {}; 71 | for (const [key, value] of response.headers.entries()) { 72 | headersObject[key] = value; 73 | } 74 | 75 | const uconfigResponse = await fetch(uconfigUrl, { method: "GET", headers }); 76 | if (!uconfigResponse.ok) { 77 | return new Response("Failed to fetch uconfig.php", { status: uconfigResponse.status }); 78 | } 79 | const html = await uconfigResponse.text(); 80 | 81 | const match = html.match(/

You appear to be browsing the site from (.*?)<\/strong>/); 82 | const browsingCountry = match ? match[1] : "Unknown"; 83 | 84 | return new Response( 85 | JSON.stringify( 86 | { 87 | accountStatus: "Unknown", 88 | headers: headersObject, 89 | browsingCountry: browsingCountry, 90 | }, 91 | null, 92 | 2 93 | ), 94 | { 95 | status: 200, 96 | headers: { 97 | "Content-Type": "application/json", 98 | "Access-Control-Allow-Origin": "*", 99 | }, 100 | } 101 | ); 102 | } catch (err) { 103 | return new Response(`Error: ${err.message}`, { 104 | status: 500, 105 | headers: { 106 | "Access-Control-Allow-Origin": "*", 107 | }, 108 | }); 109 | } 110 | } 111 | 112 | if (url.pathname === "/" || url.pathname.endsWith(".html")) { 113 | const response = await env.ASSETS.fetch(request); 114 | 115 | return new HTMLRewriter() 116 | .on("option[data-cloud-run-api]", new SetAPI(env.CLOUD_RUN_API)) 117 | .on("option[data-aws-lambda-api]", new SetAPI(env.AWS_LAMBDA_API)) 118 | .on("option[data-azure-func-api]", new SetAPI(env.AZURE_FUNC_API)) 119 | .transform(response); 120 | } 121 | 122 | return env.ASSETS.fetch(request); 123 | }, 124 | }; 125 | 126 | class SetAPI { 127 | constructor(newAPI) { 128 | this.newAPI = newAPI; 129 | } 130 | 131 | element(element) { 132 | if (this.newAPI) { 133 | element.setAttribute("value", this.newAPI); 134 | element.removeAttribute("hidden"); 135 | } else { 136 | element.removeAttribute("value"); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ExHentai Igneous Generator 14 | 91 | 92 | 93 |

ExHentai Igneous Generator

94 | 95 | 96 | Tenboro Image 97 | 98 |
99 | 106 | 107 |
108 | 109 | 115 | 116 | 117 | 118 | 125 | 126 |
Code copied to clipboard!
127 |
Failed to copy: Something went wrong!
128 | 129 | 133 | 134 | 301 | 302 | 303 | 304 | --------------------------------------------------------------------------------