Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
42 lines
1.6 KiB
Python
42 lines
1.6 KiB
Python
import re
|
|
|
|
from bs4 import Tag
|
|
from typing_extensions import override
|
|
|
|
from zerver.lib.markdown import get_markdown_image_for_url
|
|
from zerver.lib.markdown.from_html import ZulipMarkdownConverter, convert_html_to_markdown
|
|
|
|
# https://learn.microsoft.com/en-us/graph/api/chatmessagehostedcontent-get
|
|
HOSTED_CONTENT_GRAPH_API_URL_REGEX = r"https://graph\.microsoft\.com/v1\.0/teams/[^/]+/channels/[^/]+/messages/[^/]+/hostedContents/[^/]+/\$value"
|
|
HOSTED_CONTENT_MARKDOWN_IMAGE_SYNTAX_REGEX = rf"""
|
|
!\[
|
|
(?P<file_name>[^\]]+)
|
|
\]\(
|
|
(?P<api_url>{HOSTED_CONTENT_GRAPH_API_URL_REGEX})
|
|
\)
|
|
"""
|
|
|
|
|
|
class MicrosoftTeamsToZulipMarkdownConverter(ZulipMarkdownConverter):
|
|
"""HTML-to-Markdown converter for Microsoft Teams exports.
|
|
|
|
Hosted-content images are kept in inline `` form, which
|
|
process_hosted_content_attachments matches to download each image
|
|
and rewrite it into a Zulip upload link. Other images get the base
|
|
class's external-link treatment.
|
|
"""
|
|
|
|
@override
|
|
def convert_img(self, el: Tag, text: str, parent_tags: set[str]) -> str:
|
|
src = el.get("src", "")
|
|
alt = el.get("alt", "")
|
|
assert isinstance(src, str)
|
|
assert isinstance(alt, str)
|
|
if re.fullmatch(HOSTED_CONTENT_GRAPH_API_URL_REGEX, src):
|
|
return get_markdown_image_for_url(alt, src)
|
|
return super().convert_img(el, text, parent_tags)
|
|
|
|
|
|
def convert_microsoft_teams_html_to_markdown(html: str) -> str:
|
|
return convert_html_to_markdown(html, converter_class=MicrosoftTeamsToZulipMarkdownConverter)
|