fix(gateway): allow [[as_document]] glued directly to MEDIA path (#63632)

MEDIA_TAG_CLEANUP_RE failed to match when a directive like [[as_document]]
was concatenated directly to the file extension without whitespace
(e.g., MEDIA:/home/user/report.xlsx[[as_document]]). This caused the
file to be silently not delivered while the gateway reported success.

Root cause: the lookahead character class [\s`",;:)\}\]|$) did not
include [, so [[as_document]] immediately after the extension broke
the lookahead assertion.

Fix: add \[ to the lookahead class so directives can follow the path
without whitespace. This is safe because [ is already stripped elsewhere
in the same file via .replace("[[as_document]]", "").

Added regression tests covering:
- Directive glued to extension (issue case)
- Directive with whitespace (baseline)
- Tag at end of string ($ anchor)
This commit is contained in:
liuhao1024 2026-07-13 15:04:33 +08:00 committed by Teknium
parent 41f2196c53
commit b58b1fa962
2 changed files with 62 additions and 1 deletions

View file

@ -1514,7 +1514,7 @@ MEDIA_TAG_CLEANUP_RE = re.compile(
r'''[`"']?MEDIA:\s*'''
r'''(?P<path>`[^`\n]+`|"[^"\n]+"|'[^'\n]+'|'''
r'''(?:~/|/|[A-Za-z]:[/\\])\S+(?:[^\S\n]+\S+)*?\.(?:''' + _MEDIA_EXT_ALTERNATION + r'''))'''
r'''(?=[\s`"',;:)\]}]|$)[`"']?''',
r'''(?=[\s`"',;:)\]}\[]|$)[`"']?''',
re.IGNORECASE,
)

View file

@ -0,0 +1,61 @@
"""Tests for MEDIA_TAG_CLEANUP_RE regex matching behavior (#63632)."""
class TestMediaTagCleanup:
"""Tests for MEDIA_TAG_CLEANUP_RE regex matching behavior."""
def test_media_tag_with_directive_glued_to_extension(self):
"""Regression: MEDIA:<path>[[as_document]] must match when directive is glued
directly to the extension without whitespace (#63632).
The fix adds `\\[` to the lookahead character class in MEDIA_TAG_CLEANUP_RE.
"""
from gateway.platforms.base import MEDIA_TAG_CLEANUP_RE
# Issue case: [[as_document]] glued directly to .xlsx
text = "Готово. MEDIA:/home/hermes/report.xlsx[[as_document]]"
assert MEDIA_TAG_CLEANUP_RE.search(text) is not None
stripped = MEDIA_TAG_CLEANUP_RE.sub("", text)
assert "MEDIA:" not in stripped
assert "/home/hermes/report.xlsx" not in stripped
# Same with whitespace (should still work)
text_with_space = "Готово. MEDIA:/home/hermes/report.xlsx [[as_document]]"
assert MEDIA_TAG_CLEANUP_RE.search(text_with_space) is not None
stripped = MEDIA_TAG_CLEANUP_RE.sub("", text_with_space)
assert "MEDIA:" not in stripped
assert "/home/hermes/report.xlsx" not in stripped
# Other directives ([[as_image]]) should also work
text_image = "Done. MEDIA:/tmp/chart.png[[as_image]]"
assert MEDIA_TAG_CLEANUP_RE.search(text_image) is not None
stripped = MEDIA_TAG_CLEANUP_RE.sub("", text_image)
assert "MEDIA:" not in stripped
assert "/tmp/chart.png" not in stripped
def test_media_tag_with_whitespace_still_works(self):
"""Baseline: MEDIA tags with whitespace before/after still match."""
from gateway.platforms.base import MEDIA_TAG_CLEANUP_RE
# Space before closing quote
text = "Here is your report: MEDIA:/tmp/report.md "
stripped = MEDIA_TAG_CLEANUP_RE.sub("", text).strip()
assert "MEDIA:" not in stripped
assert "/tmp/report.md" not in stripped
# Multiple spaces (regex removes tag but preserves surrounding whitespace)
text = "Report at MEDIA:/tmp/data.pdf done"
stripped = MEDIA_TAG_CLEANUP_RE.sub("", text)
assert "MEDIA:" not in stripped
assert "/tmp/data.pdf" not in stripped
assert "Report at" in stripped and "done" in stripped
def test_media_tag_at_end_of_string(self):
"""MEDIA tags at the end of a string should match ($ anchor)."""
from gateway.platforms.base import MEDIA_TAG_CLEANUP_RE
text = "Here is the file: MEDIA:/tmp/file.docx"
stripped = MEDIA_TAG_CLEANUP_RE.sub("", text).strip()
assert "MEDIA:" not in stripped
assert "/tmp/file.docx" not in stripped
assert "Here is the file:" in stripped