Files
wordloop/backend/services/wiki_llm_quota_service.py
john 05e173b293 Ship native iOS app, Wiki/TTS backend, and skeleton loading UX.
Replace the WebView shell with SwiftUI screens, add account-scoped Wiki and TTS APIs with adaptive review and photo scan support, and keep web/iOS pages usable while data loads asynchronously.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 15:13:59 +08:00

89 lines
2.9 KiB
Python

from __future__ import annotations
from datetime import datetime, timezone
from sqlalchemy.orm import Session
from config import get_settings
from models import User, WikiLlmUsage
class WikiLlmQuotaExceeded(Exception):
def __init__(self, *, daily_limit: int, used_today: int):
self.daily_limit = daily_limit
self.used_today = used_today
super().__init__(
f"今日 AI 整理额度已用完({used_today}/{daily_limit} 次),请充值后继续使用"
)
class WikiLlmQuotaService:
def daily_limit(self) -> int:
return max(1, int(get_settings().ai_wiki_daily_llm_limit))
def usage_date(self, now: datetime | None = None) -> str:
current = now or datetime.now(timezone.utc)
return current.strftime("%Y-%m-%d")
def get_usage_row(self, db: Session, user: User, usage_date: str | None = None) -> WikiLlmUsage:
day = usage_date or self.usage_date()
row = (
db.query(WikiLlmUsage)
.filter(WikiLlmUsage.user_id == user.id, WikiLlmUsage.usage_date == day)
.first()
)
if not row:
row = WikiLlmUsage(
user_id=user.id,
usage_date=day,
call_count=0,
)
db.add(row)
db.flush()
return row
def used_today(self, db: Session, user: User) -> int:
return int(self.get_usage_row(db, user).call_count)
def remaining_today(self, db: Session, user: User) -> int:
return max(0, self.daily_limit() - self.used_today(db, user))
def quota_dict(self, db: Session, user: User) -> dict:
limit = self.daily_limit()
used = self.used_today(db, user)
remaining = max(0, limit - used)
return {
"daily_limit": limit,
"used_today": used,
"remaining_today": remaining,
"quota_exceeded": remaining <= 0,
"recharge_message": (
"今日 AI 整理额度已用完,请充值后继续使用"
if remaining <= 0
else None
),
}
def consume(self, db: Session, user: User, *, count: int = 1) -> dict:
if count <= 0:
return self.quota_dict(db, user)
row = self.get_usage_row(db, user)
limit = self.daily_limit()
if row.call_count + count > limit:
raise WikiLlmQuotaExceeded(daily_limit=limit, used_today=row.call_count)
row.call_count += count
db.flush()
return self.quota_dict(db, user)
def require_available(self, db: Session, user: User) -> dict:
quota = self.quota_dict(db, user)
if quota["quota_exceeded"]:
raise WikiLlmQuotaExceeded(
daily_limit=quota["daily_limit"],
used_today=quota["used_today"],
)
return quota
wiki_llm_quota_service = WikiLlmQuotaService()