mirror of
https://github.com/zulip/zulip.git
synced 2025-11-04 14:03:30 +00:00
markdown: Change URL structure for dropbox preview to be up-to-date.
The URL structure for a shared link has changed since this function was returned and this commit makes sure our code is in compliance with that structure. The concept of an album doesn't exist anymore and folders exist in-lieu of that. For dropbox links that are folders on non-image files, we show previews same as any other link previews. It is not possible to get information about the shared link except whether it is a file or folder. So for title and description for that linked preview, we use `Dropbox file` or `Dropbox folder` respectively. Earlier, we were just having raw=1 as the query param to get the image file if required, but now for every dropbox sharing link, preserving query params is important (otherwise we get a 404), this commit makes changes to address that. For /sc/ links, it is not possible to generate them anymore (afaik), but it is possible to view those existing links, so we support that link but treat it as a folder instead. You can check https://www.dropboxforum.com/discussions/101001012/shared-link--scl-to-s/689070/replies/695266 for URL structure info. We have used inline ignore for codespell since fo can be a valid misspell of `of` and we don't want to ignore that. https://chat.zulip.org/#narrow/channel/9-issues/topic/.F0.9F.93.82.20message_inline_ref.20dropbox.20links Co-authored-by: Tim Abbott <tabbott@zulip.com>
This commit is contained in:
committed by
Tim Abbott
parent
22b5744726
commit
bace83ec5a
@@ -20,6 +20,14 @@ format used by the Zulip server that they are interacting with.
|
||||
|
||||
## Changes in Zulip 11.0
|
||||
|
||||
**Feature level 395**
|
||||
|
||||
* [Markdown message
|
||||
formatting](/api/message-formatting#removed-features): Previously,
|
||||
Zulip's Markdown syntax had special support for previewing Dropbox
|
||||
albums. Dropbox albums no longer exist, and links to Dropbox folders
|
||||
now consistently use Zulip's standard open graph preview markup.
|
||||
|
||||
**Feature level 394**
|
||||
|
||||
* [`POST /register`](/api/register-queue), [`GET
|
||||
|
||||
@@ -365,7 +365,33 @@ features.
|
||||
|
||||
## Removed features
|
||||
|
||||
**Changes**: In Zulip 4.0 (feature level 24), the rarely used `!avatar()`
|
||||
### Removed legacy Dropbox link preview markup
|
||||
|
||||
In Zulip 11.0 (feature level 395), the Zulip server stopped generating
|
||||
legacy Dropbox link previews. Dropbox links are now previewed just
|
||||
like standard Zulip image/link previews. However, some legacy Dropbox
|
||||
previews may exist in existing messages.
|
||||
|
||||
Clients are recommended to prune these previews from message HTML;
|
||||
since they always appear after the actual link, there is no loss of
|
||||
information/functionality. They can be recognized via the classes
|
||||
`message_inline_ref`, `message_inline_image_desc`, and
|
||||
`message_inline_image_title`:
|
||||
|
||||
``` html
|
||||
<div class="message_inline_ref">
|
||||
<a href="https://www.dropbox.com/sh/cm39k9e04z7fhim/AAAII5NK-9daee3FcF41anEua?dl=" title="Saves">
|
||||
<img src="/path/to/folder_dropbox.png">
|
||||
</a>
|
||||
<div><div class="message_inline_image_title">Saves</div>
|
||||
<desc class="message_inline_image_desc"></desc>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Removed legacy avatar markup
|
||||
|
||||
In Zulip 4.0 (feature level 24), the rarely used `!avatar()`
|
||||
and `!gravatar()` markup syntax, which was never documented and had an
|
||||
inconsistent syntax, were removed.
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
|
||||
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
||||
# entries in the endpoint's documentation in `zulip.yaml`.
|
||||
|
||||
API_FEATURE_LEVEL = 394
|
||||
API_FEATURE_LEVEL = 395
|
||||
|
||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
||||
# only when going from an old version of the code to a newer version. Bump
|
||||
|
||||
@@ -13,7 +13,7 @@ from email.message import EmailMessage
|
||||
from functools import lru_cache
|
||||
from re import Match, Pattern
|
||||
from typing import Any, Generic, Optional, TypeAlias, TypedDict, TypeVar, cast
|
||||
from urllib.parse import parse_qs, quote, urljoin, urlsplit, urlunsplit
|
||||
from urllib.parse import parse_qs, parse_qsl, quote, urlencode, urljoin, urlsplit, urlunsplit
|
||||
from xml.etree.ElementTree import Element, SubElement
|
||||
|
||||
import ahocorasick
|
||||
@@ -803,11 +803,15 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||
# TODO: The returned Dict could possibly be a TypedDict in future.
|
||||
parsed_url = urlsplit(url)
|
||||
if parsed_url.netloc == "dropbox.com" or parsed_url.netloc.endswith(".dropbox.com"):
|
||||
is_album = parsed_url.path.startswith("/sc/") or parsed_url.path.startswith("/photos/")
|
||||
# Only allow preview Dropbox shared links
|
||||
if not (
|
||||
parsed_url.path.startswith("/s/") or parsed_url.path.startswith("/sh/") or is_album
|
||||
):
|
||||
# See https://www.dropboxforum.com/discussions/101001012/shared-link--scl-to-s/689070/replies/695266
|
||||
# for more info on the URL structure mentioned here.
|
||||
# It is not possible to generate /sc/ links which is kind of a showcase
|
||||
# for multiple images. We treat it now as a folder instead.
|
||||
is_album = parsed_url.path.startswith(
|
||||
"/scl/fo/" # codespell:ignore fo
|
||||
) or parsed_url.path.startswith("/sc/")
|
||||
is_file = parsed_url.path.startswith("/scl/fi/")
|
||||
if not (is_file or is_album):
|
||||
return None
|
||||
|
||||
# Try to retrieve open graph protocol info for a preview
|
||||
@@ -817,7 +821,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||
# want to use the open graph image.
|
||||
image_info = fetch_open_graph_image(url)
|
||||
|
||||
is_image = is_album or self.is_image(url)
|
||||
is_image = self.is_image(url)
|
||||
|
||||
# If it is from an album or not an actual image file,
|
||||
# just use open graph image.
|
||||
@@ -827,17 +831,31 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||
if image_info is None:
|
||||
return None
|
||||
|
||||
if is_album:
|
||||
image_info["title"] = "Dropbox folder"
|
||||
image_info["desc"] = "Click to open folder."
|
||||
else:
|
||||
image_info["title"] = "Dropbox file"
|
||||
image_info["desc"] = "Click to open file."
|
||||
|
||||
image_info["is_image"] = is_image
|
||||
return image_info
|
||||
|
||||
# Otherwise, try to retrieve the actual image.
|
||||
# Try to retrieve the actual image.
|
||||
# This is because open graph image from Dropbox may have padding
|
||||
# and gifs do not work.
|
||||
# TODO: What if image is huge? Should we get headers first?
|
||||
if image_info is None:
|
||||
image_info = {}
|
||||
image_info["is_image"] = True
|
||||
image_info["image"] = parsed_url._replace(query="raw=1").geturl()
|
||||
|
||||
# Adding raw=1 as query param will give us the URL of the
|
||||
# actual image instead of the dropbox image preview page.
|
||||
query_params = dict(parse_qsl(parsed_url.query))
|
||||
query_params["raw"] = "1"
|
||||
query = urlencode(query_params)
|
||||
|
||||
image_info["image"] = parsed_url._replace(query=query).geturl()
|
||||
|
||||
return image_info
|
||||
return None
|
||||
@@ -1339,20 +1357,22 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||
|
||||
dropbox_image = self.dropbox_image(url)
|
||||
if dropbox_image is not None:
|
||||
class_attr = "message_inline_ref"
|
||||
is_image = dropbox_image["is_image"]
|
||||
if is_image:
|
||||
class_attr = "message_inline_image"
|
||||
# Not making use of title and description of images
|
||||
self.add_a(
|
||||
root,
|
||||
image_url=dropbox_image["image"],
|
||||
link=url,
|
||||
title=dropbox_image.get("title"),
|
||||
desc=dropbox_image.get("desc", ""),
|
||||
class_attr=class_attr,
|
||||
already_thumbnailed=True,
|
||||
found_url = ResultWithFamily(
|
||||
family=found_url.family,
|
||||
result=(dropbox_image["image"], dropbox_image["image"]),
|
||||
)
|
||||
self.handle_image_inlining(root, found_url)
|
||||
continue
|
||||
|
||||
dropbox_embed_data = UrlEmbedData(
|
||||
type="image",
|
||||
title=dropbox_image["title"],
|
||||
description=dropbox_image["desc"],
|
||||
image=dropbox_image["image"],
|
||||
)
|
||||
self.add_embed(root, url, dropbox_embed_data)
|
||||
continue
|
||||
|
||||
if self.is_image(url):
|
||||
|
||||
@@ -1062,32 +1062,28 @@ class MarkdownEmbedsTest(ZulipTestCase):
|
||||
self.assertFalse(url_embed_preview_enabled(message, no_previews=True))
|
||||
|
||||
def test_inline_dropbox(self) -> None:
|
||||
msg = "Look at how hilarious our old office was: https://www.dropbox.com/s/ymdijjcg67hv2ta/IMG_0923.JPG"
|
||||
msg = "Look at how hilarious our old office was: https://www.dropbox.com/scl/fi/cbabl5ryv1veky9ehs603/IMG_0923.JPG?rlkey=24sfgf0k0dneebzf5tfccldg0"
|
||||
image_info = {
|
||||
"image": "https://photos-4.dropbox.com/t/2/AABIre1oReJgPYuc_53iv0IHq1vUzRaDg2rrCfTpiWMccQ/12/129/jpeg/1024x1024/2/_/0/4/IMG_0923.JPG/CIEBIAEgAiAHKAIoBw/ymdijjcg67hv2ta/AABz2uuED1ox3vpWWvMpBxu6a/IMG_0923.JPG",
|
||||
"desc": "Shared with Dropbox",
|
||||
"title": "IMG_0923.JPG",
|
||||
"image": "https://www.dropbox.com/scl/fi/cbabl5ryv1veky9ehs603/IMG_0923.JPG?rlkey=24sfgf0k0dneebzf5tfccldg0&raw=1",
|
||||
}
|
||||
with mock.patch("zerver.lib.markdown.fetch_open_graph_image", return_value=image_info):
|
||||
converted = markdown_convert_wrapper(msg)
|
||||
|
||||
self.assertEqual(
|
||||
converted,
|
||||
f"""<p>Look at how hilarious our old office was: <a href="https://www.dropbox.com/s/ymdijjcg67hv2ta/IMG_0923.JPG">https://www.dropbox.com/s/ymdijjcg67hv2ta/IMG_0923.JPG</a></p>\n<div class="message_inline_image"><a href="https://www.dropbox.com/s/ymdijjcg67hv2ta/IMG_0923.JPG" title="IMG_0923.JPG"><img src="{get_camo_url("https://www.dropbox.com/s/ymdijjcg67hv2ta/IMG_0923.JPG?raw=1")}"></a></div>""",
|
||||
f"""<p>Look at how hilarious our old office was: <a href="https://www.dropbox.com/scl/fi/cbabl5ryv1veky9ehs603/IMG_0923.JPG?rlkey=24sfgf0k0dneebzf5tfccldg0">https://www.dropbox.com/scl/fi/cbabl5ryv1veky9ehs603/IMG_0923.JPG?rlkey=24sfgf0k0dneebzf5tfccldg0</a></p>\n<div class="message_inline_image"><a href="https://www.dropbox.com/scl/fi/cbabl5ryv1veky9ehs603/IMG_0923.JPG?rlkey=24sfgf0k0dneebzf5tfccldg0&raw=1"><img src="{get_camo_url("https://www.dropbox.com/scl/fi/cbabl5ryv1veky9ehs603/IMG_0923.JPG?rlkey=24sfgf0k0dneebzf5tfccldg0&raw=1")}"></a></div>""",
|
||||
)
|
||||
|
||||
msg = "Look at my hilarious drawing folder: https://www.dropbox.com/sh/cm39k9e04z7fhim/AAAII5NK-9daee3FcF41anEua?dl="
|
||||
msg = "Look at my hilarious drawing folder: https://www.dropbox.com/scl/fo/ty22bx4thyhl9r89p839g/AAzfPX5IbiOb8wmxHvns2pM?rlkey=5pinfuoghias9cueq0zyhj2rp&st=dz5p1ytw" # codespell:ignore fo
|
||||
image_info = {
|
||||
"image": "https://cf.dropboxstatic.com/static/images/icons128/folder_dropbox.png",
|
||||
"desc": "Shared with Dropbox",
|
||||
"title": "Saves",
|
||||
"image": "https://www.dropbox.com/static/metaserver/static/images/opengraph/opengraph-content-icon-folder-dropbox-landscape.png",
|
||||
}
|
||||
with mock.patch("zerver.lib.markdown.fetch_open_graph_image", return_value=image_info):
|
||||
converted = markdown_convert_wrapper(msg)
|
||||
|
||||
self.assertEqual(
|
||||
converted,
|
||||
f"""<p>Look at my hilarious drawing folder: <a href="https://www.dropbox.com/sh/cm39k9e04z7fhim/AAAII5NK-9daee3FcF41anEua?dl=">https://www.dropbox.com/sh/cm39k9e04z7fhim/AAAII5NK-9daee3FcF41anEua?dl=</a></p>\n<div class="message_inline_ref"><a href="https://www.dropbox.com/sh/cm39k9e04z7fhim/AAAII5NK-9daee3FcF41anEua?dl=" title="Saves"><img src="{get_camo_url("https://cf.dropboxstatic.com/static/images/icons128/folder_dropbox.png")}"></a><div><div class="message_inline_image_title">Saves</div><desc class="message_inline_image_desc"></desc></div></div>""",
|
||||
"""<p>Look at my hilarious drawing folder: <a href="https://www.dropbox.com/scl/fo/ty22bx4thyhl9r89p839g/AAzfPX5IbiOb8wmxHvns2pM?rlkey=5pinfuoghias9cueq0zyhj2rp&st=dz5p1ytw">https://www.dropbox.com/scl/fo/ty22bx4thyhl9r89p839g/AAzfPX5IbiOb8wmxHvns2pM?rlkey=5pinfuoghias9cueq0zyhj2rp&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&st=dz5p1ytw" style="background-image: url("https://external-content.zulipcdn.net/external_content/a301902b9942efb85cfe2a6f4bb07d76ba7b86de/68747470733a2f2f7777772e64726f70626f782e636f6d2f7374617469632f6d6574617365727665722f7374617469632f696d616765732f6f70656e67726170682f6f70656e67726170682d636f6e74656e742d69636f6e2d666f6c6465722d64726f70626f782d6c616e6473636170652e706e67")"></a><div class="data-container"><div class="message_embed_title"><a href="https://www.dropbox.com/scl/fo/ty22bx4thyhl9r89p839g/AAzfPX5IbiOb8wmxHvns2pM?rlkey=5pinfuoghias9cueq0zyhj2rp&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_preview(self) -> None:
|
||||
@@ -1095,15 +1091,14 @@ class MarkdownEmbedsTest(ZulipTestCase):
|
||||
msg = "https://www.dropbox.com/sc/tditp9nitko60n5/03rEiZldy5"
|
||||
image_info = {
|
||||
"image": "https://photos-6.dropbox.com/t/2/AAAlawaeD61TyNewO5vVi-DGf2ZeuayfyHFdNTNzpGq-QA/12/271544745/jpeg/1024x1024/2/_/0/5/baby-piglet.jpg/CKnjvYEBIAIgBygCKAc/tditp9nitko60n5/AADX03VAIrQlTl28CtujDcMla/0",
|
||||
"desc": "Shared with Dropbox",
|
||||
"title": "1 photo",
|
||||
}
|
||||
with mock.patch("zerver.lib.markdown.fetch_open_graph_image", return_value=image_info):
|
||||
converted = markdown_convert_wrapper(msg)
|
||||
|
||||
self.assertEqual(
|
||||
converted,
|
||||
f"""<p><a href="https://www.dropbox.com/sc/tditp9nitko60n5/03rEiZldy5">https://www.dropbox.com/sc/tditp9nitko60n5/03rEiZldy5</a></p>\n<div class="message_inline_image"><a href="https://www.dropbox.com/sc/tditp9nitko60n5/03rEiZldy5" title="1 photo"><img src="{get_camo_url("https://photos-6.dropbox.com/t/2/AAAlawaeD61TyNewO5vVi-DGf2ZeuayfyHFdNTNzpGq-QA/12/271544745/jpeg/1024x1024/2/_/0/5/baby-piglet.jpg/CKnjvYEBIAIgBygCKAc/tditp9nitko60n5/AADX03VAIrQlTl28CtujDcMla/0")}"></a></div>""",
|
||||
"""<p><a href="https://www.dropbox.com/sc/tditp9nitko60n5/03rEiZldy5">https://www.dropbox.com/sc/tditp9nitko60n5/03rEiZldy5</a></p>
|
||||
<div class="message_embed"><a class="message_embed_image" href="https://www.dropbox.com/sc/tditp9nitko60n5/03rEiZldy5" style="background-image: url("https://external-content.zulipcdn.net/external_content/e7584a56d9ba7f2a2aee96ee1427a6b746eab5ff/68747470733a2f2f70686f746f732d362e64726f70626f782e636f6d2f742f322f4141416c6177616544363154794e65774f357656692d444766325a6575617966794846644e544e7a7047712d51412f31322f3237313534343734352f6a7065672f3130323478313032342f322f5f2f302f352f626162792d7069676c65742e6a70672f434b6e6a7659454249414967427967434b41632f7464697470396e69746b6f36306e352f41414458303356414972516c546c32384374756a44634d6c612f30")"></a><div class="data-container"><div class="message_embed_title"><a href="https://www.dropbox.com/sc/tditp9nitko60n5/03rEiZldy5" title="Dropbox folder">Dropbox folder</a></div><div class="message_embed_description">Click to open folder.</div></div></div>""",
|
||||
)
|
||||
|
||||
def test_inline_dropbox_negative(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user