stats/app.py

122 lines
3.5 KiB
Python
Raw Normal View History

2024-05-31 03:32:14 +00:00
from typing import List, Union
from pathlib import Path
from datetime import datetime, timedelta, timezone
from urllib.parse import urlparse
from json import dumps
2024-10-22 19:32:42 +09:00
from pprint import pprint
2024-05-31 03:32:14 +00:00
from requests import post
from fastapi import FastAPI, Response, Header, status
from fastapi.responses import JSONResponse, PlainTextResponse, FileResponse
from contextlib import asynccontextmanager
2024-05-31 03:32:14 +00:00
def fastapi_serve(dir: str, ref: str, indexes: List[str] = ["index.html", "index.htm"]) -> Response:
url_path = urlparse(ref or "/").path
root = Path(dir)
try_files = []
if url_path.endswith("/"):
try_files += [root / url_path.lstrip("/") / i for i in indexes]
try_files += [root / url_path]
try_files_tried = [t for t in try_files if t.is_file()]
print(try_files, try_files_tried)
if not try_files_tried:
return PlainTextResponse("指定されたファイルが見つかりません", status.HTTP_404_NOT_FOUND)
path = try_files_tried[0]
print(path, "をサーブ中")
return FileResponse(path)
ctx = {}
@asynccontextmanager
async def lifespan(app: FastAPI):
ctx["daily"] = Path("analytics_daily.txt").read_text("UTF-8")
ctx["hourly"] = Path("analytics_hourly.txt").read_text("UTF-8")
2024-10-22 19:32:42 +09:00
pprint(ctx)
yield
ctx.clear()
app = FastAPI(lifespan=lifespan)
2024-05-31 03:32:14 +00:00
2024-06-22 19:33:50 +09:00
@app.get("/api/cloudflare")
2024-05-31 03:32:14 +00:00
async def cloudflare(zone_id: str, x_token: Union[str, None] = Header()):
now = datetime.now()
before = now - timedelta(**{ "days": 30 })
variables = {
"zoneTag": zone_id,
"from": before.astimezone(timezone.utc).strftime("%Y-%m-%d"),
"to": now.astimezone(timezone.utc).strftime("%Y-%m-%d"),
"limit": 30
}
result = post(
url="https://api.cloudflare.com/client/v4/graphql",
headers={
"Authorization": f"Bearer {x_token}"
},
data=dumps({
"query": ctx["daily"],
2024-05-31 03:32:14 +00:00
"variables": variables
})
)
2024-06-27 01:41:35 +09:00
json = result.json()
res = JSONResponse(json)
if "data" in json and not json["errors"]:
2025-01-31 16:51:57 +09:00
pass
else:
2024-06-27 01:41:35 +09:00
res.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
2025-01-31 18:30:03 +09:00
res.headers["Cache-Control"] = f"public, max-age=60, s-maxage=60"
res.headers["CDN-Cache-Control"] = f"max-age=60"
2024-05-31 03:32:14 +00:00
return res
2024-06-22 19:33:50 +09:00
@app.get("/api/cloudflare2")
async def cloudflare2(zone_id: str, x_token: Union[str, None] = Header()):
now = datetime.now()
before = now - timedelta(**{ "hours": 72 })
variables = {
"zoneTag": zone_id,
"from": before.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
"to": now.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
"limit": 72
}
result = post(
url="https://api.cloudflare.com/client/v4/graphql",
headers={
"Authorization": f"Bearer {x_token}"
},
data=dumps({
"query": ctx["hourly"],
2024-06-22 19:33:50 +09:00
"variables": variables
})
)
2024-06-27 01:41:35 +09:00
json = result.json()
res = JSONResponse(json)
if "data" in json and not json["errors"]:
2025-01-31 16:51:57 +09:00
pass
else:
2024-06-27 01:41:35 +09:00
res.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
2025-01-31 18:30:03 +09:00
res.headers["Cache-Control"] = f"public, max-age=60, s-maxage=60"
res.headers["CDN-Cache-Control"] = f"max-age=60"
2024-06-22 19:33:50 +09:00
return res
2024-05-31 03:32:14 +00:00
@app.get("/")
@app.get("/{ref:path}")
async def home(ref: str = None):
res = fastapi_serve("static", ref)
res.headers["Cache-Control"] = "public, max-age=3600, s-maxage=3600"
res.headers["CDN-Cache-Control"] = "max-age=3600"
return res