feat: switch config to JSONC + split secrets.json
Load business config as JSONC (comments + trailing commas) via an in-repo stripper then stdlib json — no new deps. Default path prefers config.jsonc, falls back to legacy config.json. Auth write-back targets only sibling secrets.json so JSONC comments are never wiped; secrets overlay merges on load. Examples, compose, Docker, docs, favsort and tools all share the same loader. Phase A only — no DB settings migration.
This commit was merged in pull request #4.
This commit is contained in:
1 parent
b4f0f45c4e
commit
8e7ead1669
21 files changed
+652
-182
No files matched your search
@@ -31,6 +31,7 @@ from typing import Any, Mapping, Sequence
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from reaction_board.config import default_config_path # noqa: E402
|
||||
from reaction_board.database import Database # noqa: E402
|
||||
from reaction_board.repository import Repository # noqa: E402
|
||||
from reaction_board.timeutil import SHANGHAI_TZ # noqa: E402
|
||||
@@ -226,19 +227,19 @@ def _database_path(config_path: str, override: str | None) -> Path:
|
||||
return Path(override)
|
||||
from reaction_board.config import ConfigStore
|
||||
|
||||
candidates = [Path(config_path), Path("/config/config.json")]
|
||||
candidates = [Path(config_path), Path("/config/config.jsonc"), Path("/config/config.json")]
|
||||
for candidate in candidates:
|
||||
if candidate.exists():
|
||||
return ConfigStore(str(candidate), require_auth=False).get().storage.database_path
|
||||
raise ValueError(
|
||||
"找不到配置文件;请用 --db /data/app.db 或 --config /config/config.json"
|
||||
"找不到配置文件;请用 --db /data/app.db 或 --config /config/config.jsonc"
|
||||
)
|
||||
|
||||
|
||||
def main(argv: Sequence[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description="从 B 站粉丝历史 CSV 回填 up_stat")
|
||||
parser.add_argument("--csv", required=True, help="粉丝历史 CSV 路径")
|
||||
parser.add_argument("--config", default=str(ROOT / "config.json"), help="配置文件")
|
||||
parser.add_argument("--config", default=str(default_config_path(ROOT)), help="配置文件")
|
||||
parser.add_argument("--db", default=None, help="直接指定数据库(覆盖配置)")
|
||||
parser.add_argument("--mid", type=int, default=DEFAULT_MID, help="写入的 B 站 mid")
|
||||
parser.add_argument("--force", action="store_true", help="覆盖同日期已有 ok=1 记录")
|
||||
|
||||
+3
-2
@@ -49,8 +49,9 @@ def get(url, cookie):
|
||||
|
||||
|
||||
def main():
|
||||
cfg = json.load(open(os.path.join(ROOT, "config.json"), encoding="utf-8"))
|
||||
full = cfg["cookie"]
|
||||
from reaction_board.config import default_config_path, load_config
|
||||
app = load_config(default_config_path(ROOT), require_auth=False)
|
||||
full = app.bilibili.read.cookie or app.bilibili.write.cookie
|
||||
anon = strip_identity(full)
|
||||
|
||||
variants = [("完整 cookie", full), ("去掉身份字段", anon), ("完全无 cookie", None)]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
用法::
|
||||
|
||||
uv run python tools/seed_preview_db.py --days 7 --seed 20261031
|
||||
uv run python app.py serve --preview --config data/preview/config.json
|
||||
uv run python app.py serve --preview --config data/preview/config.jsonc
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -31,7 +31,9 @@ from reaction_board.timeutil import SHANGHAI_TZ, shanghai_datetime # noqa: E402
|
||||
|
||||
DEFAULT_SOURCE = ROOT / "data" / "app.db"
|
||||
DEFAULT_TARGET = ROOT / "data" / "preview" / "app.db"
|
||||
DEFAULT_CONFIG_SOURCE = ROOT / "config.json"
|
||||
from reaction_board.config import default_config_path # noqa: E402
|
||||
|
||||
DEFAULT_CONFIG_SOURCE = default_config_path(ROOT)
|
||||
|
||||
BASE_DAILY_RATES: dict[str, float] = {
|
||||
"view": 0.0040,
|
||||
@@ -187,8 +189,9 @@ def _read_source_config(path: Path | None) -> dict[str, Any] | None:
|
||||
if path is None or not path.exists():
|
||||
return None
|
||||
try:
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, json.JSONDecodeError):
|
||||
from reaction_board import jsonc
|
||||
data = jsonc.load(path)
|
||||
except (OSError, ValueError):
|
||||
return None
|
||||
return data if isinstance(data, dict) else None
|
||||
|
||||
@@ -617,7 +620,7 @@ def seed_preview(
|
||||
config_target = (
|
||||
Path(config_out).resolve()
|
||||
if config_out is not None
|
||||
else target_path.parent / "config.json"
|
||||
else target_path.parent / "config.jsonc"
|
||||
)
|
||||
config_target.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
Reference in new issue
Block a user