74 lines
2.0 KiB
Python
74 lines
2.0 KiB
Python
|
from fastapi import FastAPI, Request
|
||
|
from fastapi.responses import HTMLResponse
|
||
|
from fastapi.staticfiles import StaticFiles
|
||
|
from fastapi.templating import Jinja2Templates
|
||
|
from datetime import datetime
|
||
|
import asyncio
|
||
|
|
||
|
app = FastAPI()
|
||
|
|
||
|
# Mount static and media folders
|
||
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||
|
app.mount("/media", StaticFiles(directory="media"), name="media")
|
||
|
|
||
|
# Templates folder
|
||
|
templates = Jinja2Templates(directory="templates")
|
||
|
|
||
|
# Python's official birth date
|
||
|
PYTHON_BIRTH = datetime(1991, 2, 20)
|
||
|
|
||
|
|
||
|
class SharedState:
|
||
|
""" Tracks Python's current age in decimal years, updated asynchronously. """
|
||
|
def __init__(self):
|
||
|
self.current_age = 0.0
|
||
|
self.running = False
|
||
|
|
||
|
async def update_age(self):
|
||
|
""" Continuously update Python's age in decimal years. """
|
||
|
while self.running:
|
||
|
now = datetime.now()
|
||
|
delta = now - PYTHON_BIRTH
|
||
|
# Convert time delta to decimal years
|
||
|
self.current_age = delta.days / 365.25 + (delta.seconds / (86400 * 365.25))
|
||
|
await asyncio.sleep(0.1) # Update about 10 times per second
|
||
|
|
||
|
|
||
|
state = SharedState()
|
||
|
|
||
|
@app.on_event("startup")
|
||
|
async def on_startup():
|
||
|
state.running = True
|
||
|
asyncio.create_task(state.update_age())
|
||
|
|
||
|
@app.on_event("shutdown")
|
||
|
async def on_shutdown():
|
||
|
state.running = False
|
||
|
|
||
|
@app.get("/", response_class=HTMLResponse)
|
||
|
async def home(request: Request):
|
||
|
"""
|
||
|
Main page with an <object> that loads /stream.
|
||
|
"""
|
||
|
return templates.TemplateResponse(
|
||
|
"index.html",
|
||
|
{
|
||
|
"request": request,
|
||
|
"now": datetime.now()
|
||
|
}
|
||
|
)
|
||
|
|
||
|
@app.get("/stream", response_class=HTMLResponse)
|
||
|
async def stream_time(request: Request):
|
||
|
"""
|
||
|
Returns a tiny HTML snippet that self-refreshes every 0.1 seconds.
|
||
|
No leftover lines, no JS. The page is simply reloaded repeatedly.
|
||
|
"""
|
||
|
return templates.TemplateResponse(
|
||
|
"counter.html",
|
||
|
{
|
||
|
"request": request,
|
||
|
"current_age": f"{state.current_age:.10f}"
|
||
|
}
|
||
|
)
|