first commit
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from .aggregator import aggregate_period, enrich_snapshot_meta
|
||||
from .config import ROOT_DIR, settings
|
||||
from .db import get_latest_snapshot, init_db, log_push
|
||||
from .periods import get_today_period, get_yesterday_period
|
||||
from .scheduler import job_finalize_yesterday, job_push_wecom, job_refresh_today, start_scheduler, startup_tasks, stop_scheduler
|
||||
from .state import get_today_cache
|
||||
from .wecom import build_markdown, send_wecom_markdown
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
WEB_DIR = ROOT_DIR / "web"
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
init_db()
|
||||
if settings.proxy_enabled:
|
||||
logger.info(
|
||||
"Proxy enabled: %s (scope=%s)",
|
||||
settings.proxy_url,
|
||||
settings.proxy_for,
|
||||
)
|
||||
else:
|
||||
logger.info("Proxy disabled (direct connection)")
|
||||
await startup_tasks()
|
||||
start_scheduler()
|
||||
yield
|
||||
stop_scheduler()
|
||||
|
||||
|
||||
app = FastAPI(title="币安成交量排名监控", lifespan=lifespan)
|
||||
|
||||
if WEB_DIR.exists():
|
||||
app.mount("/static", StaticFiles(directory=str(WEB_DIR)), name="static")
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def index():
|
||||
index_path = WEB_DIR / "index.html"
|
||||
if index_path.exists():
|
||||
return FileResponse(index_path)
|
||||
return {"message": "Web UI not found. Place files in /web"}
|
||||
|
||||
|
||||
@app.get("/api/yesterday/top30")
|
||||
async def api_yesterday_top30():
|
||||
snap = get_latest_snapshot("yesterday")
|
||||
if snap:
|
||||
return {
|
||||
"period_start": snap["period_start"],
|
||||
"period_end": snap["period_end"],
|
||||
"updated_at": snap["created_at"],
|
||||
"top_n": settings.top_n,
|
||||
"volume_threshold": settings.volume_threshold,
|
||||
"change_threshold": settings.change_threshold,
|
||||
"items": snap["items"],
|
||||
}
|
||||
start, end = get_yesterday_period()
|
||||
try:
|
||||
items = await aggregate_period(start, end)
|
||||
return enrich_snapshot_meta(items, start, end)
|
||||
except Exception as e:
|
||||
logger.error("api yesterday failed: %s", e)
|
||||
meta = enrich_snapshot_meta([], start, end)
|
||||
meta["error"] = "数据暂不可用,请检查网络或稍后重试"
|
||||
return meta
|
||||
|
||||
|
||||
@app.get("/api/today/top30")
|
||||
async def api_today_top30():
|
||||
cached = get_today_cache()
|
||||
if cached:
|
||||
return cached
|
||||
start, end = get_today_period()
|
||||
try:
|
||||
items = await aggregate_period(start, end, use_live_prices=True)
|
||||
return enrich_snapshot_meta(items, start, end)
|
||||
except Exception as e:
|
||||
logger.error("api today failed: %s", e)
|
||||
meta = enrich_snapshot_meta([], start, end)
|
||||
meta["error"] = "数据暂不可用,请检查网络或稍后重试"
|
||||
return meta
|
||||
|
||||
|
||||
@app.post("/api/push/test")
|
||||
async def api_push_test():
|
||||
snap = get_latest_snapshot("yesterday")
|
||||
if not snap:
|
||||
start, end = get_yesterday_period()
|
||||
items = await aggregate_period(start, end)
|
||||
from .db import save_snapshot
|
||||
save_snapshot("yesterday", start, end, items)
|
||||
snap = get_latest_snapshot("yesterday")
|
||||
if not snap:
|
||||
raise HTTPException(500, "无法生成昨日数据")
|
||||
content = build_markdown(snap)
|
||||
ok, msg = await send_wecom_markdown(content)
|
||||
log_push(snap["period_start"], snap["period_end"], ok, msg)
|
||||
if not ok:
|
||||
raise HTTPException(500, f"推送失败: {msg}")
|
||||
return {"success": True, "message": "推送成功"}
|
||||
|
||||
|
||||
@app.post("/api/refresh/yesterday")
|
||||
async def api_refresh_yesterday():
|
||||
await job_finalize_yesterday()
|
||||
snap = get_latest_snapshot("yesterday")
|
||||
return snap or {"message": "done"}
|
||||
|
||||
|
||||
@app.post("/api/refresh/today")
|
||||
async def api_refresh_today():
|
||||
await job_refresh_today()
|
||||
return get_today_cache() or {"message": "done"}
|
||||
Reference in New Issue
Block a user