Add /spoiler and /unspoiler
This commit is contained in:
parent
022df56c9e
commit
160670bea3
|
@ -138,6 +138,13 @@ 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*)")
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,6 +231,7 @@ class HTMLProcessor:
|
||||||
# Client-side modifications
|
# Client-side modifications
|
||||||
|
|
||||||
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
|
||||||
|
@ -250,11 +258,11 @@ class HTMLProcessor:
|
||||||
"font": {"color"},
|
"font": {"color"},
|
||||||
"a": {"href", "class", "data-mention"},
|
"a": {"href", "class", "data-mention"},
|
||||||
"code": {"class"},
|
"code": {"class"},
|
||||||
|
"span": {"data-mx-spoiler", "data-mx-color"},
|
||||||
}
|
}
|
||||||
attributes = {**inlines_attributes, **{
|
attributes = {**inlines_attributes, **{
|
||||||
"ol": {"start"},
|
"ol": {"start"},
|
||||||
"hr": {"width"},
|
"hr": {"width"},
|
||||||
"span": {"data-mx-color"},
|
|
||||||
"img": {
|
"img": {
|
||||||
"data-mx-emote", "src", "alt", "title", "width", "height",
|
"data-mx-emote", "src", "alt", "title", "width", "height",
|
||||||
},
|
},
|
||||||
|
|
|
@ -183,6 +183,8 @@ class MatrixClient(nio.AsyncClient):
|
||||||
self.cmd_handler_map = {
|
self.cmd_handler_map = {
|
||||||
"me ": MatrixClient.handle_cmd_emote,
|
"me ": MatrixClient.handle_cmd_emote,
|
||||||
"react ": MatrixClient.handle_cmd_react,
|
"react ": MatrixClient.handle_cmd_react,
|
||||||
|
"spoiler ": MatrixClient.handle_cmd_spoiler,
|
||||||
|
"unspoiler": MatrixClient.handle_cmd_unspoiler,
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -655,6 +657,8 @@ class MatrixClient(nio.AsyncClient):
|
||||||
text: str,
|
text: str,
|
||||||
display_name_mentions: Optional[Dict[str, str]] = None, # {id: name}
|
display_name_mentions: Optional[Dict[str, str]] = None, # {id: name}
|
||||||
reply_to_event_id: Optional[str] = None,
|
reply_to_event_id: Optional[str] = None,
|
||||||
|
override_to_html: Optional[str] = None,
|
||||||
|
override_echo_body: Optional[str] = None,
|
||||||
emote: bool = False,
|
emote: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Send a markdown `m.text` or `m.emote` message ."""
|
"""Send a markdown `m.text` or `m.emote` message ."""
|
||||||
|
@ -676,6 +680,12 @@ 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)
|
||||||
|
|
||||||
|
# override_echo_body will not be effective if it is a reply.
|
||||||
|
# echo_body is only shown before the event is received back from the
|
||||||
|
# server, so this is fine if not ideal
|
||||||
|
to_html = override_to_html or to_html
|
||||||
|
echo_body = override_echo_body or echo_body
|
||||||
|
|
||||||
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"
|
||||||
content["formatted_body"] = to_html
|
content["formatted_body"] = to_html
|
||||||
|
@ -762,6 +772,56 @@ class MatrixClient(nio.AsyncClient):
|
||||||
await self.send_reaction(room_id, reaction, reply_to_event_id)
|
await self.send_reaction(room_id, reaction, reply_to_event_id)
|
||||||
|
|
||||||
|
|
||||||
|
async def handle_cmd_spoiler(
|
||||||
|
self,
|
||||||
|
room_id: str,
|
||||||
|
text: str,
|
||||||
|
display_name_mentions: Optional[Dict[str, str]] = None, # {id: name}
|
||||||
|
reply_to_event_id: Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
from_md = partial(
|
||||||
|
HTML.from_markdown, display_name_mentions=display_name_mentions,
|
||||||
|
)
|
||||||
|
|
||||||
|
to_html = from_md(text, outgoing=True)
|
||||||
|
echo_body = from_md(text)
|
||||||
|
|
||||||
|
to_html = f"<span data-mx-spoiler>{to_html}</span>"
|
||||||
|
echo_body = f"<span data-mx-spoiler>{echo_body}</span>"
|
||||||
|
|
||||||
|
|
||||||
|
await self._send_text(
|
||||||
|
room_id,
|
||||||
|
text,
|
||||||
|
display_name_mentions,
|
||||||
|
reply_to_event_id,
|
||||||
|
override_to_html = to_html,
|
||||||
|
override_echo_body = echo_body,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def handle_cmd_unspoiler(
|
||||||
|
self,
|
||||||
|
room_id: str,
|
||||||
|
text: str,
|
||||||
|
display_name_mentions: Optional[Dict[str, str]] = None, # {id: name}
|
||||||
|
reply_to_event_id: Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
|
if reply_to_event_id is None or reply_to_event_id == '':
|
||||||
|
await self.send_fake_notice(room_id, "Please reply to a message with /unspoiler to unspoiler it 🙃")
|
||||||
|
else:
|
||||||
|
spoiler_event: Event = \
|
||||||
|
self.models[self.user_id, room_id, "events"][reply_to_event_id]
|
||||||
|
|
||||||
|
# get formatted_body, fallback to body,
|
||||||
|
spoiler = getattr(spoiler_event.source, "formatted_body", None) or \
|
||||||
|
getattr(spoiler_event.source, "body", "")
|
||||||
|
|
||||||
|
unspoiler = re.sub(r'<span[^>]+data-mx-spoiler[^>]*>(.*?)</?span>', r'\1', spoiler)
|
||||||
|
await self.send_fake_notice(room_id, unspoiler)
|
||||||
|
|
||||||
|
|
||||||
async def send_reaction(
|
async def send_reaction(
|
||||||
self,
|
self,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user