大量修改二期功能清单内容

This commit is contained in:
Azmat@qq.com
2026-08-17 18:26:42 +08:00
parent 36e91aab3c
commit d1ecb52125
76 changed files with 4222 additions and 294 deletions
@@ -0,0 +1,77 @@
"""上传脚本取正文 —— 只认 docx / txt。
docx 用标准库拆(zip + xml),不引 python-docx:镜像少一个依赖,也避免它对损坏文件抛一堆内部异常。
段落 = <w:p>,文字 = 其中所有 <w:t> 拼接;<w:br>/<w:tab> 补空白,否则整段会粘成一坨。
"""
import re
import zipfile
from io import BytesIO
from xml.etree import ElementTree
W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
MAX_UPLOAD_BYTES = 5 * 1024 * 1024 # 脚本是纯文字,5MB 足够;更大的基本是误传
class ScriptFileError(ValueError):
"""取正文失败,message 直接给用户看(中文)。"""
def _docx_text(raw: bytes) -> str:
try:
with zipfile.ZipFile(BytesIO(raw)) as bundle:
document = bundle.read("word/document.xml")
except KeyError:
raise ScriptFileError("这个 docx 里没有正文,请确认文件没有损坏")
except zipfile.BadZipFile:
raise ScriptFileError("这个文件不是有效的 docx,请另存为 .docx 后重试")
try:
root = ElementTree.fromstring(document)
except ElementTree.ParseError:
raise ScriptFileError("docx 正文解析失败,请另存一份后重试")
paragraphs = []
for node in root.iter(f"{{{W_NS}}}p"):
pieces = []
for child in node.iter():
tag = child.tag
if tag == f"{{{W_NS}}}t":
pieces.append(child.text or "")
elif tag in (f"{{{W_NS}}}br", f"{{{W_NS}}}cr"):
pieces.append("\n")
elif tag == f"{{{W_NS}}}tab":
pieces.append("\t")
line = "".join(pieces).strip()
if line:
paragraphs.append(line)
return "\n".join(paragraphs)
def _txt_text(raw: bytes) -> str:
# 中文 txt 常见三种落盘编码;utf-8 失败再退 GBK 家族,最后一步忽略坏字节保底出文本。
for encoding in ("utf-8-sig", "utf-8", "gb18030"):
try:
return raw.decode(encoding)
except UnicodeDecodeError:
continue
return raw.decode("utf-8", errors="ignore")
def extract_script_text(upload) -> tuple[str, str]:
"""(文件名, 正文)。只收 docx / txt,其余一律拒绝。"""
name = getattr(upload, "name", "") or "script"
lowered = name.lower()
if not lowered.endswith((".docx", ".txt")):
raise ScriptFileError("只支持 docx 和 txt 两种脚本文件")
raw = upload.read()
if len(raw) > MAX_UPLOAD_BYTES:
raise ScriptFileError("脚本文件不能超过 5MB")
text = _docx_text(raw) if lowered.endswith(".docx") else _txt_text(raw)
# 统一换行 + 压掉连续空行,避免原稿的排版空白撑爆后面的提示词
text = re.sub(r"\n{3,}", "\n\n", text.replace("\r\n", "\n").replace("\r", "\n")).strip()
if not text:
raise ScriptFileError("没能从这个文件里读到文字,请换一份")
return name, text