# -*- coding: utf-8 -*- r'''守卫:对外公开的材料里不许出现「中转管理后台」。 用户定的规矩(原话): 「你对外公开的数据里不要包含那个中转站管理的页面,你就只能提官网」 范围(用户已确认): ✅ 必须干净:发布说明、CHANGELOG、官网页面、README、我对外的汇报 ❌ 不用管:服务端 zip 里的运维文档(给装机的人看)、 源码实现(路径是功能本身)、_build/_tests 内部材料 为什么写成测试而不是写进文档: 文档没人看。这一天里我因为"以为记住了"翻了三次车, 所以把规矩变成会红的断言 —— 违反了立刻报错。 顺便也守住另外两条用户明确说过的: * 官网里不能出现管理入口 * 发布说明只能是更新内容 ''' from __future__ import annotations import re import sys from pathlib import Path ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") # 这些词一律不许出现在对外材料里 FORBIDDEN = [ "zhongzhuanzhan", "/admin", "管理后台", "管理页", "管理入口", "管理面板", "admin_password", ] # 对外公开的文件(相对路径) PUBLIC_FILES = [ "_build/CHANGELOG.md", "README.md", ] # 对外公开的目录:里面所有 .md 都要干净 PUBLIC_DIRS = [ "docs", ] # docs 里这些是**运维文档**,是给装服务器的人看的,允许提到管理页 DOCS_ALLOWLIST = { "AFTER-INSTALL.txt", "BEFORE-INSTALL.txt", "LICENSE.txt", "项目规矩.md", # 这份文件本身就是在讲这条规矩 "免费托管方案.md", # 讲托管方案,不涉及 } # 官网源码里这些词也不许有(landing.py 渲染出来的页面) SITE_FILES = [ "relay/landing.py", "relay/showcase.py", ] passed = 0 failed = 0 def check(name: str, ok: bool, detail: str = "") -> None: global passed, failed if ok: passed += 1 print(" [PASS] " + name) else: failed += 1 print(" [FAIL] " + name + " " + str(detail)) def scan(path: Path) -> list: """返回 [(行号, 关键词, 那一行)]""" hits = [] try: text = path.read_text(encoding="utf-8", errors="replace") except OSError: return hits for index, line in enumerate(text.splitlines(), 1): for word in FORBIDDEN: if word in line: hits.append((index, word, line.strip()[:70])) return hits def main() -> int: print(" 一、对外公开的单文件") for rel in PUBLIC_FILES: path = ROOT / rel if not path.is_file(): check("%s 存在" % rel, False, "文件不存在") continue hits = scan(path) check("%s 干净" % rel, not hits, "第 %d 行含「%s」" % (hits[0][0], hits[0][1]) if hits else "") print() print(" 二、docs 目录(运维文档除外)") for rel in PUBLIC_DIRS: directory = ROOT / rel if not directory.is_dir(): continue for path in sorted(directory.iterdir()): if not path.is_file(): continue if path.name in DOCS_ALLOWLIST: print(" [跳过] %s(运维文档,允许提及)" % path.name) continue hits = scan(path) check("docs/%s 干净" % path.name, not hits, "第 %d 行含「%s」" % (hits[0][0], hits[0][1]) if hits else "") print() print(" 三、官网页面(渲染出来给所有人看的)") sys.path.insert(0, str(ROOT / "relay")) try: import landing html = landing.render_site([ {"name": "ykxmz-setup-1.8.0.exe", "size": 15066550}, {"name": "ykxmz-server-1.8.0.zip", "size": 214661}, {"name": "ykxmz-watch-1.8.0.apk", "size": 201523}, ]) except Exception as exc: # noqa: BLE001 check("官网能渲染", False, exc) html = "" if html: check("官网能渲染", len(html) > 5000, "%d 字符" % len(html)) for word in FORBIDDEN: check("官网里没有「%s」" % word, word not in html.lower() if word.isascii() else word not in html) # 只允许链接到下载 / 截图 / 首页 / 图标 / 页内锚点。 # 出现别的站内路径就说明可能把管理入口又加回去了。 allowed = ("/download/", "/shot/", "/", "/favicon.ico", "#") hrefs = set(re.findall(r'href="([^"]+)"', html)) bad = [h for h in hrefs if h.startswith("/") and not h.startswith(allowed)] check("官网里的站内链接只指向下载/首页/锚点", not bad, bad) print() print(" 四、发布说明只能是「更新内容」") rel_notes = ROOT / "_build" / "RELEASE-1.8.0.md" if rel_notes.is_file(): text = rel_notes.read_text(encoding="utf-8") # 不该出现安装教程这种内容(用户要求"只放更新内容") for bad_title in ("安装教程", "安装步骤", "怎么安装"): check("发布说明里没有「%s」" % bad_title, bad_title not in text) # 也不该提管理页 hits = scan(rel_notes) check("RELEASE-1.8.0.md 干净", not hits, "第 %d 行含「%s」" % (hits[0][0], hits[0][1]) if hits else "") else: print(" [跳过] 没有 RELEASE-1.8.0.md") print() print("=" * 54) print(" 通过 %d 项,失败 %d 项" % (passed, failed)) return 0 if failed == 0 else 1 if __name__ == "__main__": sys.exit(main())