|
from apscheduler.executors.asyncio import AsyncIOExecutor |
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler |
|
from contextlib import asynccontextmanager |
|
from datetime import datetime |
|
from fastapi import FastAPI, Request |
|
from fastapi.responses import FileResponse, PlainTextResponse, Response |
|
from typing import Any |
|
|
|
import httpx |
|
import json |
|
import subprocess |
|
|
|
|
|
class PrettyJSONResponse(Response): |
|
media_type = "application/json" |
|
|
|
def render(self, content: Any) -> bytes: |
|
return json.dumps(content, indent=2).encode("utf-8") |
|
|
|
|
|
@asynccontextmanager |
|
async def lifespan(app: FastAPI): |
|
scheduler.start() |
|
yield |
|
scheduler.shutdown() |
|
|
|
|
|
app = FastAPI(lifespan=lifespan) |
|
|
|
|
|
@app.middleware("http") |
|
async def log_request(request: Request, call_next: Any): |
|
ts = datetime.now().strftime("%y%m%d%H%M%S%f") |
|
data = { |
|
"day": int(ts[:6]), |
|
"dt": int(ts[:-3]), |
|
"url": request.url, |
|
"query_params": request.query_params, |
|
"client": request.client.host, |
|
"method": request.method, |
|
"headers": dict(request.headers), |
|
} |
|
output = json.dumps( |
|
obj=data, |
|
default=str, |
|
indent=None, |
|
separators=(", ", ":"), |
|
) |
|
with open("a.json", "a") as f: |
|
separator = "\n" if f.tell() else "" |
|
f.write(separator + output) |
|
|
|
response = await call_next(request) |
|
return response |
|
|
|
|
|
@app.get("/") |
|
def read_root(request: Request): |
|
query_params = dict(request.query_params) |
|
py_ver = query_params.pop("python", "3.12") |
|
if "Windows" in request.headers.get("user-agent"): |
|
pup_url = "https://raw.githubusercontent.com/liquidcarbon/puppy/main/pup.ps1" |
|
script = [f"& ([scriptblock]::Create((iwr -useb {pup_url}).Content)) {py_ver}"] |
|
else: |
|
pup_url = "https://raw.githubusercontent.com/liquidcarbon/puppy/main/pup.sh" |
|
script = [f"curl -fsSL {pup_url} | bash -s {py_ver}"] |
|
|
|
pixi_packages = query_params.pop("pixi", "") |
|
if pixi_packages: |
|
for pkg in pixi_packages.split(","): |
|
script.append(f"pixi add {pkg}") |
|
|
|
|
|
for venv, uv_packages in query_params.items(): |
|
for pkg in uv_packages.split(","): |
|
script.append(f"pup add {venv} {pkg}") |
|
|
|
script.append("# script ends here\n") |
|
return PlainTextResponse("\n".join(script)) |
|
|
|
|
|
@app.get("/a", response_class=PrettyJSONResponse) |
|
def get_analytics(n: int = 5): |
|
if n == 0: |
|
cmd = "cat a.json" |
|
else: |
|
cmd = f"tail -{n} a.json" |
|
json_lines = subprocess.run(cmd.split(), capture_output=True).stdout |
|
content = json.loads(f"[{json_lines.replace(b"\n", b",").decode()}]") |
|
return content |
|
|
|
|
|
@app.api_route("/qa", response_class=FileResponse, methods=["GET", "HEAD"]) |
|
def query_analytics(): |
|
return "a.json" |
|
|
|
|
|
@app.get("/favicon.ico") |
|
async def favicon(): |
|
return {"message": "woof!"} |
|
|
|
|
|
@app.get("/ping") |
|
async def ping(): |
|
return {"message": "woof!"} |
|
|
|
|
|
async def self_ping(): |
|
async with httpx.AsyncClient() as client: |
|
_ = await client.get("http://0.0.0.0:7860/ping") |
|
|
|
|
|
scheduler = AsyncIOScheduler(executors={"default": AsyncIOExecutor()}) |
|
scheduler.add_job(self_ping, "interval", minutes=60) |
|
|