- 7部经文迁移至 sutras/ 目录,/api/sutras 实时扫描返回清单 - 前端改为按需懒加载经文 JSON(selectToken 防快速切换乱序) - add_sutra.sh:校验+上传/删除 一键管理,免重启 - 修正生僻异体字(𫗪→喂、𫄨→絺、𦈎→繟、鬪→斗) - run.md 同步新架构与经文管理文档 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
89 lines
3.2 KiB
Bash
Executable File
89 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 管理服务器上的经文:加经 / 减经。
|
||
# 目录是实时扫描的,无需重启服务,操作完即生效。
|
||
#
|
||
# 用法:
|
||
# ./add_sutra.sh <经文.json> # 加经(校验 → 上传 → 验证)
|
||
# ./add_sutra.sh --remove <id> # 减经(如 ./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 <id>(如 $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 <id>"; 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 即可在下拉框看到。"
|