#!/usr/bin/env bash # 管理服务器上的经文:加经 / 减经。 # 目录是实时扫描的,无需重启服务,操作完即生效。 # # 用法: # ./add_sutra.sh <经文.json> # 加经(校验 → 上传 → 验证) # ./add_sutra.sh --remove # 减经(如 ./add_sutra.sh -d qingjing) # FJ_PASS=xxx ./add_sutra.sh ... # 密码登录(需 sshpass);已配 SSH key 则不需要 # # JSON 格式见 sutras/ 下现有文件:id/order/name/cat/title/seal/translator/source/sourceUrl/pageSize/segments[{h?,g?,t}] set -euo pipefail cd "$(dirname "$0")" HOST=154.8.162.18 USER=root DEST=/opt/fj/sutras SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=15" SSH_CMD="ssh $SSH_OPTS" if [ -n "${FJ_PASS:-}" ]; then command -v sshpass >/dev/null || { echo "缺少 sshpass:brew install sshpass 或改用 SSH key"; exit 1; } SSH_CMD="sshpass -p $FJ_PASS ssh $SSH_OPTS" fi list_remote() { curl -s --max-time 15 https://fj.all8ai.top/api/sutras | python3 -c " import json, sys items = {s['id']: s['name'] for s in json.load(sys.stdin)['sutras']} print(' 当前目录:' + ('、'.join(items.values()) or '(空)')) " } # ---- 减经 ---- if [ "${1:-}" = "--remove" ] || [ "${1:-}" = "-d" ]; then ID="${2:-}" if [ -z "$ID" ]; then echo "用法:$0 --remove (如 $0 -d qingjing)"; exit 1 fi echo "==> 删除 $USER@$HOST:$DEST/ 中 id=$ID 的经文" # 按文件名或 JSON 内 id 字段匹配,命中即删 $SSH_CMD "$USER@$HOST" "python3 -c 'import json,sys,pathlib d=pathlib.Path(\"$DEST\") i=\"$ID\" for f in sorted(d.glob(\"*.json\")): try: meta=json.loads(f.read_text(encoding=\"utf-8\")) except Exception: continue if f.stem==i or meta.get(\"id\")==i: f.unlink(); print(\"已删除\", f.name); break else: print(\"不存在:\", i); sys.exit(1)'" echo "==> 验证目录接口" sleep 1 list_remote echo "完成。该经的 TTS 缓存文件仍在 cache/(无害,复用文本时仍可命中)。" exit 0 fi # ---- 加经 ---- FILE="${1:-}" if [ -z "$FILE" ] || [ ! -f "$FILE" ]; then echo "用法:$0 <经文.json> 或 $0 --remove "; exit 1 fi # 基本校验:合法 JSON + 必填字段齐全 + segments 非空且每段有 t echo "==> 校验 $FILE" python3 - "$FILE" <<'PY' import json, sys d = json.load(open(sys.argv[1], encoding="utf-8")) req = ["id", "name", "cat", "title", "seal", "translator", "source", "sourceUrl", "pageSize", "segments"] missing = [k for k in req if k not in d] assert not missing, f"缺少字段: {missing}" segs = d["segments"] assert isinstance(segs, list) and segs, "segments 必须是非空数组" assert all(s.get("t") for s in segs), "存在缺 t 字段的段" long_seg = [i for i, s in enumerate(segs) if len(s["t"]) > 800] assert not long_seg, f"第 {long_seg} 段超过 800 字上限,请拆分" print(f" 《{d['name']}》 {len(segs)} 段, 分类 {d['cat']}, order {d.get('order', 99)} —— 校验通过") PY NAME=$(basename "$FILE") echo "==> 上传到 $USER@$HOST:$DEST/$NAME" rsync -az --timeout=30 -e "$SSH_CMD" "$FILE" "$USER@$HOST:$DEST/$NAME" echo "==> 验证目录接口" sleep 1 list_remote echo "完成。刷新 https://fj.all8ai.top 即可在下拉框看到。"