Files
PerToolBoxServer/backend/routers/v1/stats.py
2026-03-31 16:03:55 +08:00

81 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
PerToolBox Server - 热度统计路由
Copyright (C) 2024 Sea Network Technology Studio
Author: Canglan <admin@sea-studio.top>
License: AGPL v3
"""
from datetime import datetime
from fastapi import APIRouter
from ...utils.redis_client import redis_client
from ...models import ToolStatsTotal
from ...dependencies import DbDependency
from ...middleware.rate_limit import rate_limit
router = APIRouter(prefix="/api/v1", tags=["stats"])
# 预定义工具名称(对应前端页面)
TOOL_NAMES = [
"todos", "notes", "password", "qrcode",
"crypto_hash", "crypto_base64", "crypto_url", "crypto_aes", "json"
]
@router.post("/tool/usage")
@rate_limit(requests=20, period=60)
async def record_usage(tool_name: str, db: DbDependency):
"""记录页面访问次数(热度)"""
if tool_name not in TOOL_NAMES:
raise HTTPException(status_code=400, detail="无效的工具名")
today = datetime.now().strftime("%Y-%m-%d")
today_key = f"tool:stats:today:{tool_name}:{today}"
total_key = f"tool:stats:total:{tool_name}"
# 增加今日计数设置48小时过期
today_count = redis_client.incr(today_key)
redis_client.expire(today_key, 48 * 3600)
# 增加总计数
total_count = redis_client.incr(total_key)
# 异步更新 MySQL可选这里简单处理
# 实际可改为定时任务同步,此处为简化,直接更新
stats = db.query(ToolStatsTotal).filter(ToolStatsTotal.tool_name == tool_name).first()
if stats:
stats.total_count = total_count
else:
stats = ToolStatsTotal(tool_name=tool_name, total_count=total_count)
db.add(stats)
db.commit()
return {"success": True}
@router.get("/tool/stats")
@rate_limit(requests=100, period=60)
async def get_stats(db: DbDependency):
"""获取所有工具的今日/总访问次数"""
today = datetime.now().strftime("%Y-%m-%d")
result = {}
for tool_name in TOOL_NAMES:
today_key = f"tool:stats:today:{tool_name}:{today}"
total_key = f"tool:stats:total:{tool_name}"
today_count = redis_client.get(today_key)
total_count = redis_client.get(total_key)
if total_count is None:
# 从 MySQL 读取
stats = db.query(ToolStatsTotal).filter(ToolStatsTotal.tool_name == tool_name).first()
total_count = stats.total_count if stats else 0
else:
total_count = int(total_count)
result[tool_name] = {
"today": int(today_count) if today_count else 0,
"total": total_count
}
return result