diff --git a/mautrix_telegram/commands/portal.py b/mautrix_telegram/commands/portal.py
index 43cdca76..ede472e3 100644
--- a/mautrix_telegram/commands/portal.py
+++ b/mautrix_telegram/commands/portal.py
@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-from typing import Dict, Callable, Optional, Tuple, Coroutine
+from typing import Dict, Callable, Optional, Tuple, Coroutine, Awaitable
from io import StringIO
import asyncio
@@ -396,13 +396,38 @@ async def upgrade(evt: CommandEvent) -> Dict:
@command_handler(help_section=SECTION_PORTAL_MANAGEMENT,
help_text="View or change per-portal settings.",
help_args="<`help`|_subcommand_> [...]")
-async def config(evt: CommandEvent) -> Dict:
+async def config(evt: CommandEvent) -> None:
cmd = evt.args[0].lower() if len(evt.args) > 0 else "help"
- 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 not in ("view", "defaults", "set", "unset", "add", "del"):
- return await evt.reply("""**Usage:** `$cmdprefix config [...]`. Subcommands:
+ await config_help(evt)
+ return
+ elif cmd == "defaults":
+ await config_defaults(evt)
+ return
+
+ portal = po.Portal.get_by_mxid(evt.room_id)
+ if not portal:
+ await evt.reply("This is not a portal room.")
+ return
+ elif cmd == "view":
+ await config_view(evt, portal)
+ return
+
+ key = evt.args[1] if len(evt.args) > 1 else None
+ value = yaml.load(" ".join(evt.args[2:])) if len(evt.args) > 2 else None
+ if cmd == "set":
+ await config_set(evt, portal, key, value)
+ elif cmd == "unset":
+ await config_unset(evt, portal, key)
+ elif cmd == "add" or cmd == "del":
+ await config_add_del(evt, portal, key, value, cmd)
+ else:
+ return
+ portal.save()
+
+
+def config_help(evt: CommandEvent) -> Awaitable[Dict]:
+ return evt.reply("""**Usage:** `$cmdprefix config [...]`. Subcommands:
* **help** - View this help text.
* **view** - View the current config data.
@@ -412,66 +437,73 @@ async def config(evt: CommandEvent) -> Dict:
* **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\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": {
- "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["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\n```yaml\n{stream.getvalue()}```",
- allow_html=True)
- key = evt.args[1] if len(evt.args) > 1 else None
- value = yaml.load(" ".join(evt.args[2:])) if len(evt.args) > 2 else None
- if cmd == "set":
- 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}`.")
- else:
- return await evt.reply(f"Failed to set value of `{key}`. "
- "Does the path contain non-map types?")
- elif cmd == "unset":
- if not key:
- return await evt.reply(f"**Usage:** `$cmdprefix+sp config {cmd} `")
- elif util.recursive_del(portal.local_config, key):
- return await evt.reply(f"Successfully deleted `{key}` from config.")
- else:
- return await evt.reply(f"`{key}` not found in config.")
- elif cmd == "add" or cmd == "del":
- 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)
- if not arr:
- return await evt.reply(f"`{key}` not found in config. "
- f"Maybe do `$cmdprefix+sp config set {key} []` first?")
- elif not isinstance(arr, list):
- return await evt.reply("`{key}` does not seem to be an array.")
- elif cmd == "add":
- if value in arr:
- return await evt.reply(f"The array at `{key}` already contains `{value}`.")
- arr.append(value)
- return await evt.reply(f"Successfully added `{value}` to the array at `{key}`")
- else:
- if value not in arr:
- 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()
+def config_view(evt: CommandEvent, portal: po.Portal) -> Awaitable[Dict]:
+ stream = StringIO()
+ yaml.dump(portal.local_config, stream)
+ return evt.reply(f"Room-specific config:\n\n```yaml\n{stream.getvalue()}```",
+ allow_html=True)
+
+
+def config_defaults(evt: CommandEvent) -> Awaitable[Dict]:
+ stream = StringIO()
+ yaml.dump({
+ "edits_as_replies": evt.config["bridge.edits_as_replies"],
+ "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["bridge.native_stickers"],
+ "message_formats": evt.config["bridge.message_formats"],
+ "state_event_formats": evt.config["bridge.state_event_formats"],
+ }, stream)
+ return evt.reply(f"Bridge instance wide config:\n\n```yaml\n{stream.getvalue()}```",
+ allow_html=True)
+
+
+def config_set(evt: CommandEvent, portal: po.Portal, key: str, value: str) -> Awaitable[Dict]:
+ if not key or value is None:
+ return evt.reply(f"**Usage:** `$cmdprefix+sp config set `")
+ elif util.recursive_set(portal.local_config, key, value):
+ return evt.reply(f"Successfully set the value of `{key}` to `{value}`.")
+ else:
+ return evt.reply(f"Failed to set value of `{key}`. "
+ "Does the path contain non-map types?")
+
+
+def config_unset(evt: CommandEvent, portal: po.Portal, key: str) -> Awaitable[Dict]:
+ if not key:
+ return evt.reply(f"**Usage:** `$cmdprefix+sp config unset `")
+ elif util.recursive_del(portal.local_config, key):
+ return evt.reply(f"Successfully deleted `{key}` from config.")
+ else:
+ return evt.reply(f"`{key}` not found in config.")
+
+
+def config_add_del(evt: CommandEvent, portal: po.Portal, key: str, value: str, cmd: str
+ ) -> Awaitable[Dict]:
+ if not key or value is None:
+ return evt.reply(f"**Usage:** `$cmdprefix+sp config {cmd} `")
+
+ arr = util.recursive_get(portal.local_config, key)
+ if not arr:
+ return evt.reply(f"`{key}` not found in config. "
+ f"Maybe do `$cmdprefix+sp config set {key} []` first?")
+ elif not isinstance(arr, list):
+ return evt.reply("`{key}` does not seem to be an array.")
+ elif cmd == "add":
+ if value in arr:
+ return evt.reply(f"The array at `{key}` already contains `{value}`.")
+ arr.append(value)
+ return evt.reply(f"Successfully added `{value}` to the array at `{key}`")
+ else:
+ if value not in arr:
+ return evt.reply(f"The array at `{key}` does not contain `{value}`.")
+ arr.remove(value)
+ return evt.reply(f"Successfully removed `{value}` from the array at `{key}`")
@command_handler(help_section=SECTION_PORTAL_MANAGEMENT,
diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py
index b7303316..789104f2 100644
--- a/mautrix_telegram/portal.py
+++ b/mautrix_telegram/portal.py
@@ -983,9 +983,9 @@ class Portal:
if msgtype == "m.notice":
bridge_notices = self.get_config("bridge_notices")
- if not bridge_notices.get("default", False):
- if sender_id not in bridge_notices.get("exceptions"):
- return
+ if not bridge_notices.get("default", False) and sender_id not in bridge_notices.get(
+ "exceptions"):
+ return
if msgtype == "m.text":
await self._handle_matrix_text(sender_id, event_id, space, client, message, reply_to)