"""Flask Web Server
所有 HTTP 路由集中在 backend.api 包管理,本文件仅负责:
1. 注册 Blueprint
2. 启动服务
启动方式:
./start.sh <notifier_name> <notifier_token>
"""
from __future__ import annotations
import sys
from flask import Flask
from backend.core.database import init_db
from backend.core.logger import get_logger
from backend.dispatcher.monitor import monitor
from backend.services import user_service
LOGGER = get_logger("backend.server")
app = Flask(__name__)
from backend.api import api_bp, webhook, static
app.register_blueprint(webhook.webhook_bp)
app.register_blueprint(api_bp)
app.register_blueprint(static.static_bp)
def main() -> None:
"""启动入口:解析参数 → 初始化 → 启动服务"""
import argparse
parser = argparse.ArgumentParser(description="CodeSpectra Webhook Server")
parser.add_argument("--host", default="0.0.0.0", help="监听地址 (默认: 0.0.0.0)")
parser.add_argument("--port", type=int, default=8000, help="监听端口 (默认: 8000)")
parser.add_argument("--notifier-name", required=True, help="notifier 账户名")
parser.add_argument("--notifier-token", required=True, help="notifier access_token")
args = parser.parse_args()
init_db()
import backend.handlers
import atexit
from backend.dispatcher.routes import collect_stat_keys
from backend.services import monitor_service
monitor.restore(
total=monitor_service.load_total_requests(),
cumulative_uptime=monitor_service.load_cumulative_uptime(),
routes=monitor_service.load_route_stats(),
peak=monitor_service.load_peak_window_count(),
)
stale_routes = monitor.prune_stale_route_stats(collect_stat_keys())
if stale_routes:
LOGGER.info(f"cleaned stale route stats: {stale_routes}")
atexit.register(monitor.persist)
monitor.start_periodic_persist()
user_service.get_or_create_user(args.notifier_name, "notifier", access_token=args.notifier_token)
user_service.update_user(args.notifier_name, type="notifier", access_token=args.notifier_token)
LOGGER.info(f"notifier user [{args.notifier_name}] is ready")
LOGGER.info("init successfully, starting server")
LOGGER.info(f"start waitress @ {args.host}:{args.port}")
sys.stdout.flush()
import waitress
waitress.serve(
app,
host=args.host,
port=args.port,
threads=8,
_quiet=True,
)
if __name__ == "__main__":
main()