markdown: Show inline video previews for dropbox videos.

Fixes https://chat.zulip.org/#narrow/channel/9-issues/topic/.F0.9F.93.82.20video.20preview.20not.20working.20.28Dropbox.29
This commit is contained in:
Shubham Padia 2025-06-26 14:18:18 +00:00 committed by Tim Abbott
parent 276bc7284f
commit d701fec37d
2 changed files with 43 additions and 6 deletions

View File

@ -611,6 +611,7 @@ IMAGE_EXTENSIONS = [".bmp", ".gif", ".jpe", ".jpeg", ".jpg", ".png", ".webp"]
class DropboxMediaInfo(TypedDict):
is_image: bool
is_video: bool
media_url: str
title: NotRequired[str]
desc: NotRequired[str]
@ -813,9 +814,14 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
return None
is_image = self.is_image(url)
# is_video function uses `mimetypes` library to determine
# file type. For that we have to get rid of any query params
# in the url before passing it to `is_video`.
is_video = self.is_video(urlsplit(url).path)
# If it is from an album or not an actual image file,
# just use open graph image.
if is_album or not is_image:
if is_album or not (is_image or is_video):
open_graph_image_info = fetch_open_graph_image(url)
# Failed to follow link to find an image preview so
# use placeholder image and guess filename
@ -833,6 +839,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
title=title,
desc=desc,
is_image=is_image,
is_video=is_video,
media_url=open_graph_image_info["image"],
)
@ -843,7 +850,9 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
query = urlencode(query_params)
return DropboxMediaInfo(
is_image=is_image, media_url=parsed_url._replace(query=query).geturl()
is_image=is_image,
is_video=is_video,
media_url=parsed_url._replace(query=query).geturl(),
)
return None
@ -1337,10 +1346,6 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
else:
continue
if self.is_video(url):
self.handle_video_inlining(root, found_url)
continue
dropbox_media = self.dropbox_media(url)
if dropbox_media is not None:
is_image = dropbox_media["is_image"]
@ -1352,6 +1357,15 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
self.handle_image_inlining(root, found_url)
continue
is_video = dropbox_media["is_video"]
if is_video:
found_url = ResultWithFamily(
family=found_url.family,
result=(dropbox_media["media_url"], dropbox_media["media_url"]),
)
self.handle_video_inlining(root, found_url)
continue
dropbox_embed_data = UrlEmbedData(
type="image",
title=dropbox_media["title"],
@ -1361,6 +1375,15 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
self.add_embed(root, url, dropbox_embed_data)
continue
# This needs to run after all the dropbox code has been run.
# `is_video` will return True for dropbox video, and if this is
# ran before the dropbox code, it will try to make the video
# preview work without making the relevant changes to the dropbox
# url.
if self.is_video(url):
self.handle_video_inlining(root, found_url)
continue
if self.is_image(url):
image_source = self.corrected_image_source(url)
if image_source is not None:

View File

@ -1086,6 +1086,20 @@ class MarkdownEmbedsTest(ZulipTestCase):
"""<p>Look at my hilarious drawing folder: <a href="https://www.dropbox.com/scl/fo/ty22bx4thyhl9r89p839g/AAzfPX5IbiOb8wmxHvns2pM?rlkey=5pinfuoghias9cueq0zyhj2rp&amp;st=dz5p1ytw">https://www.dropbox.com/scl/fo/ty22bx4thyhl9r89p839g/AAzfPX5IbiOb8wmxHvns2pM?rlkey=5pinfuoghias9cueq0zyhj2rp&amp;st=dz5p1ytw</a></p>\n<div class="message_embed"><a class="message_embed_image" href="https://www.dropbox.com/scl/fo/ty22bx4thyhl9r89p839g/AAzfPX5IbiOb8wmxHvns2pM?rlkey=5pinfuoghias9cueq0zyhj2rp&amp;st=dz5p1ytw" style="background-image: url(&quot;https://external-content.zulipcdn.net/external_content/a301902b9942efb85cfe2a6f4bb07d76ba7b86de/68747470733a2f2f7777772e64726f70626f782e636f6d2f7374617469632f6d6574617365727665722f7374617469632f696d616765732f6f70656e67726170682f6f70656e67726170682d636f6e74656e742d69636f6e2d666f6c6465722d64726f70626f782d6c616e6473636170652e706e67&quot;)"></a><div class="data-container"><div class="message_embed_title"><a href="https://www.dropbox.com/scl/fo/ty22bx4thyhl9r89p839g/AAzfPX5IbiOb8wmxHvns2pM?rlkey=5pinfuoghias9cueq0zyhj2rp&amp;st=dz5p1ytw" title="Dropbox folder">Dropbox folder</a></div><div class="message_embed_description">Click to open folder.</div></div></div>""", # codespell:ignore fo
)
def test_inline_dropbox_video(self) -> None:
msg = "Look at this video: https://www.dropbox.com/scl/fi/x8z01rodq1n6pgyznt1kh/SampleVideo_1280x720_1mb.mp4?rlkey=fiibsgnu06tms041vfzfopmos&st=kjtkea8h&dl=0"
image_info = {
"image": "https://www.dropbox.com/scl/fi/x8z01rodq1n6pgyznt1kh/SampleVideo_1280x720_1mb.mp4?rlkey=fiibsgnu06tms041vfzfopmos&st=kjtkea8h&dl=0&raw=1",
}
with mock.patch("zerver.lib.markdown.fetch_open_graph_image", return_value=image_info):
converted = markdown_convert_wrapper(msg)
self.assertEqual(
converted,
"""<p>Look at this video: <a href="https://www.dropbox.com/scl/fi/x8z01rodq1n6pgyznt1kh/SampleVideo_1280x720_1mb.mp4?rlkey=fiibsgnu06tms041vfzfopmos&amp;st=kjtkea8h&amp;dl=0">https://www.dropbox.com/scl/fi/x8z01rodq1n6pgyznt1kh/SampleVideo_1280x720_1mb.mp4?rlkey=fiibsgnu06tms041vfzfopmos&amp;st=kjtkea8h&amp;dl=0</a></p>
<div class="message_inline_image message_inline_video"><a href="https://www.dropbox.com/scl/fi/x8z01rodq1n6pgyznt1kh/SampleVideo_1280x720_1mb.mp4?rlkey=fiibsgnu06tms041vfzfopmos&amp;st=kjtkea8h&amp;dl=0&amp;raw=1"><video preload="metadata" src="https://external-content.zulipcdn.net/external_content/eca04355025c60f40334c9a03d220c3298d4df47/68747470733a2f2f7777772e64726f70626f782e636f6d2f73636c2f66692f78387a3031726f6471316e367067797a6e74316b682f53616d706c65566964656f5f31323830783732305f316d622e6d70343f726c6b65793d6669696273676e753036746d7330343176667a666f706d6f732673743d6b6a746b6561386826646c3d30267261773d31"></video></a></div>""",
)
def test_inline_dropbox_preview(self) -> None:
# Test photo album previews
msg = "https://www.dropbox.com/sc/tditp9nitko60n5/03rEiZldy5"