consolidate commands
This commit is contained in:
+198
-210
@@ -1167,15 +1167,164 @@ class CommunityBot(Plugin):
|
||||
return True
|
||||
|
||||
@community.subcommand(
|
||||
"user", help="manage users in the community"
|
||||
)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def user(self, evt: MessageEvent) -> None:
|
||||
"""Main user command - shows usage by default"""
|
||||
await evt.reply("Use !community user <subcommand> to manage users. Available subcommands: bancheck, ban, unban, kick, ignore, unignore, redact")
|
||||
|
||||
@user.subcommand(
|
||||
"bancheck", help="check subscribed banlists for a user's mxid"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
async def check_banlists(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
async def user_bancheck(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
if not await self.check_parent_room(evt):
|
||||
return
|
||||
ban_status = await self.check_if_banned(mxid)
|
||||
await evt.reply(f"user on banlist: {ban_status}")
|
||||
|
||||
@user.subcommand(
|
||||
"ban", help="kick and ban a specific user from the community and all rooms"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def user_ban(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
await evt.mark_read()
|
||||
|
||||
user = mxid
|
||||
msg = await evt.respond("starting the ban...")
|
||||
results_map = await self.ban_this_user(user, all_rooms=True)
|
||||
|
||||
results = "the following users were kicked and banned:<p><code>{ban_list}</code></p>the following errors were \
|
||||
recorded:<p><code>{error_list}</code></p>".format(
|
||||
ban_list=results_map["ban_list"], error_list=results_map["error_list"]
|
||||
)
|
||||
await evt.respond(results, allow_html=True, edits=msg)
|
||||
|
||||
# sync our database after we've made changes to room memberships
|
||||
await self.do_sync()
|
||||
|
||||
@user.subcommand(
|
||||
"unban", help="unban a specific user from the community and all rooms"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def user_unban(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
await evt.mark_read()
|
||||
|
||||
user = mxid
|
||||
msg = await evt.respond("starting the unban...")
|
||||
roomlist = await self.get_space_roomlist()
|
||||
# don't forget to kick from the space itself
|
||||
roomlist.append(self.config["parent_room"])
|
||||
unban_list = {}
|
||||
error_list = {}
|
||||
|
||||
unban_list[user] = []
|
||||
for room in roomlist:
|
||||
try:
|
||||
roomname = None
|
||||
roomnamestate = await self.client.get_state_event(
|
||||
room, "m.room.name"
|
||||
)
|
||||
if roomnamestate:
|
||||
roomname = roomnamestate.name
|
||||
else:
|
||||
roomname = room
|
||||
|
||||
await self.client.unban_user(room, user)
|
||||
unban_list[user].append(roomname)
|
||||
except Exception as e:
|
||||
error_list[room] = str(e)
|
||||
|
||||
results = "the following users were unbanned:<p><code>{unban_list}</code></p>the following errors were \
|
||||
recorded:<p><code>{error_list}</code></p>".format(
|
||||
unban_list=unban_list, error_list=error_list
|
||||
)
|
||||
await evt.respond(results, allow_html=True, edits=msg)
|
||||
|
||||
# sync our database after we've made changes to room memberships
|
||||
await self.do_sync()
|
||||
|
||||
@user.subcommand(
|
||||
"ignore", help="exclude a specific matrix ID from inactivity tracking"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
@decorators.handle_errors("Failed to ignore user")
|
||||
async def user_ignore(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
if not self.config_manager.is_tracking_enabled():
|
||||
await evt.reply("user tracking is disabled")
|
||||
return
|
||||
|
||||
Client.parse_user_id(mxid)
|
||||
await self.database.execute(
|
||||
"UPDATE user_events SET ignore_inactivity = 1 WHERE \
|
||||
mxid = $1",
|
||||
mxid,
|
||||
)
|
||||
self.log.info(f"{mxid} set to ignore inactivity")
|
||||
await evt.react("✅")
|
||||
|
||||
@user.subcommand(
|
||||
"unignore", help="re-enable activity tracking for a specific matrix ID"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
@decorators.handle_errors("Failed to unignore user")
|
||||
async def user_unignore(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
if not self.config_manager.is_tracking_enabled():
|
||||
await evt.reply("user tracking is disabled")
|
||||
return
|
||||
|
||||
Client.parse_user_id(mxid)
|
||||
await self.database.execute(
|
||||
"UPDATE user_events SET ignore_inactivity = 0 WHERE \
|
||||
mxid = $1",
|
||||
mxid,
|
||||
)
|
||||
self.log.info(f"{mxid} set to track inactivity")
|
||||
await evt.react("✅")
|
||||
|
||||
@user.subcommand(
|
||||
"redact", help="redact messages from a specific user (optionally in a specific room)"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@command.argument("room", "room ID", required=False)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def user_redact(self, evt: MessageEvent, mxid: UserID, room: str) -> None:
|
||||
await evt.mark_read()
|
||||
|
||||
if room:
|
||||
if room.startswith("#"):
|
||||
try:
|
||||
room_id = await self.client.resolve_room_alias(room)
|
||||
room_id = room_id["room_id"]
|
||||
except:
|
||||
evt.reply("i couldn't resolve that alias, sorry")
|
||||
return
|
||||
else:
|
||||
room_id = room
|
||||
else:
|
||||
room_id = evt.room_id
|
||||
|
||||
# get list of messages to redact in this room
|
||||
messages = await self.get_messages_to_redact(room_id, mxid)
|
||||
for msg in messages:
|
||||
await self.database.execute(
|
||||
"INSERT INTO redaction_tasks (event_id, room_id) VALUES ($1, $2)",
|
||||
msg.event_id,
|
||||
room_id,
|
||||
)
|
||||
await evt.respond(f"Queued {len(messages)} messages for redaction in {room_id}")
|
||||
|
||||
@community.subcommand(
|
||||
"sync",
|
||||
help="update the activity tracker with the current space members \
|
||||
@@ -1200,48 +1349,6 @@ class CommunityBot(Plugin):
|
||||
f"Added: {added_str}<br /><br />Dropped: {dropped_str}", allow_html=True
|
||||
)
|
||||
|
||||
@community.subcommand(
|
||||
"ignore", help="exclude a specific matrix ID from inactivity tracking"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
@decorators.handle_errors("Failed to ignore user")
|
||||
async def ignore_inactivity(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
if not self.config_manager.is_tracking_enabled():
|
||||
await evt.reply("user tracking is disabled")
|
||||
return
|
||||
|
||||
Client.parse_user_id(mxid)
|
||||
await self.database.execute(
|
||||
"UPDATE user_events SET ignore_inactivity = 1 WHERE \
|
||||
mxid = $1",
|
||||
mxid,
|
||||
)
|
||||
self.log.info(f"{mxid} set to ignore inactivity")
|
||||
await evt.react("✅")
|
||||
|
||||
@community.subcommand(
|
||||
"unignore", help="re-enable activity tracking for a specific matrix ID"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
@decorators.handle_errors("Failed to unignore user")
|
||||
async def unignore_inactivity(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
if not self.config_manager.is_tracking_enabled():
|
||||
await evt.reply("user tracking is disabled")
|
||||
return
|
||||
|
||||
Client.parse_user_id(mxid)
|
||||
await self.database.execute(
|
||||
"UPDATE user_events SET ignore_inactivity = 0 WHERE \
|
||||
mxid = $1",
|
||||
mxid,
|
||||
)
|
||||
self.log.info(f"{mxid} set to track inactivity")
|
||||
await evt.react("✅")
|
||||
|
||||
@community.subcommand(
|
||||
"report", help="generate reports of user activity and inactivity"
|
||||
)
|
||||
@@ -1399,24 +1506,24 @@ class CommunityBot(Plugin):
|
||||
# sync our database after we've made changes to room memberships
|
||||
await self.do_sync()
|
||||
|
||||
@community.subcommand(
|
||||
@user.subcommand(
|
||||
"kick", help="kick a specific user from the community and all rooms"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def kick_user(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
async def user_kick(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
await evt.mark_read()
|
||||
|
||||
user = mxid
|
||||
msg = await evt.respond("starting the purge...")
|
||||
msg = await evt.respond("starting the kick...")
|
||||
roomlist = await self.get_space_roomlist()
|
||||
# don't forget to kick from the space itself
|
||||
roomlist.append(self.config["parent_room"])
|
||||
purge_list = {}
|
||||
kick_list = {}
|
||||
error_list = {}
|
||||
|
||||
purge_list[user] = []
|
||||
kick_list[user] = []
|
||||
for room in roomlist:
|
||||
try:
|
||||
roomname = None
|
||||
@@ -1428,9 +1535,9 @@ class CommunityBot(Plugin):
|
||||
await self.client.get_state_event(room, EventType.ROOM_MEMBER, user)
|
||||
await self.client.kick_user(room, user, reason="kicked")
|
||||
if roomname:
|
||||
purge_list[user].append(roomname)
|
||||
kick_list[user].append(roomname)
|
||||
else:
|
||||
purge_list[user].append(room)
|
||||
kick_list[user].append(room)
|
||||
time.sleep(self.config["sleep"])
|
||||
except MNotFound:
|
||||
pass
|
||||
@@ -1439,127 +1546,15 @@ class CommunityBot(Plugin):
|
||||
error_list[user] = []
|
||||
error_list[user].append(roomname or room)
|
||||
|
||||
results = "the following users were kicked:<p><code>{purge_list}</code></p>the following errors were \
|
||||
results = "the following users were kicked:<p><code>{kick_list}</code></p>the following errors were \
|
||||
recorded:<p><code>{error_list}</code></p>".format(
|
||||
purge_list=purge_list, error_list=error_list
|
||||
kick_list=kick_list, error_list=error_list
|
||||
)
|
||||
await evt.respond(results, allow_html=True, edits=msg)
|
||||
|
||||
# sync our database after we've made changes to room memberships
|
||||
await self.do_sync()
|
||||
|
||||
@community.subcommand(
|
||||
"ban", help="kick and ban a specific user from the community and all rooms"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def ban_user(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
await evt.mark_read()
|
||||
|
||||
user = mxid
|
||||
msg = await evt.respond("starting the ban...")
|
||||
results_map = await self.ban_this_user(user, all_rooms=True)
|
||||
|
||||
results = "the following users were kicked and banned:<p><code>{ban_list}</code></p>the following errors were \
|
||||
recorded:<p><code>{error_list}</code></p>".format(
|
||||
ban_list=results_map["ban_list"], error_list=results_map["error_list"]
|
||||
)
|
||||
await evt.respond(results, allow_html=True, edits=msg)
|
||||
|
||||
# sync our database after we've made changes to room memberships
|
||||
await self.do_sync()
|
||||
|
||||
@community.subcommand(
|
||||
"unban", help="unban a specific user from the community and all rooms"
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
async def unban_user(self, evt: MessageEvent, mxid: UserID) -> None:
|
||||
if not await self.check_parent_room(evt):
|
||||
return
|
||||
await evt.mark_read()
|
||||
if not await self.user_permitted(evt.sender):
|
||||
await evt.reply("You don't have permission to use this command")
|
||||
return
|
||||
|
||||
user = mxid
|
||||
msg = await evt.respond("starting the unban...")
|
||||
roomlist = await self.get_space_roomlist()
|
||||
# don't forget to kick from the space itself
|
||||
roomlist.append(self.config["parent_room"])
|
||||
unban_list = {}
|
||||
error_list = {}
|
||||
|
||||
unban_list[user] = []
|
||||
for room in roomlist:
|
||||
try:
|
||||
roomname = None
|
||||
roomnamestate = await self.client.get_state_event(
|
||||
room, "m.room.name"
|
||||
)
|
||||
roomname = roomnamestate["name"]
|
||||
|
||||
await self.client.get_state_event(room, EventType.ROOM_MEMBER, user)
|
||||
await self.client.unban_user(room, user, reason="unbanned")
|
||||
if roomname:
|
||||
unban_list[user].append(roomname)
|
||||
else:
|
||||
unban_list[user].append(room)
|
||||
time.sleep(self.config["sleep"])
|
||||
except MNotFound:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.log.warning(e)
|
||||
error_list[user] = []
|
||||
error_list[user].append(roomname or room)
|
||||
|
||||
results = "the following users were unbanned:<p><code>{unban_list}</code></p>the following errors were \
|
||||
recorded:<p><code>{error_list}</code></p>".format(
|
||||
unban_list=unban_list, error_list=error_list
|
||||
)
|
||||
await evt.respond(results, allow_html=True, edits=msg)
|
||||
|
||||
# sync our database after we've made changes to room memberships
|
||||
await self.do_sync()
|
||||
|
||||
@community.subcommand(
|
||||
"redact",
|
||||
help="redact messages from a specific user (optionally in a specific room)",
|
||||
)
|
||||
@command.argument("mxid", "full matrix ID", required=True)
|
||||
@command.argument("room", "room ID", required=False)
|
||||
async def mark_for_redaction(
|
||||
self, evt: MessageEvent, mxid: UserID, room: str
|
||||
) -> None:
|
||||
if not await self.check_parent_room(evt):
|
||||
return
|
||||
await evt.mark_read()
|
||||
if not await self.user_permitted(evt.sender):
|
||||
await evt.reply("You don't have permission to use this command")
|
||||
return
|
||||
|
||||
if room:
|
||||
if room.startswith("#"):
|
||||
try:
|
||||
room_id = await self.client.resolve_room_alias(room)
|
||||
room_id = room_id["room_id"]
|
||||
except:
|
||||
evt.reply("i couldn't resolve that alias, sorry")
|
||||
return
|
||||
else:
|
||||
room_id = room
|
||||
else:
|
||||
room_id = evt.room_id
|
||||
|
||||
# get list of messages to redact in this room
|
||||
messages = await self.get_messages_to_redact(room_id, mxid)
|
||||
for msg in messages:
|
||||
await self.database.execute(
|
||||
"INSERT INTO redaction_tasks (event_id, room_id) VALUES ($1, $2)",
|
||||
msg.event_id,
|
||||
room_id,
|
||||
)
|
||||
await evt.respond(f"Queued {len(messages)} messages for redaction in {room_id}")
|
||||
|
||||
async def create_room(self, roomname: str, evt: MessageEvent = None, power_level_override: Optional[PowerLevelStateEventContent] = None, creation_content: Optional[dict] = None, invitees: Optional[list[str]] = None) -> tuple[str, str] | None:
|
||||
"""Create a new room and add it to the parent space.
|
||||
@@ -1681,14 +1676,23 @@ class CommunityBot(Plugin):
|
||||
return None
|
||||
|
||||
@community.subcommand(
|
||||
"createroom",
|
||||
"room", help="manage rooms in the community"
|
||||
)
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def room(self, evt: MessageEvent) -> None:
|
||||
"""Main room command - shows usage by default"""
|
||||
await evt.reply("Use !community room <subcommand> to manage rooms. Available subcommands: create, archive, replace, guests, id, version, setpower")
|
||||
|
||||
@room.subcommand(
|
||||
"create",
|
||||
help="create a new room titled <roomname> and add it to the parent space. \
|
||||
optionally include `--encrypted` or `--unencrypted` to force regardless of the default settings.",
|
||||
)
|
||||
@command.argument("roomname", pass_raw=True, required=True)
|
||||
async def create_that_room(self, evt: MessageEvent, roomname: str) -> None:
|
||||
if not await self.check_parent_room(evt):
|
||||
return
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def room_create(self, evt: MessageEvent, roomname: str) -> None:
|
||||
if (roomname == "help") or len(roomname) == 0:
|
||||
await evt.reply(
|
||||
'pass me a room name (like "cool topic") and i will create it and add it to the space. \
|
||||
@@ -1697,10 +1701,6 @@ class CommunityBot(Plugin):
|
||||
)
|
||||
return
|
||||
|
||||
if not await self.user_permitted(evt.sender):
|
||||
await evt.reply("You don't have permission to use this command")
|
||||
return
|
||||
|
||||
# Check if community slug is configured
|
||||
if not self.config["community_slug"]:
|
||||
await evt.reply("No community slug configured. Please run initialize command first.")
|
||||
@@ -1716,17 +1716,13 @@ class CommunityBot(Plugin):
|
||||
if not result:
|
||||
return # Error already logged and reported to user by create_room
|
||||
|
||||
@community.subcommand("archive", help="archive a room")
|
||||
@room.subcommand("archive", help="archive a room")
|
||||
@command.argument("room", required=False)
|
||||
async def archive_room(self, evt: MessageEvent, room: str) -> None:
|
||||
if not await self.check_parent_room(evt):
|
||||
return
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def room_archive(self, evt: MessageEvent, room: str) -> None:
|
||||
await evt.mark_read()
|
||||
|
||||
if not await self.user_permitted(evt.sender):
|
||||
await evt.reply("You don't have permission to use this command")
|
||||
return
|
||||
|
||||
if not room:
|
||||
room_id = evt.room_id
|
||||
self.log.debug(f"DEBUG room we are archiving is {room_id}")
|
||||
@@ -1753,21 +1749,16 @@ class CommunityBot(Plugin):
|
||||
if success and room_id != evt.room_id:
|
||||
await evt.respond("Room has been archived.")
|
||||
|
||||
@community.subcommand("replaceroom", help="replace a room with a new one")
|
||||
@room.subcommand("replace", help="replace a room with a new one")
|
||||
@command.argument("room", required=False)
|
||||
async def replace_room(self, evt: MessageEvent, room: str) -> None:
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission(min_level=100)
|
||||
async def room_replace(self, evt: MessageEvent, room: str) -> None:
|
||||
self.log.info(f"=== REPLACEROOM COMMAND STARTED ===")
|
||||
self.log.info(f"Command arguments: room='{room}', evt.room_id='{evt.room_id}'")
|
||||
|
||||
if not await self.check_parent_room(evt):
|
||||
self.log.info("Parent room check failed, returning")
|
||||
return
|
||||
await evt.mark_read()
|
||||
|
||||
if not await self.user_permitted(evt.sender):
|
||||
await evt.reply("You don't have permission to use this command")
|
||||
return
|
||||
|
||||
if not room:
|
||||
room = evt.room_id
|
||||
# first we need to get relevant room state of the room we want to replace
|
||||
@@ -2181,14 +2172,14 @@ class CommunityBot(Plugin):
|
||||
f"Old room has been archived with a pointer to the new room."
|
||||
)
|
||||
|
||||
@community.subcommand(
|
||||
@room.subcommand(
|
||||
"guests",
|
||||
help="generate a list of members in a room who are not members of the parent space",
|
||||
)
|
||||
@command.argument("room", required=False)
|
||||
async def get_guestlist(self, evt: MessageEvent, room: str) -> None:
|
||||
if not await self.check_parent_room(evt):
|
||||
return
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def room_guests(self, evt: MessageEvent, room: str) -> None:
|
||||
space_members_obj = await self.client.get_joined_members(
|
||||
self.config["parent_room"]
|
||||
)
|
||||
@@ -2222,13 +2213,13 @@ class CommunityBot(Plugin):
|
||||
except Exception as e:
|
||||
await evt.respond(f"something went wrong: {e}")
|
||||
|
||||
@community.subcommand(
|
||||
"roomid", help="return the matrix room ID of this, or a given, room"
|
||||
@room.subcommand(
|
||||
"id", help="return the matrix room ID of this, or a given, room"
|
||||
)
|
||||
@command.argument("room", required=False)
|
||||
async def get_roomid(self, evt: MessageEvent, room: str) -> None:
|
||||
if not await self.check_parent_room(evt):
|
||||
return
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def room_id(self, evt: MessageEvent, room: str) -> None:
|
||||
room_id = None
|
||||
if room:
|
||||
if room.startswith("#"):
|
||||
@@ -2247,13 +2238,13 @@ class CommunityBot(Plugin):
|
||||
except Exception as e:
|
||||
await evt.respond(f"something went wrong: {e}")
|
||||
|
||||
@community.subcommand(
|
||||
"roomversion", help="return the room version and creators of this, or a given, room"
|
||||
@room.subcommand(
|
||||
"version", help="return the room version and creators of this, or a given, room"
|
||||
)
|
||||
@command.argument("room", required=False)
|
||||
async def get_roomversion(self, evt: MessageEvent, room: str) -> None:
|
||||
if not await self.check_parent_room(evt):
|
||||
return
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission()
|
||||
async def room_version(self, evt: MessageEvent, room: str) -> None:
|
||||
room_id = None
|
||||
if room:
|
||||
if room.startswith("#"):
|
||||
@@ -2294,21 +2285,18 @@ class CommunityBot(Plugin):
|
||||
except Exception as e:
|
||||
await evt.respond(f"something went wrong: {e}")
|
||||
|
||||
@community.subcommand(
|
||||
@room.subcommand(
|
||||
"setpower", help="sync user power levels from parent room to all child rooms. this will override existing user power levels in child rooms!"
|
||||
)
|
||||
@command.argument("target_room", required=False)
|
||||
async def set_powerlevels(
|
||||
@decorators.require_parent_room
|
||||
@decorators.require_permission(min_level=100)
|
||||
async def room_setpower(
|
||||
self,
|
||||
evt: MessageEvent,
|
||||
target_room: str = None
|
||||
) -> None:
|
||||
if not await self.check_parent_room(evt):
|
||||
return
|
||||
await evt.mark_read()
|
||||
if not await self.user_permitted(evt.sender, min_level=100):
|
||||
await evt.reply("You don't have permission to use this command")
|
||||
return
|
||||
|
||||
if target_room:
|
||||
roomlist = [target_room]
|
||||
|
||||
Reference in New Issue
Block a user