Skip to content

Commit a21d7c6

Browse files
authored
Update index.html
1 parent cd2796f commit a21d7c6

1 file changed

Lines changed: 71 additions & 25 deletions

File tree

index.html

Lines changed: 71 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,80 +2,126 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8">
5-
<title>Perchance + allOrigins (CORS fixed)</title>
5+
<title>Perchance Generator - Working CORS</title>
66
<style>
77
body { font-family: system-ui, Arial, sans-serif; max-width: 800px; margin: 2rem auto; padding: 20px; }
8-
#output { padding: 1rem; border: 1px solid #ccc; border-radius: 12px; min-height: 80px; margin: 1rem 0; background: #f9f9fc; }
9-
button, input { padding: 8px 14px; font-size: 1rem; border-radius: 40px; border: 1px solid #aaa; }
8+
#output { padding: 1rem; border: 1px solid #ccc; border-radius: 12px; min-height: 80px; margin: 1rem 0; background: #f9f9fc; white-space: pre-wrap; }
9+
button, input, select { padding: 8px 14px; font-size: 1rem; border-radius: 40px; border: 1px solid #aaa; margin: 5px; }
1010
button { background: #1e2f3e; color: white; cursor: pointer; }
1111
button:hover { background: #0f1e2a; }
12+
button:disabled { opacity: 0.5; cursor: not-allowed; }
1213
.error { color: #c33; background: #ffe8e6; padding: 0.5rem; border-radius: 12px; }
1314
.success { background: #e0f2e9; padding: 0.5rem; border-radius: 12px; }
15+
.info { background: #e3f2fd; padding: 0.5rem; border-radius: 12px; font-size: 0.9rem; margin-top: 1rem; }
1416
</style>
1517
</head>
1618
<body>
17-
<h1>🎲 Perchance Generator (via allOrigins)</h1>
18-
<p>Using <code>api.allorigins.win/raw</code> - reliable CORS proxy</p>
19+
<h1>🎲 Perchance Generator (CORS Fixed)</h1>
20+
<p>Using reliable CORS proxies</p>
1921

20-
<label><strong>Generator name:</strong></label><br>
21-
<input type="text" id="generatorInput" value="fantasy-character" style="width: 70%; margin-top: 6px;">
22+
<input type="text" id="generatorInput" value="fantasy-character" style="width: 60%;">
23+
<select id="proxySelect">
24+
<option value="cloudflare">Cloudflare CORS (fastest)</option>
25+
<option value="x2u">cors.x2u.in (clean)</option>
26+
<option value="codetabs">codetabs (stable)</option>
27+
<option value="thebugging">thebugging (10/hour limit)</option>
28+
</select>
2229

2330
<div id="output">✨ Click Generate</div>
2431
<button id="generateBtn">Generate</button>
2532

33+
<div class="info">
34+
💡 <strong>Recommended:</strong> Cloudflare CORS proxy - fastest & no limits
35+
</div>
36+
2637
<script>
2738
const generateBtn = document.getElementById('generateBtn');
2839
const generatorInput = document.getElementById('generatorInput');
40+
const proxySelect = document.getElementById('proxySelect');
2941
const outputDiv = document.getElementById('output');
3042

43+
function getProxyUrl(directUrl) {
44+
const proxyType = proxySelect.value;
45+
switch(proxyType) {
46+
case 'cloudflare':
47+
return `https://test.cors.workers.dev/?${encodeURIComponent(directUrl)}`;
48+
case 'x2u':
49+
return `https://cors.x2u.in/${directUrl}`;
50+
case 'codetabs':
51+
return `https://codetabs.com/cors-proxy/cors-proxy.html?url=${encodeURIComponent(directUrl)}`;
52+
case 'thebugging':
53+
return `https://www.thebugging.com/apis/cors-proxy?url=${encodeURIComponent(directUrl)}`;
54+
default:
55+
return `https://test.cors.workers.dev/?${encodeURIComponent(directUrl)}`;
56+
}
57+
}
58+
3159
async function fetchFromPerchance() {
3260
const generatorName = generatorInput.value.trim();
3361
if (!generatorName) {
34-
outputDiv.innerHTML = '<span class="error">❌ Enter a generator name</span>';
62+
outputDiv.innerHTML = '<span class="error">❌ Please enter a generator name</span>';
3563
return;
3664
}
3765

38-
// Direct Perchance API URL
3966
const directUrl = `https://perchance.org/api/generate?generator=${encodeURIComponent(generatorName)}&count=1`;
40-
41-
// allOrigins proxy (RAW endpoint returns pure JSON)
42-
const proxyUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent(directUrl)}`;
67+
const proxyUrl = getProxyUrl(directUrl);
4368

4469
generateBtn.disabled = true;
4570
generateBtn.textContent = '⏳ Loading...';
46-
outputDiv.innerHTML = '🌀 Fetching via allOrigins...';
71+
outputDiv.innerHTML = '🌀 Fetching via proxy...';
4772

4873
try {
49-
const response = await fetch(proxyUrl);
50-
74+
const controller = new AbortController();
75+
const timeoutId = setTimeout(() => controller.abort(), 15000);
76+
const response = await fetch(proxyUrl, { signal: controller.signal });
77+
clearTimeout(timeoutId);
78+
5179
if (!response.ok) {
52-
throw new Error(`HTTP ${response.status}`);
80+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
5381
}
5482

5583
const data = await response.json();
5684

57-
// Perchance returns array: ["result text"]
85+
// Handle different proxy response formats
86+
let result = null;
5887
if (Array.isArray(data) && data.length > 0) {
59-
outputDiv.innerHTML = `<div class="success">✨ ${escapeHtml(data[0])}</div>`;
88+
result = data[0];
89+
} else if (data && data.contents) {
90+
// codetabs wraps in contents
91+
const parsed = JSON.parse(data.contents);
92+
result = parsed[0];
93+
} else if (data && typeof data === 'object' && data.data) {
94+
result = data.data;
95+
} else {
96+
result = JSON.stringify(data);
97+
}
98+
99+
if (result) {
100+
outputDiv.innerHTML = `<div class="success">✨ ${escapeHtml(result)}</div>`;
60101
} else {
61102
outputDiv.innerHTML = '<span class="error">⚠️ Unexpected response format</span>';
62103
}
63104
} catch (err) {
64105
console.error(err);
65-
outputDiv.innerHTML = `<span class="error">❌ ${escapeHtml(err.message)}</span>`;
106+
let errorMsg = err.message;
107+
if (err.name === 'AbortError') {
108+
errorMsg = 'Timeout - proxy took too long';
109+
} else if (errorMsg.includes('Failed to fetch')) {
110+
errorMsg = 'Network error. Try another proxy from the dropdown.';
111+
} else if (errorMsg.includes('429') || errorMsg.includes('rate')) {
112+
errorMsg = 'Rate limit exceeded (thebugging proxy). Switch to Cloudflare or x2u.';
113+
}
114+
outputDiv.innerHTML = `<span class="error">❌ ${escapeHtml(errorMsg)}</span>`;
66115
} finally {
67116
generateBtn.disabled = false;
68117
generateBtn.textContent = 'Generate';
69118
}
70119
}
71120

72121
function escapeHtml(str) {
73-
return str.replace(/[&<>]/g, function(m) {
74-
if (m === '&') return '&amp;';
75-
if (m === '<') return '&lt;';
76-
if (m === '>') return '&gt;';
77-
return m;
78-
});
122+
const div = document.createElement('div');
123+
div.textContent = str;
124+
return div.innerHTML;
79125
}
80126

81127
generateBtn.addEventListener('click', fetchFromPerchance);

0 commit comments

Comments
 (0)