822896ea6c
DingTalk exports empty online documents to valid but contentless docx/xlsx; WeKnora then rejects them with a generic remote_parse_failed. Detect blank exports (no text, no embedded media) at fetch time and report the cause in Chinese, and add the matching dead-letter hint.
69 lines
2.6 KiB
Python
69 lines
2.6 KiB
Python
import io
|
|
import pathlib
|
|
import tempfile
|
|
import unittest
|
|
import zipfile
|
|
|
|
MODULE_PATH = pathlib.Path(__file__).with_name("artifact_fetch.py")
|
|
import importlib.util
|
|
spec = importlib.util.spec_from_file_location("artifact_fetch", MODULE_PATH)
|
|
assert spec is not None and spec.loader is not None
|
|
artifact_fetch = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(artifact_fetch)
|
|
|
|
|
|
def make_docx(document_xml, media=None):
|
|
handle = tempfile.NamedTemporaryFile(suffix=".docx", delete=False)
|
|
with zipfile.ZipFile(handle, "w") as archive:
|
|
archive.writestr("word/document.xml", document_xml)
|
|
for name in media or []:
|
|
archive.writestr("word/media/" + name, b"\x89PNG fake")
|
|
return handle.name
|
|
|
|
|
|
class ExportedBlankDocTest(unittest.TestCase):
|
|
def test_empty_body_docx_is_flagged_blank(self):
|
|
# What DingTalk produces for an empty online document: valid zip,
|
|
# document.xml with no text nodes.
|
|
path = make_docx('<?xml version="1.0"?><w:document><w:body><w:p/></w:body></w:document>')
|
|
try:
|
|
self.assertTrue(artifact_fetch.exported_doc_is_blank(path, False))
|
|
finally:
|
|
pathlib.Path(path).unlink()
|
|
|
|
def test_text_docx_is_not_blank(self):
|
|
path = make_docx("<w:document><w:t>开箱步骤</w:t></w:document>")
|
|
try:
|
|
self.assertFalse(artifact_fetch.exported_doc_is_blank(path, False))
|
|
finally:
|
|
pathlib.Path(path).unlink()
|
|
|
|
def test_image_only_docx_is_not_blank(self):
|
|
path = make_docx("<w:document><w:body><w:p/></w:body></w:document>", media=["image1.png"])
|
|
try:
|
|
self.assertFalse(artifact_fetch.exported_doc_is_blank(path, False))
|
|
finally:
|
|
pathlib.Path(path).unlink()
|
|
|
|
def test_spreadsheet_checks_shared_strings(self):
|
|
handle = tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False)
|
|
with zipfile.ZipFile(handle, "w") as archive:
|
|
archive.writestr("xl/sharedStrings.xml", "<sst><si><t>表头</t></si></sst>")
|
|
try:
|
|
self.assertFalse(artifact_fetch.exported_doc_is_blank(handle.name, True))
|
|
finally:
|
|
pathlib.Path(handle.name).unlink()
|
|
|
|
def test_unreadable_file_is_not_judged_blank(self):
|
|
handle = tempfile.NamedTemporaryFile(suffix=".docx", delete=False)
|
|
handle.write(b"not a zip at all")
|
|
handle.close()
|
|
try:
|
|
self.assertFalse(artifact_fetch.exported_doc_is_blank(handle.name, False))
|
|
finally:
|
|
pathlib.Path(handle.name).unlink()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|