Skip to content

Commit 7b95ffa

Browse files
authored
Add index.html for Perchance Generator UI
Creates a new HTML file for the Perchance Generator with a modern API integration and user interface.
1 parent adb9f7d commit 7b95ffa

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

index.html

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Perchance Generator – Modern API</title>
6+
<style>
7+
body { font-family: system-ui, Arial, sans-serif; max-width: 800px; margin: 2rem auto; padding: 0 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; }
10+
button { background: #1e2f3e; color: white; cursor: pointer; transition: 0.2s; }
11+
button:hover { background: #0f1e2a; }
12+
.error { color: #c33; background: #ffe8e6; padding: 0.5rem; border-radius: 12px; }
13+
hr { margin: 1.5rem 0; }
14+
code { background: #eee; padding: 0.2rem 0.4rem; border-radius: 8px; }
15+
</style>
16+
</head>
17+
<body>
18+
<h1>🎲 Perchance Generator (fixed API)</h1>
19+
<p>Uses official <code>/api/generate</code> endpoint – no CORS proxy needed.</p>
20+
21+
<label for="generatorInput"><strong>Generator name:</strong> (e.g. <code>fantasy-character</code>, <code>tavern-names</code>)</label><br>
22+
<input type="text" id="generatorInput" value="fantasy-character" style="width: 70%; margin-top: 6px;">
23+
24+
<div id="output">✨ Click "Generate" to see a random result.</div>
25+
<button id="generateBtn">Generate</button>
26+
27+
<hr>
28+
<small>✅ Fixed: uses modern <code>https://perchance.org/api/generate?generator=...&count=1</code><br>
29+
🔁 Removed deprecated <code>generateList.php</code> – handles CORS & JSON correctly.</small>
30+
31+
<script>
32+
const generateBtn = document.getElementById('generateBtn');
33+
const generatorInput = document.getElementById('generatorInput');
34+
const outputDiv = document.getElementById('output');
35+
36+
async function fetchFromPerchance() {
37+
const generatorName = generatorInput.value.trim();
38+
if (!generatorName) {
39+
outputDiv.innerHTML = '<span class="error">❌ Please enter a generator name.</span>';
40+
return;
41+
}
42+
43+
// Modern API endpoint (supports CORS, returns JSON array)
44+
const url = `https://perchance.org/api/generate?generator=${encodeURIComponent(generatorName)}&count=1`;
45+
46+
generateBtn.disabled = true;
47+
generateBtn.textContent = '⏳ Loading...';
48+
outputDiv.innerHTML = '🌀 Fetching from Perchance...';
49+
50+
try {
51+
const controller = new AbortController();
52+
const timeoutId = setTimeout(() => controller.abort(), 8000);
53+
const response = await fetch(url, { signal: controller.signal });
54+
clearTimeout(timeoutId);
55+
56+
if (!response.ok) {
57+
if (response.status === 404) {
58+
throw new Error(`Generator "${generatorName}" not found. Check the name.`);
59+
}
60+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
61+
}
62+
63+
const data = await response.json();
64+
65+
// Expected format: array of strings, e.g. ["result text"]
66+
if (Array.isArray(data) && data.length > 0 && typeof data[0] === 'string') {
67+
outputDiv.innerHTML = `<div>✨ ${escapeHtml(data[0])}</div>`;
68+
} else {
69+
console.warn('Unexpected API response:', data);
70+
outputDiv.innerHTML = '<span class="error">⚠️ Generator returned unexpected format. Try another generator.</span>';
71+
}
72+
} catch (err) {
73+
console.error(err);
74+
let msg = err.message;
75+
if (err.name === 'AbortError') msg = 'Timeout – server took too long.';
76+
else if (msg.includes('Failed to fetch')) msg = 'Network error. Check connection or CORS? (Perchance supports CORS, but your browser may block it)';
77+
outputDiv.innerHTML = `<span class="error">❌ ${escapeHtml(msg)}</span>`;
78+
} finally {
79+
generateBtn.disabled = false;
80+
generateBtn.textContent = 'Generate';
81+
}
82+
}
83+
84+
// simple XSS protection
85+
function escapeHtml(str) {
86+
return str.replace(/[&<>]/g, function(m) {
87+
if (m === '&') return '&amp;';
88+
if (m === '<') return '&lt;';
89+
if (m === '>') return '&gt;';
90+
return m;
91+
});
92+
}
93+
94+
generateBtn.addEventListener('click', fetchFromPerchance);
95+
generatorInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') fetchFromPerchance(); });
96+
</script>
97+
</body>
98+
</html>

0 commit comments

Comments
 (0)