33# This Source Code Form is subject to the terms of the Mozilla Public
44# License, v. 2.0. If a copy of the MPL was not distributed with this
55# file, You can obtain one at http://mozilla.org/MPL/2.0/.
6- from typing import Optional
6+ from __future__ import annotations
77
88from mautrix .errors import IntentError , MatrixRequestError , MForbidden
99from mautrix .types import ContentURI , EventID , UserID
1010
11+ from ... import bridge as br
1112from .handler import SECTION_ADMIN , CommandEvent , command_handler
1213
1314
1617 needs_auth = False ,
1718 name = "set-pl" ,
1819 help_section = SECTION_ADMIN ,
19- help_args = "<_level_> [_mxid_]" ,
20+ help_args = "[_mxid_] <_level_> " ,
2021 help_text = "Set a temporary power level without affecting the remote platform." ,
2122)
2223async def set_power_level (evt : CommandEvent ) -> EventID :
24+ try :
25+ user_id = UserID (evt .args [0 ])
26+ except IndexError :
27+ return await evt .reply (f"**Usage:** `$cmdprefix+sp set-pl [mxid] <level>`" )
28+
29+ if user_id .startswith ("@" ):
30+ evt .args .pop (0 )
31+ else :
32+ user_id = evt .sender .mxid
33+
2334 try :
2435 level = int (evt .args [0 ])
2536 except (KeyError , IndexError ):
26- return await evt .reply ("**Usage:** `$cmdprefix+sp set-pl <level> [mxid]`" )
37+ return await evt .reply ("**Usage:** `$cmdprefix+sp set-pl [mxid] <level> `" )
2738 except ValueError :
2839 return await evt .reply ("The level must be an integer." )
29- mxid = evt .args [1 ] if len (evt .args ) > 1 else evt .sender .mxid
3040 levels = await evt .main_intent .get_power_levels (evt .room_id , ignore_cache = True )
31- levels .users [mxid ] = level
41+ levels .users [user_id ] = level
3242 try :
3343 return await evt .main_intent .set_power_levels (evt .room_id , levels )
3444 except MForbidden as e :
@@ -38,6 +48,28 @@ async def set_power_level(evt: CommandEvent) -> EventID:
3848 return await evt .reply ("Failed to update power levels (see logs for more details)" )
3949
4050
51+ async def _get_mxid_param (
52+ evt : CommandEvent , args : str
53+ ) -> tuple [br .BasePuppet | None , EventID | None ]:
54+ try :
55+ user_id = UserID (evt .args [0 ])
56+ except IndexError :
57+ return None , await evt .reply (f"**Usage:** `$cmdprefix+sp { evt .command } { args } `" )
58+
59+ if user_id .startswith ("@" ) and ":" in user_id :
60+ # TODO support parsing mention pills instead of requiring a plaintext mxid
61+ puppet = await evt .bridge .get_puppet (user_id )
62+ if not puppet :
63+ return None , await evt .reply ("The given user ID is not a valid ghost user." )
64+ evt .args .pop (0 )
65+ return puppet , None
66+ elif evt .is_portal and (puppet := await evt .portal .get_dm_puppet ()):
67+ return puppet , None
68+ return None , await evt .reply (
69+ "This is not a private chat portal, you must pass a user ID explicitly."
70+ )
71+
72+
4173@command_handler (
4274 needs_admin = True ,
4375 needs_auth = False ,
@@ -46,27 +78,20 @@ async def set_power_level(evt: CommandEvent) -> EventID:
4678 help_args = "<_mxc:// uri_> [_mxid_]" ,
4779 help_text = "Set an avatar for a ghost user." ,
4880)
49- async def set_ghost_avatar (evt : CommandEvent ) -> Optional [EventID ]:
81+ async def set_ghost_avatar (evt : CommandEvent ) -> EventID | None :
82+ puppet , err = await _get_mxid_param (evt , "[mxid] <mxc:// URI>" )
83+ if err :
84+ return err
85+
5086 try :
5187 mxc_uri = ContentURI (evt .args [0 ])
52- except ( KeyError , IndexError ) :
53- return await evt .reply ("**Usage:** `$cmdprefix+sp set-avatar <mxc_uri> [mxid]`" )
88+ except IndexError :
89+ return await evt .reply ("**Usage:** `$cmdprefix+sp set-avatar [mxid] <mxc_uri> `" )
5490 if not mxc_uri .startswith ("mxc://" ):
55- return await evt .reply ("The URI has to start with mxc://." )
56- if len (evt .args ) > 1 :
57- # TODO support parsing mention pills instead of requiring a plaintext mxid
58- puppet = await evt .processor .bridge .get_puppet (UserID (evt .args [1 ]))
59- if puppet is None :
60- return await evt .reply ("The given mxid was not a valid ghost user." )
61- intent = puppet .intent
62- elif evt .is_portal :
63- intent = evt .portal .main_intent
64- if intent == evt .az .intent :
65- return await evt .reply ("No mxid given and the main intent is not a ghost user." )
66- else :
67- return await evt .reply ("No mxid given and not in a portal." )
91+ return await evt .reply ("The avatar URL must start with `mxc://`" )
92+
6893 try :
69- return await intent .set_avatar_url (mxc_uri )
94+ return await puppet . default_mxid_intent .set_avatar_url (mxc_uri )
7095 except (MatrixRequestError , IntentError ):
7196 evt .log .exception ("Failed to set avatar." )
7297 return await evt .reply ("Failed to set avatar (see logs for more details)." )
@@ -80,20 +105,12 @@ async def set_ghost_avatar(evt: CommandEvent) -> Optional[EventID]:
80105 help_args = "[_mxid_]" ,
81106 help_text = "Remove the avatar for a ghost user." ,
82107)
83- async def remove_ghost_avatar (evt : CommandEvent ) -> Optional [EventID ]:
84- if len (evt .args ) > 0 :
85- puppet = await evt .processor .bridge .get_puppet (UserID (evt .args [0 ]))
86- if puppet is None :
87- return await evt .reply ("The given mxid was not a valid ghost user." )
88- intent = puppet .intent
89- elif evt .is_portal :
90- intent = evt .portal .main_intent
91- if intent == evt .az .intent :
92- return await evt .reply ("No mxid given and the main intent is not a ghost user." )
93- else :
94- return await evt .reply ("No mxid given and not in a portal." )
108+ async def remove_ghost_avatar (evt : CommandEvent ) -> EventID | None :
109+ puppet , err = await _get_mxid_param (evt , "[mxid]" )
110+ if err :
111+ return err
95112 try :
96- return await intent .set_avatar_url (ContentURI ("" ))
113+ return await puppet . default_mxid_intent .set_avatar_url (ContentURI ("" ))
97114 except (MatrixRequestError , IntentError ):
98115 evt .log .exception ("Failed to remove avatar." )
99116 return await evt .reply ("Failed to remove avatar (see logs for more details)." )
@@ -104,29 +121,15 @@ async def remove_ghost_avatar(evt: CommandEvent) -> Optional[EventID]:
104121 needs_auth = False ,
105122 name = "set-displayname" ,
106123 help_section = SECTION_ADMIN ,
107- help_args = "<_displayname_> [_mxid_]" ,
124+ help_args = "[_mxid_] <_displayname_> " ,
108125 help_text = "Set the display name for a ghost user." ,
109126)
110- async def set_ghost_display_name (evt : CommandEvent ) -> Optional [EventID ]:
111- if len (evt .args ) > 1 :
112- # This allows whitespaces in the name
113- puppet = await evt .processor .bridge .get_puppet (UserID (evt .args [len (evt .args ) - 1 ]))
114- if puppet is None :
115- return await evt .reply (
116- "The given mxid was not a valid ghost user. "
117- "If the display name has whitespaces mxid is required"
118- )
119- intent = puppet .intent
120- displayname = " " .join (evt .args [:- 1 ])
121- elif evt .is_portal :
122- intent = evt .portal .main_intent
123- if intent == evt .az .intent :
124- return await evt .reply ("No mxid given and the main intent is not a ghost user." )
125- displayname = evt .args [0 ]
126- else :
127- return await evt .reply ("No mxid given and not in a portal." )
127+ async def set_ghost_display_name (evt : CommandEvent ) -> EventID | None :
128+ puppet , err = await _get_mxid_param (evt , "[mxid] <displayname>" )
129+ if err :
130+ return err
128131 try :
129- return await intent . set_displayname (displayname )
132+ return await puppet . default_mxid_intent . set_displayname (" " . join ( evt . args ) )
130133 except (MatrixRequestError , IntentError ):
131134 evt .log .exception ("Failed to set display name." )
132135 return await evt .reply ("Failed to set display name (see logs for more details)." )
@@ -140,20 +143,12 @@ async def set_ghost_display_name(evt: CommandEvent) -> Optional[EventID]:
140143 help_args = "[_mxid_]" ,
141144 help_text = "Remove the display name for a ghost user." ,
142145)
143- async def set_ghost_display_name (evt : CommandEvent ) -> Optional [EventID ]:
144- if len (evt .args ) > 0 :
145- puppet = await evt .processor .bridge .get_puppet (UserID (evt .args [0 ]))
146- if puppet is None :
147- return await evt .reply ("The given mxid was not a valid ghost user." )
148- intent = puppet .intent
149- elif evt .is_portal :
150- intent = evt .portal .main_intent
151- if intent == evt .az .intent :
152- return await evt .reply ("No mxid given and the main intent is not a ghost user." )
153- else :
154- return await evt .reply ("No mxid given and not in a portal (see logs for more details)." )
146+ async def remove_ghost_display_name (evt : CommandEvent ) -> EventID | None :
147+ puppet , err = await _get_mxid_param (evt , "[mxid]" )
148+ if err :
149+ return err
155150 try :
156- return await intent .set_displayname ("" )
151+ return await puppet . default_mxid_intent .set_displayname ("" )
157152 except (MatrixRequestError , IntentError ):
158153 evt .log .exception ("Failed to remove display name." )
159154 return await evt .reply ("Failed to remove display name (see logs for more details)." )
0 commit comments