Catch some reaction failure modes, make spoilers black bars
This commit is contained in:
parent
8eb1afb91c
commit
294bd887ba
|
@ -138,13 +138,6 @@ class HTMLProcessor:
|
||||||
re.MULTILINE,
|
re.MULTILINE,
|
||||||
)
|
)
|
||||||
|
|
||||||
spoiler_regex = re.compile(
|
|
||||||
r"(<span[^>]+data-mx-spoiler[^>]*>)"
|
|
||||||
r"(.*?)"
|
|
||||||
r"(</?span>)",
|
|
||||||
re.MULTILINE,
|
|
||||||
)
|
|
||||||
|
|
||||||
extra_newlines_regex = re.compile(r"\n(\n*)")
|
extra_newlines_regex = re.compile(r"\n(\n*)")
|
||||||
|
|
||||||
|
|
||||||
|
@ -230,9 +223,28 @@ class HTMLProcessor:
|
||||||
|
|
||||||
# Client-side modifications
|
# Client-side modifications
|
||||||
|
|
||||||
|
# re-parsing, will sanitize again but allowing style
|
||||||
|
tree = etree.fromstring(
|
||||||
|
html, parser=etree.HTMLParser(encoding="utf-8"),
|
||||||
|
)
|
||||||
|
|
||||||
|
for span_tag in tree.iterfind(".//span[@data-mx-spoiler]"):
|
||||||
|
# if there are sub-elements, their styles also need to be set or
|
||||||
|
# background-color doesn't seem to apply
|
||||||
|
for tag in span_tag.iter():
|
||||||
|
tag.set(
|
||||||
|
"style",
|
||||||
|
"color: black !important; background-color: black !important;"
|
||||||
|
+ (tag.get("style") or "")
|
||||||
|
)
|
||||||
|
|
||||||
|
html = etree.tostring(tree, encoding="utf-8", method="html").decode()
|
||||||
|
|
||||||
|
html = Sanitizer(self.sanitize_settings(
|
||||||
|
inline, outgoing, mentions, extra_attributes={"style"}
|
||||||
|
)).sanitize(html).rstrip("\n")
|
||||||
|
|
||||||
html = self.quote_regex.sub(r'\1<span class="quote">\2</span>\3', html)
|
html = self.quote_regex.sub(r'\1<span class="quote">\2</span>\3', html)
|
||||||
html = self.spoiler_regex.sub(
|
|
||||||
r'\1<font color="#00000000">\2</font>\3', html)
|
|
||||||
|
|
||||||
if not inline:
|
if not inline:
|
||||||
return html
|
return html
|
||||||
|
@ -247,6 +259,7 @@ class HTMLProcessor:
|
||||||
inline: bool = False,
|
inline: bool = False,
|
||||||
outgoing: bool = False,
|
outgoing: bool = False,
|
||||||
display_name_mentions: Optional[Dict[str, str]] = None,
|
display_name_mentions: Optional[Dict[str, str]] = None,
|
||||||
|
extra_attributes: set = set(),
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""Return an html_sanitizer configuration."""
|
"""Return an html_sanitizer configuration."""
|
||||||
|
|
||||||
|
@ -269,6 +282,11 @@ class HTMLProcessor:
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
for key in inlines_attributes:
|
||||||
|
inlines_attributes[key] |= extra_attributes
|
||||||
|
for key in attributes:
|
||||||
|
attributes[key] |= extra_attributes
|
||||||
|
|
||||||
username_link_regexes = [re.compile(r) for r in [
|
username_link_regexes = [re.compile(r) for r in [
|
||||||
rf"(?<!\w)(?P<body>{re.escape(name or user_id)})(?!\w)(?P<host>)"
|
rf"(?<!\w)(?P<body>{re.escape(name or user_id)})(?!\w)(?P<host>)"
|
||||||
for user_id, name in (display_name_mentions or {}).items()
|
for user_id, name in (display_name_mentions or {}).items()
|
||||||
|
|
|
@ -771,7 +771,7 @@ class MatrixClient(nio.AsyncClient):
|
||||||
) -> None:
|
) -> None:
|
||||||
if reply_to_event_id is None or reply_to_event_id == "":
|
if reply_to_event_id is None or reply_to_event_id == "":
|
||||||
await self.send_fake_notice(
|
await self.send_fake_notice(
|
||||||
room_id, "please reply to a message to react to it 🙃")
|
room_id, "Please reply to a message to react to it")
|
||||||
else:
|
else:
|
||||||
reaction = emoji.emojize(text, language="alias")
|
reaction = emoji.emojize(text, language="alias")
|
||||||
await self.send_reaction(room_id, reaction, reply_to_event_id)
|
await self.send_reaction(room_id, reaction, reply_to_event_id)
|
||||||
|
@ -792,9 +792,19 @@ class MatrixClient(nio.AsyncClient):
|
||||||
to_html = from_md(text, outgoing=True)
|
to_html = from_md(text, outgoing=True)
|
||||||
echo_body = from_md(text)
|
echo_body = from_md(text)
|
||||||
|
|
||||||
to_html = f"<span data-mx-spoiler>{to_html}</span>"
|
if to_html.startswith("<p>") and to_html.endswith("</p>"):
|
||||||
echo_body = f"<span data-mx-spoiler>{echo_body}</span>"
|
# we want to make sure the <span> is inside the <p>, otherwise the
|
||||||
|
# black bar will be too wide
|
||||||
|
inner_html = to_html[len('<p>'):-len('</p>')]
|
||||||
|
to_html = f"<p><span data-mx-spoiler>{inner_html}</span></p>"
|
||||||
|
else:
|
||||||
|
to_html = f"<span data-mx-spoiler>{to_html}</span>"
|
||||||
|
|
||||||
|
if echo_body.startswith("<p>") and echo_body.endswith("</p>"):
|
||||||
|
inner_html = echo_body[len('<p>'):-len('</p>')]
|
||||||
|
echo_body = f"<p><span data-mx-spoiler>{inner_html}</span></p>"
|
||||||
|
else:
|
||||||
|
echo_body = f"<span data-mx-spoiler>{echo_body}</span>"
|
||||||
|
|
||||||
await self._send_text(
|
await self._send_text(
|
||||||
room_id,
|
room_id,
|
||||||
|
@ -816,7 +826,7 @@ class MatrixClient(nio.AsyncClient):
|
||||||
if reply_to_event_id is None or reply_to_event_id == "":
|
if reply_to_event_id is None or reply_to_event_id == "":
|
||||||
await self.send_fake_notice(
|
await self.send_fake_notice(
|
||||||
room_id,
|
room_id,
|
||||||
"Please reply to a message with /unspoiler to unspoiler it 🙃",
|
"Please reply to a message with /unspoiler to unspoiler it",
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
spoiler_event: Event = \
|
spoiler_event: Event = \
|
||||||
|
@ -835,16 +845,31 @@ class MatrixClient(nio.AsyncClient):
|
||||||
|
|
||||||
async def send_reaction(
|
async def send_reaction(
|
||||||
self,
|
self,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
key: str,
|
key: str,
|
||||||
reacts_to: str,
|
reacts_to: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
# local event id in model isn't necessarily the actual event id
|
# local event id in model isn't necessarily the actual event id
|
||||||
reacts_to_event_id = self.models[
|
reacts_to_event = self.models[
|
||||||
self.user_id, room_id, "events"][reacts_to].event_id
|
self.user_id, room_id, "events"][reacts_to]
|
||||||
|
|
||||||
item_uuid = uuid4()
|
reacts_to_event_id = reacts_to_event.event_id
|
||||||
|
|
||||||
|
if self.user_id in reacts_to_event.reactions.get(key, {}).get('users', []):
|
||||||
|
await self.send_fake_notice(
|
||||||
|
room_id,
|
||||||
|
"Can't send the same reaction more than once",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
elif reacts_to_event_id.startswith("echo-"):
|
||||||
|
await self.send_fake_notice(
|
||||||
|
room_id,
|
||||||
|
"Can't react to that, it's not a real event",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
item_uuid = uuid4()
|
||||||
|
|
||||||
content: Dict[str, Any] = {
|
content: Dict[str, Any] = {
|
||||||
"m.relates_to": {
|
"m.relates_to": {
|
||||||
|
@ -858,8 +883,25 @@ class MatrixClient(nio.AsyncClient):
|
||||||
content[f"{__reverse_dns__}.transaction_id"] = str(tx_id)
|
content[f"{__reverse_dns__}.transaction_id"] = str(tx_id)
|
||||||
|
|
||||||
await self.pause_while_offline()
|
await self.pause_while_offline()
|
||||||
await self._send_message(
|
try:
|
||||||
room_id, content, item_uuid, message_type = "m.reaction")
|
await self._send_message(
|
||||||
|
room_id, content, item_uuid, message_type = "m.reaction")
|
||||||
|
except MatrixError as err:
|
||||||
|
if err.m_code == "M_DUPLICATE_ANNOTATION":
|
||||||
|
# potentially possible if the new reaction is
|
||||||
|
# sent before the existing reaction is loaded
|
||||||
|
await self.send_fake_notice(
|
||||||
|
room_id,
|
||||||
|
"Can't send the same reaction more than once",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
if err.m_code == "M_UNKNOWN":
|
||||||
|
await self.send_fake_notice(
|
||||||
|
room_id,
|
||||||
|
"Failed to send reaction. Has the event you are reacting to fully sent yet?",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise err
|
||||||
|
|
||||||
# only update the UI after the reaction is sent, to not be misleading
|
# only update the UI after the reaction is sent, to not be misleading
|
||||||
await self._register_reaction(
|
await self._register_reaction(
|
||||||
|
@ -1222,7 +1264,7 @@ class MatrixClient(nio.AsyncClient):
|
||||||
|
|
||||||
event = Event(
|
event = Event(
|
||||||
id = f"echo-{transaction_id}",
|
id = f"echo-{transaction_id}",
|
||||||
event_id = "",
|
event_id = f"echo-{transaction_id}" if fake_event else "",
|
||||||
event_type = event_type,
|
event_type = event_type,
|
||||||
date = datetime.now(),
|
date = datetime.now(),
|
||||||
sender_id = self.user_id,
|
sender_id = self.user_id,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user