初始提交:短剧库源码(含转码优化 ultrafast)

This commit is contained in:
yvan
2026-09-17 19:09:08 +08:00
commit 07dc0f1059
247 changed files with 43242 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
@echo off
chcp 65001 >nul
cd /d "%~dp0.."
if not exist dist mkdir dist
set CGO_ENABLED=0
set GOOS=windows
set GOARCH=amd64
go build -trimpath -ldflags="-s -w" -o dist\juku_windows_amd64.exe .
if errorlevel 1 exit /b 1
echo 已生成 dist\juku_windows_amd64.exe
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")/.."
mkdir -p dist
echo "Building macOS arm64..."
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -trimpath -ldflags="-s -w" -o dist/juku_darwin_arm64 .
echo "Building macOS amd64..."
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o dist/juku_darwin_amd64 .
echo "Building Linux amd64..."
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o dist/juku_linux_amd64 .
echo "Building Windows amd64..."
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o dist/juku_windows_amd64.exe .
echo "Done. Files are in dist/."
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
project_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
if ! command -v docker >/dev/null 2>&1; then
echo "请先安装 Docker。" >&2
exit 1
fi
exec docker build --pull -t "${JUKU_IMAGE:-juku:local}" "$@" "$project_dir"
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
project_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
if ! command -v docker >/dev/null 2>&1 || ! docker compose version >/dev/null 2>&1; then
echo "请先安装 Docker 及 Compose v2。" >&2
exit 1
fi
exec docker compose --project-directory "$project_dir" -f "$project_dir/compose.yaml" up -d --build "$@"
+189
View File
@@ -0,0 +1,189 @@
#!/usr/bin/env python3
"""把新版 短剧库.zip 与本地源码对比,展示变更并更新本地旧代码。
用法:
python scripts/update_from_zip.py # 从默认地址下载最新包并预览变更
python scripts/update_from_zip.py --apply # 下载并真正更新本地代码
python scripts/update_from_zip.py 某个路径/短剧库.zip # 用本地压缩包
python scripts/update_from_zip.py --url https://... # 指定其他下载地址
行为:
1. 读取压缩包(自动处理中文文件名 GBK/UTF-8、自动剥离压缩包内公共顶层目录)
2. 与本地源码逐文件比对(忽略 .git、data/、日志、压缩包等运行时文件)
3. 列出 新增 / 修改 / 删除 三类变更;加 --apply 后写入本地
4. 更新完成后用 git status / git diff 自查,再提交
"""
import argparse
import hashlib
import sys
import tempfile
import urllib.parse
import urllib.request
import zipfile
from pathlib import Path
DEFAULT_URL = "https://www.252035.xyz/短剧库.zip"
REPO_ROOT = Path(__file__).resolve().parent.parent
IGNORE_DIRS = {".git", "data", "__pycache__", "dist", "短剧下载"}
IGNORE_SUFFIX = {".log", ".zip", ".tar", ".pyc"}
IGNORE_NAMES = {".DS_Store", "Thumbs.db"}
PROTECT = {"scripts/update_from_zip.py"} # 更新工具自身,永远不删
def download(url: str) -> Path:
quoted = urllib.parse.quote(url, safe=":/?&=%")
print(f"下载最新压缩包:{url}")
request = urllib.request.Request(quoted, headers={"User-Agent": "juku-update/1.0"})
with urllib.request.urlopen(request, timeout=60) as resp:
total = int(resp.headers.get("Content-Length") or 0)
target = Path(tempfile.gettempdir()) / "短剧库-update.zip"
done = 0
with target.open("wb") as f:
while True:
chunk = resp.read(1 << 16)
if not chunk:
break
f.write(chunk)
done += len(chunk)
if total:
print(f"\r {done}/{total} 字节", end="", flush=True)
print(f"\n 已保存到 {target}")
return target
def norm_name(info: zipfile.ZipInfo) -> str:
"""修正 zip 内中文文件名。
打包工具有两种常见错误:用 UTF-8 编码但不打 0x800 标志(跨平台工具),
或用 GBK 编码且不打标志(中文 Windows 右键压缩)。依次尝试恢复:
UTF-8 优先(其字节序列极少与 GBK 混淆),失败再试 GBK。
"""
name = info.filename
if not info.flag_bits & 0x800:
try:
raw = name.encode("cp437")
except UnicodeEncodeError:
return name.replace("\\", "/")
for encoding in ("utf-8", "gbk"):
try:
name = raw.decode(encoding)
break
except UnicodeDecodeError:
continue
return name.replace("\\", "/")
def ignored(rel: str) -> bool:
parts = rel.split("/")
return (
any(p in IGNORE_DIRS for p in parts[:-1])
or Path(rel).name in IGNORE_NAMES
or Path(rel).suffix in IGNORE_SUFFIX
)
def common_prefix(names: list[str]) -> str:
"""所有条目共享同一顶层目录时返回该前缀(如 '短剧库/'),否则返回空串。"""
if not names:
return ""
tops = {n.split("/", 1)[0] for n in names}
if len(tops) == 1 and all("/" in n for n in names):
return next(iter(tops)) + "/"
return ""
def md5_of(path: Path) -> str:
h = hashlib.md5()
with path.open("rb") as f:
for chunk in iter(lambda: f.read(1 << 16), b""):
h.update(chunk)
return h.hexdigest()
def main() -> int:
parser = argparse.ArgumentParser(description="用新版 zip 更新本地短剧库源码")
parser.add_argument("zipfile", nargs="?", default=None,
help="本地压缩包路径;省略则从 --url 地址下载最新包")
parser.add_argument("--url", default=DEFAULT_URL, help=f"新版下载地址(默认 {DEFAULT_URL})")
parser.add_argument("--apply", action="store_true", help="真正写入本地(默认只预览)")
args = parser.parse_args()
if args.zipfile:
zip_path = Path(args.zipfile)
if not zip_path.exists():
print(f"找不到压缩包:{args.zipfile}")
return 1
else:
zip_path = download(args.url)
with zipfile.ZipFile(zip_path) as zf:
infos = [i for i in zf.infolist() if not i.is_dir()]
names = [norm_name(i) for i in infos]
# 先丢弃 macOS 压缩附带的资源文件,避免干扰顶层目录识别
pairs = [
(info, name)
for info, name in zip(infos, names)
if "__MACOSX" not in name.split("/") and not Path(name).name.startswith("._")
]
prefix = common_prefix([name for _, name in pairs])
if prefix:
print(f"检测到压缩包顶层目录:{prefix}(比对时已忽略)")
incoming: dict[str, bytes] = {}
for info, name in pairs:
rel = name[len(prefix):] if prefix else name
if rel and not ignored(rel):
incoming[rel] = zf.read(info)
added, modified, unchanged = [], [], []
for rel, blob in sorted(incoming.items()):
local = REPO_ROOT / rel
if not local.exists():
added.append(rel)
elif md5_of(local) != hashlib.md5(blob).hexdigest():
modified.append(rel)
else:
unchanged.append(rel)
local_files: set[str] = set()
for path in REPO_ROOT.rglob("*"):
if not path.is_file():
continue
rel = path.relative_to(REPO_ROOT).as_posix()
if ignored(rel) or rel in IGNORE_NAMES:
continue
local_files.add(rel)
deleted = sorted(local_files - set(incoming) - PROTECT)
print(f"\n对比完成:压缩包 {len(incoming)} 个文件,本地 {len(local_files)} 个文件")
print(f" 新增 {len(added)} 个")
for rel in added:
print(f" + {rel}")
print(f" 修改 {len(modified)} 个")
for rel in modified:
print(f" ~ {rel}")
print(f" 删除 {len(deleted)} 个")
for rel in deleted:
print(f" - {rel}")
print(f" 未变化 {len(unchanged)} 个")
if not (added or modified or deleted):
print("本地代码与压缩包一致,无需更新。")
return 0
if not args.apply:
print("\n当前为预览模式。确认无误后追加 --apply 执行更新,然后 git add -A && git commit。")
return 0
for rel in added + modified:
target = REPO_ROOT / rel
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(incoming[rel])
print(f"已写入 {rel}")
for rel in deleted:
(REPO_ROOT / rel).unlink(missing_ok=True)
print(f"已删除 {rel}")
print("\n更新完成。请执行 git status / git diff 复核后提交。")
return 0
if __name__ == "__main__":
sys.exit(main())
+11
View File
@@ -0,0 +1,11 @@
@echo off
chcp 65001 >nul
title 短剧库
cd /d "%~dp0.."
if not exist "dist\juku_windows_amd64.exe" (
echo 找不到下载器,请先编译或获取包含 dist 的完整版本。
pause
exit /b 1
)
"dist\juku_windows_amd64.exe" %*
if errorlevel 1 pause
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.."
case "$(uname -m)" in
arm64) binary="./dist/juku_darwin_arm64" ;;
x86_64) binary="./dist/juku_darwin_amd64" ;;
*) echo "不支持的 macOS 架构,请使用 go run ."; exit 1 ;;
esac
if [ ! -x "$binary" ]; then
echo "找不到可执行程序,请先在项目目录运行 ./scripts/build.sh。"
exit 1
fi
exec "$binary" "$@"
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.."
if [ ! -x "./dist/juku_linux_amd64" ]; then
echo "找不到 Linux x64 程序,请先运行 ./scripts/build.sh。"
exit 1
fi
exec ./dist/juku_linux_amd64 "$@"