devvibes's picture
Initial commit
a4d1533
"""
πŸ“‘ Haven Recipe Cast System
Cast recipes to mobile devices via local network.
"""
import threading
import io
import json
from http.server import HTTPServer, BaseHTTPRequestHandler
# Store the current recipe for casting
_current_recipe = None
_server_running = False
class RecipeHandler(BaseHTTPRequestHandler):
def do_GET(self):
global _current_recipe
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
if _current_recipe:
title = _current_recipe.get('title', 'Recipe')
html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{title}</title>
<style>
body {{ font-family: Georgia, serif; max-width: 600px; margin: 0 auto; padding: 20px; background: #FFF8F0; }}
h1 {{ color: #C07A5C; }}
.ingredients {{ background: #D4E6D5; padding: 15px; border-radius: 10px; margin: 20px 0; }}
.step {{ background: white; padding: 15px; margin: 10px 0; border-radius: 10px; border-left: 4px solid #C07A5C; }}
</style>
</head>
<body>
<h1>πŸ‘©πŸ»β€πŸ³ {title}</h1>
<div class="ingredients">
<h3>Ingredients</h3>
<ul>{''.join(f'<li>{i}</li>' for i in _current_recipe.get('ingredients', []))}</ul>
</div>
<h3>Instructions</h3>
{''.join(f'<div class="step"><strong>Step {i+1}:</strong> {s}</div>' for i, s in enumerate(_current_recipe.get('steps', [])))}
</body>
</html>
"""
else:
html = "<!DOCTYPE html><html><head><meta charset='UTF-8'></head><body><h1>No recipe loaded</h1></body></html>"
self.wfile.write(html.encode('utf-8'))
def log_message(self, format, *args):
pass # Suppress logging
def start_cast_server(port=8505):
global _server_running
if _server_running:
return
def run_server():
try:
server = HTTPServer(('0.0.0.0', port), RecipeHandler)
server.serve_forever()
except Exception:
pass # Silently handle server errors
thread = threading.Thread(target=run_server, daemon=True)
thread.start()
_server_running = True
def cast_recipe(recipe_dict):
"""Cast a recipe to the server and return the URL."""
global _current_recipe
_current_recipe = recipe_dict
return get_cast_url()
def get_cast_url():
"""Get the cast URL using the machine's local IP address."""
import socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
local_ip = s.getsockname()[0]
s.close()
return f"http://{local_ip}:8505"
except:
return "http://localhost:8505"
def generate_qr_code(url):
"""Generate QR code for recipe URL."""
try:
import qrcode
qr = qrcode.QRCode(version=1, box_size=10, border=2)
qr.add_data(url)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
buffer = io.BytesIO()
img.save(buffer, format='PNG')
buffer.seek(0)
return buffer.getvalue()
except Exception:
return None