This repository has been archived on 2026-10-02. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
NeteaseUrl/core/state.py
T
snowy-yang c2a8da3e43 refactor(core): 抽出框架无关核心层 core/,为 FastAPI 迁移铺路
第一步模块拆分(纯搬运,零行为变化):
- 新增 core/ 包:config(常量/配置) + state(运行时状态) + utils(纯函数) + security(音频签名)
- main.py 改为从 core 导入并以原下划线名再导出,250+ 既有调用点零改动

关键设计:
- 状态全部原地修改,import 即共享同一对象(21 项身份断言 + 10 项冒烟全绿)
- 音频签名密钥由启动时 _init_audio_secret(app.secret_key) 注入,
  解除 core.security 对 Flask app 的依赖,新老应用可互认 token

验证:py_compile 通过;冒烟 10/10 PASS;对象身份 22/22 PASS;
waitress 真实启动 /health 200 version=2.4.0。main.py 减 229 行。
2026-09-26 00:16:04 +08:00

72 lines
3.1 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.
# -*- coding: utf-8 -*-
"""进程内运行时状态(框架无关)。
自 main.py 原样迁出:这些容器全部**原地修改**(永不重新绑定),因此
`from core.state import DOWNLOAD_TASKS` 与 main 内的旧引用共享同一对象,
搬移不改变任何并发行为。
注意:这些状态**仅存于进程内存**,重启即丢(任务记录/限流桶/统计/缓存);
持久数据(账本/用户/设置)在 SQLite(auth_system)。集中在此以便
Flask/FastAPI 迁移期共用,并为后续封装成带锁的单例(State 对象)留出唯一入口。
依赖仅限标准库 threading/collections——任何下载器/HTTP 相关对象
(如批量打包信号量)不放在这里,随对应服务模块搬迁。
"""
import collections
import threading
from typing import Any, Dict, List
# ============ 短链展开结果缓存 ============
# 用户反复解析同一分享链接不再重复请求 163cn.tv(有界防膨胀)
SHORTLINK_CACHE: Dict[str, str] = {}
SHORTLINK_CACHE_LOCK = threading.Lock()
# ============ 公网限流(按 IP 滑动窗口,防刷防爆破) ============
RATE_BUCKETS = {}
RATE_LOCK = threading.Lock()
# ============ 批量打包排队估算 ============
# 最近完成批次(成功打包过)的耗时记录,用于估算排队用户的预计等待时间
BATCH_DURATIONS = collections.deque(maxlen=10)
BATCH_DURATIONS_LOCK = threading.Lock()
# ============ 下载任务表 ============
# (批量打包 + 单曲下载统一):task_id -> {type, total, done, failed, status, start, msg, cancel, pause, device_id, result, params}
# 前端通过 /api/batch_progress 轮询进度,支持取消;完成后文件按 35 分钟保留期清理
DOWNLOAD_TASKS: Dict[str, Dict[str, Any]] = {}
DOWNLOAD_TASKS_LOCK = threading.Lock()
# ============ 设备在线心跳 ============
# device_id -> 最近心跳时间。心跳超时(PAUSE_AFTER_SECONDS)未上线的设备,其批量任务
# 自动暂停让出排队名额;超时超过 CANCEL_AFTER_SECONDS(30 分钟)则自动取消任务并删文件
DEVICE_LAST_SEEN: Dict[str, float] = {}
DEVICE_LAST_SEEN_LOCK = threading.Lock()
# ============ 接口请求统计 ============
REQUEST_STATS: Dict[str, Dict[str, Any]] = {}
STATS_LOCK = threading.Lock()
# 用户解析/下载操作记录(IP);仅保留最近 2000 条
REQ_LOG: List[Dict[str, Any]] = []
# ============ 上游探测缓存 ============
# 全局账号 MUSIC_U(5 分钟缓存;后台重新扫码后自动跟随新值)
GLOBAL_MUSIC_U_CACHE = {'v': None, 'ts': 0.0}
# 服务器网易云账号昵称缓存(10 分钟):非管理员可见响应中遮蔽真实昵称
SERVER_NICK_CACHE = {'nick': None, 'ts': 0.0}
SERVER_NICK_LOCK = threading.Lock() # 第 91 条(P3-9):刷新单飞锁,防并发重复打上游
VIP_PROBE_LOCK = threading.Lock() # 第 100 条:音质探测单飞锁(有界等待)
# 全局账号 VIP 探测缓存(5 分钟):probe 一次要打 8 次网易云接口,
# 公网下账号栏高频刷新会连累服务器账号触发风控。
VIP_CACHE = {'data': None, 'ts': 0.0}
VIP_USER_CACHE = {} # user 路径按 cookie 哈希的 5 分钟缓存