Linkify typed usernames/id in markdown

This commit is contained in:
miruka 2020-03-22 16:21:29 -04:00
parent 728c47f159
commit f858e505a6
2 changed files with 36 additions and 5 deletions

View File

@ -3,6 +3,8 @@
"""HTML and Markdown processing tools.""" """HTML and Markdown processing tools."""
import re import re
from typing import Dict, Optional
from urllib.parse import quote
import html_sanitizer.sanitizer as sanitizer import html_sanitizer.sanitizer as sanitizer
import mistune import mistune
@ -162,13 +164,33 @@ class HTMLProcessor:
def from_markdown( def from_markdown(
self, text: str, inline: bool = False, outgoing: bool = False, self,
text: str,
inline: bool = False,
outgoing: bool = False,
mentionable_users: Optional[Dict[str, str]] = None,
) -> str: ) -> str:
"""Return filtered HTML from Markdown text.""" """Return filtered HTML from Markdown text."""
if mentionable_users:
text = self.markdown_linkify_users(text, mentionable_users)
return self.filter(self._markdown_to_html(text), inline, outgoing) return self.filter(self._markdown_to_html(text), inline, outgoing)
def markdown_linkify_users(self, text: str, users: Dict[str, str]) -> str:
print(text)
for user_id, username in users.items():
repl = rf"\1[{user_id}](https://matrix.to/#/{quote(user_id)})\2"
text = re.sub(rf"(^|\W){user_id}($|\W)", repl, text)
repl = rf"\1[{username}](https://matrix.to/#/{quote(user_id)})\2"
text = re.sub(rf"(^|\W){username}($|\W)", repl, text)
return text
def filter( def filter(
self, html: str, inline: bool = False, outgoing: bool = False, self, html: str, inline: bool = False, outgoing: bool = False,
) -> str: ) -> str:

View File

@ -308,6 +308,15 @@ class MatrixClient(nio.AsyncClient):
async def send_text(self, room_id: str, text: str) -> None: async def send_text(self, room_id: str, text: str) -> None:
"""Send a markdown `m.text` or `m.notice` (with `/me`) message .""" """Send a markdown `m.text` or `m.notice` (with `/me`) message ."""
from_md = partial(
HTML.from_markdown,
mentionable_users={
user_id: member.display_name or user_id
for user_id, member in
self.models[self.user_id, room_id, "members"].items()
},
)
escape = False escape = False
if text.startswith("//") or text.startswith(r"\/"): if text.startswith("//") or text.startswith(r"\/"):
escape = True escape = True
@ -317,13 +326,13 @@ class MatrixClient(nio.AsyncClient):
event_type = nio.RoomMessageEmote event_type = nio.RoomMessageEmote
text = text[len("/me "): ] text = text[len("/me "): ]
content = {"body": text, "msgtype": "m.emote"} content = {"body": text, "msgtype": "m.emote"}
to_html = HTML.from_markdown(text, inline=True, outgoing=True) to_html = from_md(text, inline=True, outgoing=True)
echo_body = HTML.from_markdown(text, inline=True) echo_body = from_md(text, inline=True)
else: else:
event_type = nio.RoomMessageText event_type = nio.RoomMessageText
content = {"body": text, "msgtype": "m.text"} content = {"body": text, "msgtype": "m.text"}
to_html = HTML.from_markdown(text, outgoing=True) to_html = from_md(text, outgoing=True)
echo_body = HTML.from_markdown(text) echo_body = from_md(text)
if to_html not in (html.escape(text), f"<p>{html.escape(text)}</p>"): if to_html not in (html.escape(text), f"<p>{html.escape(text)}</p>"):
content["format"] = "org.matrix.custom.html" content["format"] = "org.matrix.custom.html"