#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 数据库模块(稳定 API 门面)- SQLite P2 / O-07:拆分 `database.py` 为稳定门面 + `db/` 分域实现。 约束: - 外部仍通过 `import database` 调用(函数名/参数/返回结构保持不变) - schema/migration 入口统一,避免 scattered ALTER TABLE """ from __future__ import annotations import os import threading import time from typing import Optional import db_pool from app_config import get_config from db.schema import ensure_schema from db.migrations import migrate_database as _migrate_database from db.admin import ( admin_reset_user_password, approve_password_reset, clean_old_operation_logs, create_password_reset_request, ensure_default_admin, get_hourly_registration_count, get_pending_password_resets, get_system_config_raw as _get_system_config_raw, get_system_stats, reject_password_reset, update_admin_password, update_admin_username, update_system_config as _update_system_config, verify_admin, ) from db.accounts import ( create_account, delete_account, delete_user_accounts, get_account, get_account_status, get_user_accounts, increment_account_login_fail, reset_account_login_status, update_account_remark, ) from db.announcements import ( create_announcement, delete_announcement, dismiss_announcement_for_user, get_active_announcement_for_user, get_announcement_by_id, get_announcements, set_announcement_active, ) from db.email import ( get_user_by_email, get_user_email_notify, update_user_email, update_user_email_notify, ) from db.feedbacks import ( close_feedback, create_bug_feedback, delete_feedback, get_bug_feedbacks, get_feedback_by_id, get_feedback_stats, get_user_feedbacks, reply_feedback, ) from db.schedules import ( clean_old_schedule_logs, create_schedule_execution_log, create_user_schedule, delete_schedule_logs, delete_user_schedule, get_due_user_schedules, get_enabled_user_schedules, get_schedule_by_id, get_schedule_execution_logs, get_user_all_schedule_logs, get_user_schedules, recompute_schedule_next_run, toggle_user_schedule, update_schedule_next_run, update_schedule_execution_log, update_schedule_last_run, update_user_schedule, ) from db.tasks import create_task_log, delete_old_task_logs, get_task_logs, get_task_stats, get_user_run_stats from db.users import ( approve_user, create_user, delete_user, extend_user_vip, get_all_users, get_pending_users, get_user_by_id, get_user_by_username, get_user_stats, get_user_vip_info, get_vip_config, is_user_vip, reject_user, remove_user_vip, set_default_vip_days, set_user_vip, verify_user, ) from db.security import record_login_context config = get_config() # 数据库文件路径 DB_FILE = config.DB_FILE # 数据库版本 (用于迁移管理) DB_VERSION = 14 # ==================== 系统配置缓存(P1 / O-03) ==================== _system_config_cache_lock = threading.Lock() _system_config_cache_value: Optional[dict] = None _system_config_cache_loaded_at = 0.0 try: _SYSTEM_CONFIG_CACHE_TTL_SECONDS = float(os.environ.get("SYSTEM_CONFIG_CACHE_TTL_SECONDS", "3")) except Exception: _SYSTEM_CONFIG_CACHE_TTL_SECONDS = 3.0 _SYSTEM_CONFIG_CACHE_TTL_SECONDS = max(0.0, _SYSTEM_CONFIG_CACHE_TTL_SECONDS) def invalidate_system_config_cache() -> None: global _system_config_cache_value, _system_config_cache_loaded_at with _system_config_cache_lock: _system_config_cache_value = None _system_config_cache_loaded_at = 0.0 def init_database(): """初始化数据库表结构 + 迁移(入口统一)。""" db_pool.init_pool(DB_FILE, pool_size=config.DB_POOL_SIZE) with db_pool.get_db() as conn: ensure_schema(conn) _migrate_database(conn, DB_VERSION) ensure_default_admin() def migrate_database(): """数据库迁移(对外保留接口)。""" with db_pool.get_db() as conn: ensure_schema(conn) _migrate_database(conn, DB_VERSION) # ==================== 系统配置管理(缓存门面) ==================== def get_system_config(): """获取系统配置(带进程内缓存)。""" global _system_config_cache_value, _system_config_cache_loaded_at now_ts = time.time() with _system_config_cache_lock: if _system_config_cache_value is not None: if _SYSTEM_CONFIG_CACHE_TTL_SECONDS <= 0 or (now_ts - _system_config_cache_loaded_at) < _SYSTEM_CONFIG_CACHE_TTL_SECONDS: return dict(_system_config_cache_value) value = _get_system_config_raw() with _system_config_cache_lock: _system_config_cache_value = dict(value) _system_config_cache_loaded_at = now_ts return dict(value) def update_system_config( max_concurrent=None, schedule_enabled=None, schedule_time=None, schedule_browse_type=None, schedule_weekdays=None, max_concurrent_per_account=None, max_screenshot_concurrent=None, proxy_enabled=None, proxy_api_url=None, proxy_expire_minutes=None, auto_approve_enabled=None, auto_approve_hourly_limit=None, auto_approve_vip_days=None, ): """更新系统配置(写入后立即失效缓存)。""" ok = _update_system_config( max_concurrent=max_concurrent, schedule_enabled=schedule_enabled, schedule_time=schedule_time, schedule_browse_type=schedule_browse_type, schedule_weekdays=schedule_weekdays, max_concurrent_per_account=max_concurrent_per_account, max_screenshot_concurrent=max_screenshot_concurrent, proxy_enabled=proxy_enabled, proxy_api_url=proxy_api_url, proxy_expire_minutes=proxy_expire_minutes, auto_approve_enabled=auto_approve_enabled, auto_approve_hourly_limit=auto_approve_hourly_limit, auto_approve_vip_days=auto_approve_vip_days, ) if ok: invalidate_system_config_cache() return ok