init
Build and Push Containers / test (push) Successful in 28s
Build and Push Containers / build-and-push (push) Successful in 3m32s

This commit is contained in:
2026-07-31 08:16:05 -04:00
commit 806b21d856
10 changed files with 980 additions and 0 deletions
+461
View File
@@ -0,0 +1,461 @@
import base64
import json
import logging
import os
import random
import time
import uuid
from collections.abc import Generator
from typing import Any
import httpx
from dotenv import load_dotenv
from flask import Flask, Request, Response, request, stream_with_context
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger(__name__)
load_dotenv()
app = Flask(__name__)
API_URL = os.getenv("OPENAI_API_URL", "https://api.openai.com/v1/chat/completions")
API_KEY = os.getenv("OPENAI_API_KEY", "")
MODEL = os.getenv("MODEL", "gpt-4o-mini")
logger.info(f"Using model: {MODEL}")
logger.info(f"API URL: {API_URL}")
logger.info(f"API key present: {bool(API_KEY)}")
LOADING_PAGE = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Generating your page...</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #0a0a0f;
color: #e0e0e0;
font-family: system-ui, -apple-system, sans-serif;
overflow: hidden;
}
.spinner {
width: 80px;
height: 80px;
border: 4px solid rgba(100, 100, 255, 0.15);
border-top-color: #6366f1;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.title {
margin-top: 24px;
font-size: 1.5rem;
font-weight: 600;
letter-spacing: 0.02em;
}
.subtitle {
margin-top: 8px;
font-size: 0.9rem;
color: #888;
}
.stats {
margin-top: 20px;
font-size: 0.85rem;
color: #6366f1;
font-variant-numeric: tabular-nums;
}
.particles {
position: fixed;
inset: 0;
pointer-events: none;
overflow: hidden;
}
.particle {
position: absolute;
width: 3px;
height: 3px;
background: #6366f1;
border-radius: 50%;
opacity: 0;
animation: float 3s ease-in-out infinite;
}
@keyframes float {
0% { opacity: 0; transform: translateY(100vh) scale(0); }
50% { opacity: 0.6; }
100% { opacity: 0; transform: translateY(-20vh) scale(1); }
}
</style>
</head>
<body>
<div class="particles" id="particles"></div>
<div class="spinner"></div>
<div class="title">Crafting your page...</div>
<div class="subtitle">The AI is designing something unique for you</div>
<div class="stats" id="stats">Characters: 0</div>
<script>
const stats = document.getElementById('stats');
const titleEl = document.querySelector('.title');
const particles = document.getElementById('particles');
for (let i = 0; i < 30; i++) {
const p = document.createElement('div');
p.className = 'particle';
p.style.left = Math.random() * 100 + '%';
p.style.animationDelay = Math.random() * 3 + 's';
p.style.animationDuration = (2 + Math.random() * 2) + 's';
particles.appendChild(p);
}
const start = Date.now();
const es = new EventSource('/stream' + window.location.search + window.location.hash);
let chars = 0;
let htmlChunks = [];
let htmlSize = 0;
const interval = setInterval(() => {
stats.textContent = 'Characters: ' + chars.toLocaleString() + ' | ' + ((Date.now() - start) / 1000).toFixed(1) + 's';
}, 100);
window.__wotf_html = '';
es.onmessage = (e) => {
if (e.data === '[DONE]') {
clearInterval(interval);
es.close();
titleEl.textContent = 'Rendering...';
const fullHtml = htmlChunks.join('');
window.__wotf_html = fullHtml;
document.open();
document.write(fullHtml);
document.close();
injectMenu();
} else if (e.data === '[ERROR]') {
clearInterval(interval);
es.close();
titleEl.textContent = 'Error generating page';
document.querySelector('.subtitle').textContent = 'Please refresh and try again';
} else {
const decoded = atob(e.data);
htmlChunks.push(decoded);
htmlSize += decoded.length;
chars = htmlSize;
}
};
es.onerror = () => {
clearInterval(interval);
es.close();
titleEl.textContent = 'Connection error';
document.querySelector('.subtitle').textContent = 'Please refresh and try again';
};
function injectMenu() {
const style = document.createElement('style');
style.textContent = `
#wotf-menu-trigger {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 12px;
z-index: 2147483646;
cursor: default;
}
#wotf-menu {
position: fixed;
top: -52px;
left: 0;
right: 0;
height: 52px;
background: rgba(10, 10, 15, 0.95);
backdrop-filter: blur(12px);
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
padding: 0 24px;
z-index: 2147483647;
transition: top 0.25s ease;
border-bottom: 1px solid rgba(99, 102, 241, 0.3);
}
#wotf-menu.visible {
top: 0;
}
#wotf-menu button {
background: rgba(99, 102, 241, 0.15);
color: #e0e0e0;
border: 1px solid rgba(99, 102, 241, 0.4);
padding: 6px 16px;
border-radius: 6px;
font-size: 0.85rem;
cursor: pointer;
transition: all 0.15s ease;
font-family: system-ui, -apple-system, sans-serif;
}
#wotf-menu button:hover {
background: rgba(99, 102, 241, 0.35);
border-color: #6366f1;
color: #fff;
}
#wotf-menu .wotf-label {
font-size: 0.75rem;
color: #666;
letter-spacing: 0.05em;
text-transform: uppercase;
}
`;
document.head.appendChild(style);
const trigger = document.createElement('div');
trigger.id = 'wotf-menu-trigger';
const menu = document.createElement('div');
menu.id = 'wotf-menu';
const label = document.createElement('span');
label.className = 'wotf-label';
label.textContent = 'Web On The Fly';
const exportBtn = document.createElement('button');
exportBtn.textContent = 'Export Code';
exportBtn.onclick = () => {
const html = window.__wotf_html || '<!-- No HTML available -->';
const blob = new Blob([html], { type: 'text/html' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'generated-page.html';
a.click();
URL.revokeObjectURL(url);
};
const newBtn = document.createElement('button');
newBtn.textContent = 'New Page';
newBtn.onclick = () => {
window.location.href = '/';
};
menu.appendChild(label);
menu.appendChild(exportBtn);
menu.appendChild(newBtn);
document.body.appendChild(trigger);
document.body.appendChild(menu);
let hideTimer = null;
trigger.addEventListener('mouseenter', () => {
clearTimeout(hideTimer);
menu.classList.add('visible');
});
menu.addEventListener('mouseenter', () => {
clearTimeout(hideTimer);
menu.classList.add('visible');
});
trigger.addEventListener('mouseleave', () => {
hideTimer = setTimeout(() => menu.classList.remove('visible'), 150);
});
menu.addEventListener('mouseleave', (e) => {
if (e.clientY > 52) {
menu.classList.remove('visible');
}
});
}
</script>
</body>
</html>"""
def get_user_context(req: Request) -> dict[str, Any]:
user_agent = req.headers.get("User-Agent", "")
lang = req.headers.get("Accept-Language", "")
ip = req.remote_addr or ""
path = req.path
referer = req.headers.get("Referer", "")
cookies = dict(req.cookies)
return {
"user_agent": user_agent,
"language": lang,
"ip": ip,
"path": path,
"referer": referer,
"cookies": cookies,
}
THEMES = [
("fake_store", "A quirky online store selling unusual products (e.g., bottled laughter, cloud-shaped pillows)"),
("fake_store", "A vintage record store homepage with vinyl listings and album reviews"),
("fake_store", "A plant shop selling exotic and rare houseplants"),
("fake_store", "A retro gaming store selling refurbished consoles and cartridges"),
("fake_store", "A boutique selling handmade candles with weird scents"),
("fake_store", "A pet supply store for unusual pets (lizards, tarantulas, etc.)"),
("fake_homepage", "A personal portfolio site for a fictional photographer"),
("fake_homepage", "A musician's homepage with tour dates and album art"),
("fake_homepage", "A food blogger's site with recipe cards and photos"),
("fake_homepage", "A travel vlogger's site showcasing weird destinations"),
("fake_homepage", "A developer's portfolio with fun project descriptions"),
("fake_homepage", "An artist's gallery site with abstract paintings"),
("fake_social", "A social media profile page for a fictional influencer"),
("fake_social", "A Reddit-style thread about a bizarre conspiracy theory"),
("fake_social", "A Twitter/X feed from a fictional account"),
("fake_social", "A dating app profile page with funny bios"),
("fake_social", "A forum discussion about the best fictional pizza toppings"),
("fake_wiki", "A Wikipedia article about a fictional historical event"),
("fake_wiki", "A Wikipedia article about a fictional animal species"),
("fake_wiki", "A Wikipedia article about a fictional technology"),
("fake_wiki", "A wiki page for a fictional video game"),
("fake_wiki", "A wiki page for a fictional band or music group"),
("fake_forum", "A 2000s-era forum page with threads about tech support"),
("fake_forum", "A gaming forum with strategy discussions"),
("fake_forum", "A cooking forum with recipe debates and tips"),
("fake_forum", "A conspiracy forum with wild theories"),
("fake_blog", "A tech blog reviewing fictional gadgets"),
("fake_blog", "A lifestyle blog about minimalist living"),
("fake_blog", "A horror story blog with creepy tales"),
("fake_blog", "A science blog explaining weird phenomena"),
("fake_news", "A local news article about a quirky town event"),
("fake_news", "A sports article about a fictional team"),
("fake_news", "A celebrity gossip article"),
("fake_app", "A landing page for a fictional mobile app"),
("fake_app", "A SaaS dashboard for a fake productivity tool"),
("fake_app", "A streaming service page with fictional shows"),
("fake_other", "A fake email inbox from the year 2000"),
("fake_other", "A fake search engine results page for a weird query"),
("fake_other", "A fake 404 error page with an interactive game"),
("fake_other", "A fake loading screen for a fictional video game"),
("fake_other", "A fake terminal emulator with ASCII art and commands"),
]
def build_prompt(context: dict[str, Any]) -> str:
site_type, theme = random.choice(THEMES)
mood = random.choice(["playful", "mysterious", "cozy", "epic", "dreamy", "energetic", "melancholic", "whimsical"])
return f"""You are a web designer creating a realistic-looking fake website.
Here is information about the visitor:
- Preferred language: {context["language"]}
Site type: {site_type}
Theme: {theme}
Mood: {mood}
Generate a COMPLETE HTML document (<!DOCTYPE html> ... </html>) that looks like a REAL website of this type:
- Make it look authentic and believable as if it actually existed on the internet
- Include realistic details: fake names, fake content, fake comments, fake usernames, fake timestamps
- Use appropriate layout and conventions for the site type (e.g., a wiki should look like Wikipedia, a forum should have threads, etc.)
- Use inline CSS for styling - make it polished and visually appealing
- Include subtle animations or interactive elements where appropriate
- Make the content fun, interesting, and creative - not boring lorem ipsum
- Use the visitor's language for text when possible
- Responsive design that works on mobile
Examples:
- fake_store: product listings, prices, cart button, reviews
- fake_social: profile pic, followers count, posts, likes, comments
- fake_wiki: infobox, table of contents, citations, edit links
- fake_forum: thread list, usernames, post counts, timestamps
- fake_blog: article with author, date, comments section
- fake_homepage: about section, portfolio/work, contact info
Return ONLY the HTML, no markdown, no explanations."""
def stream_llm(context: dict[str, Any]) -> Generator[str]:
prompt = build_prompt(context)
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload: dict[str, Any] = {
"model": MODEL,
"messages": [
{"role": "system", "content": "You are a creative web designer."},
{"role": "user", "content": prompt},
],
"temperature": 0.9,
"stream": True,
}
req_id = uuid.uuid4().hex[:8]
start = time.time()
logger.info(f"[{req_id}] Streaming LLM call for IP={context['ip']}, lang={context['language']}")
try:
with httpx.Client(timeout=300) as client, client.stream("POST", API_URL, headers=headers, json=payload) as resp:
elapsed = time.time() - start
resp.raise_for_status()
buffer = ""
for chunk in resp.iter_text():
buffer += chunk
while "\n" in buffer:
line, buffer = buffer.split("\n", 1)
line = line.strip()
if not line or line == "data: [DONE]":
continue
if line.startswith("data: "):
data_str = line[6:]
try:
data: dict[str, Any] = json.loads(data_str)
delta = data.get("choices", [{}])[0].get("delta", {}).get("content", "")
if delta:
yield delta
except json.JSONDecodeError:
pass
elapsed = time.time() - start
logger.info(f"[{req_id}] Stream complete in {elapsed:.1f}s")
except httpx.HTTPStatusError as e:
elapsed = time.time() - start
logger.error(f"[{req_id}] HTTP error in {elapsed:.1f}s: {e.response.status_code} {e.response.text[:200]}")
yield f"\n\n<!-- Error: {e.response.status_code} -->"
except BaseException as e: # noqa: BLE001
elapsed = time.time() - start
logger.error(f"[{req_id}] Stream failed in {elapsed:.1f}s: {e}")
yield f"\n\n<!-- Error: {e} -->"
def sse_stream(context: dict[str, Any]) -> Generator[str]:
for chunk in stream_llm(context):
encoded = base64.b64encode(chunk.encode("utf-8")).decode("ascii")
yield f"data: {encoded}\n\n"
yield "data: [DONE]\n\n"
@app.route("/", defaults={"path": ""})
@app.route("/<path:path>")
def index(path: str) -> Response:
logger.info(f"Request from {request.remote_addr}: {request.path} (UA: {request.headers.get('User-Agent', '')[:80]})")
return Response(LOADING_PAGE, mimetype="text/html")
@app.route("/stream")
def stream() -> Response:
context = get_user_context(request)
logger.info(f"Stream request from {request.remote_addr}")
def generate() -> Generator[str]:
yield from sse_stream(context)
return Response(
stream_with_context(generate()),
mimetype="text/event-stream",
headers={
"Cache-Control": "no-cache",
"X-Accel-Buffering": "no",
"Connection": "keep-alive",
},
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)