diff --git a/mautrix_telegram/commands/handler.py b/mautrix_telegram/commands/handler.py
index e8e54c1f..5be4d4fd 100644
--- a/mautrix_telegram/commands/handler.py
+++ b/mautrix_telegram/commands/handler.py
@@ -15,7 +15,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
from typing import Awaitable, Callable, Dict, List, NamedTuple, Optional
-import markdown
+import commonmark
import logging
from telethon.errors import FloodWaitError
@@ -60,7 +60,8 @@ class CommandEvent:
message = message.replace("$cmdprefix", self.command_prefix)
html = None
if render_markdown:
- html = markdown.markdown(message, safe_mode="escape" if allow_html else False)
+ html = commonmark.commonmark(message if allow_html else
+ message.replace("<", "<").replace(">", ">"))
elif allow_html:
html = message
return self.az.intent.send_notice(self.room_id, message, html=html)
diff --git a/mautrix_telegram/commands/portal.py b/mautrix_telegram/commands/portal.py
index 5704f77c..43cdca76 100644
--- a/mautrix_telegram/commands/portal.py
+++ b/mautrix_telegram/commands/portal.py
@@ -393,7 +393,6 @@ async def upgrade(evt: CommandEvent) -> Dict:
return await evt.reply(e.args[0])
-
@command_handler(help_section=SECTION_PORTAL_MANAGEMENT,
help_text="View or change per-portal settings.",
help_args="<`help`|_subcommand_> [...]")
@@ -402,37 +401,43 @@ async def config(evt: CommandEvent) -> Dict:
portal = po.Portal.get_by_mxid(evt.room_id)
if not portal and cmd != "help":
return await evt.reply("This is not a portal room.")
- if cmd == "help":
- return await evt.reply("""`$cmdprefix config`:
-* `help` - View this help text.
-* `view` - View the current config data.
-* `defaults` - View the default config values.
-* `set` <_key_> <_value_> - Set a config value.
-* `unset` <_key_> - Remove a config value.
-* `add` <_key_> <_value_> - Add a value to an array.
-* `del` <_key_> <_value_> - Remove a value from an array.
+ if cmd not in ("view", "defaults", "set", "unset", "add", "del"):
+ return await evt.reply("""**Usage:** `$cmdprefix config [...]`. Subcommands:
+
+* **help** - View this help text.
+* **view** - View the current config data.
+* **defaults** - View the default config values.
+* **set** <_key_> <_value_> - Set a config value.
+* **unset** <_key_> - Remove a config value.
+* **add** <_key_> <_value_> - Add a value to an array.
+* **del** <_key_> <_value_> - Remove a value from an array.
""")
elif cmd == "view":
stream = StringIO()
yaml.dump(portal.local_config, stream)
- return await evt.reply(f"Room-specific config:\n```yaml\n{stream.getvalue()}\n```")
+ return await evt.reply(f"Room-specific config:\n\n```yaml\n{stream.getvalue()}\n```",
+ allow_html=True)
elif cmd == "defaults":
stream = StringIO()
yaml.dump({
"edits_as_replies": evt.config["bridge.edits_as_replies"],
- "bridge_notices": evt.config["bridge.bridge_notices"],
+ "bridge_notices": {
+ "default": evt.config["bridge.bridge_notices.default"],
+ "exceptions": evt.config["bridge.bridge_notices.exceptions"],
+ },
"bot_messages_as_notices": evt.config["bridge.bot_messages_as_notices"],
"inline_images": evt.config["bridge.inline_images"],
- "native_stickers": evt.config["native_stickers"],
- "message_formats": evt.config["message_formats"],
- "state_event_formats": evt.config["state_event_formats"],
+ "native_stickers": evt.config["bridge.native_stickers"],
+ "message_formats": evt.config["bridge.message_formats"],
+ "state_event_formats": evt.config["bridge.state_event_formats"],
}, stream)
- return await evt.reply(f"Bridge instance wide config:\n```yaml\n{stream.getvalue()}\n```")
+ return await evt.reply(f"Bridge instance wide config:\n\n```yaml\n{stream.getvalue()}```",
+ allow_html=True)
key = evt.args[1] if len(evt.args) > 1 else None
- value = yaml.load(evt.args[2:]) if len(evt.args) > 2 else None
+ value = yaml.load(" ".join(evt.args[2:])) if len(evt.args) > 2 else None
if cmd == "set":
- if not key or not value:
+ if not key or value is None:
return await evt.reply(f"**Usage:** `$cmdprefix+sp config {cmd} `")
elif util.recursive_set(portal.local_config, key, value):
return await evt.reply(f"Successfully set the value of `{key}` to `{value}`.")
@@ -447,7 +452,7 @@ async def config(evt: CommandEvent) -> Dict:
else:
return await evt.reply(f"`{key}` not found in config.")
elif cmd == "add" or cmd == "del":
- if not key or not value:
+ if not key or value is None:
return await evt.reply(f"**Usage:** `$cmdprefix+sp config {cmd} `")
arr = util.recursive_get(portal.local_config, key)
@@ -466,6 +471,7 @@ async def config(evt: CommandEvent) -> Dict:
return await evt.reply(f"The array at `{key}` does not contain `{value}`.")
arr.remove(value)
return await evt.reply(f"Successfully removed `{value}` from the array at `{key}`")
+ portal.save()
@command_handler(help_section=SECTION_PORTAL_MANAGEMENT,
diff --git a/mautrix_telegram/util/recursive_dict.py b/mautrix_telegram/util/recursive_dict.py
index fc9284b7..6f21a638 100644
--- a/mautrix_telegram/util/recursive_dict.py
+++ b/mautrix_telegram/util/recursive_dict.py
@@ -17,6 +17,7 @@
from typing import Dict, Any
from ..config import DictWithRecursion
+
def recursive_set(data: Dict[str, Any], key: str, value: Any) -> bool:
key, next_key = DictWithRecursion._parse_key(key)
if next_key is not None:
@@ -46,7 +47,7 @@ def recursive_del(data: Dict[str, any], key: str) -> bool:
if key not in data:
return False
next_data = data.get(key, {})
- recursive_del(next_data, next_key)
+ return recursive_del(next_data, next_key)
if key in data:
del data[key]
return True
diff --git a/requirements.txt b/requirements.txt
index 2fcca4c7..e9e5ccc2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,7 @@ ruamel.yaml
python-magic
SQLAlchemy
alembic
-Markdown
+commonmark
future-fstrings
telethon
telethon-session-sqlalchemy
diff --git a/setup.py b/setup.py
index 9d35da5d..aa2aa490 100644
--- a/setup.py
+++ b/setup.py
@@ -30,7 +30,7 @@ setuptools.setup(
"mautrix-appservice>=0.3.6,<0.4.0",
"SQLAlchemy>=1.2.3,<2",
"alembic>=1.0.0,<2",
- "Markdown>=2.6.11,<3",
+ "commonmark>=0.8.1,<1",
"ruamel.yaml>=0.15.35,<0.16",
"future-fstrings>=0.4.2",
"python-magic>=0.4.15,<0.5",