diff --git a/base-config.yaml b/base-config.yaml
index fa22ef3..65dbcb0 100644
--- a/base-config.yaml
+++ b/base-config.yaml
@@ -1,12 +1,15 @@
# the room-id of the matrix room or space to use as your "full user list"
+# changes to user power levelsin this room will affect all rooms in the space
parent_room: "!somerandomcharacters:server.tld"
# sleep time between actions. you can drop this to 0 if your bot has no
# ratelimits imposed on its homeserver, otherwise you may want to increase this
# to avoid errors.
-sleep: 1
+sleep: 5
-# whether to encrypt rooms when using the room creation commands
+# whether to encrypt rooms when using the room creation commands
+# when this is false, you can still use the --encrypt flag to force encryption
+# when creating new rooms
encrypt: False
# number of days of inactivity to be considered in the "warning zone"
@@ -27,18 +30,14 @@ track_messages: True
track_reactions: True
# list of users who can use administrative commands. these users will also be made room admins (PL100)
-# DEPRECATED: set powerlevels in the parent room instead.
-admins:
- - '@user1:server.tld'
- - '@user2:server.tld'
+# DEPRECATED: set user powerlevels in the parent room instead.
+admins: []
# list of users who should be considered community moderators. these users will be made room mods (PL50)
-# DEPRECATED: set powerlevels in the parent room instead.
-moderators:
- - '@user3:server.tld'
- - '@user4:server.tld'
+# DEPRECATED: set userpowerlevels in the parent room instead.
+moderators: []
-# list of users who should be invited to new rooms immediately (other bots perhaps)
+# list of users who should be invited to new rooms immediately (other bots, moderators, perhaps)
invitees:
- "@mybot:server.tld"
- "@secondaryadmin:server.tld"
diff --git a/community/bot.py b/community/bot.py
index 236c37d..f5a152b 100644
--- a/community/bot.py
+++ b/community/bot.py
@@ -943,21 +943,21 @@ class CommunityBot(Plugin):
await evt.reply("You don't have permission to use this command")
return
- if not self.config["track_users"]:
- await evt.reply("user tracking is disabled")
- return
+ if not self.config["track_users"]:
+ await evt.reply("user tracking is disabled")
+ return
- try:
- 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("✅")
- except Exception as e:
- await evt.respond(f"{e}")
+ try:
+ 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("✅")
+ except Exception as e:
+ await evt.respond(f"{e}")
@community.subcommand(
"unignore", help="re-enable activity tracking for a specific matrix ID"
@@ -968,21 +968,21 @@ class CommunityBot(Plugin):
await evt.reply("You don't have permission to use this command")
return
- if not self.config["track_users"]:
- await evt.reply("user tracking is disabled")
- return
+ if not self.config["track_users"]:
+ await evt.reply("user tracking is disabled")
+ return
- try:
- 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("✅")
- except Exception as e:
- await evt.respond(f"{e}")
+ try:
+ 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("✅")
+ except Exception as e:
+ await evt.respond(f"{e}")
@community.subcommand(
"report", help="generate a list of matrix IDs that have been inactive"
@@ -992,22 +992,22 @@ class CommunityBot(Plugin):
await evt.reply("You don't have permission to use this command")
return
- if not self.config["track_users"]:
- await evt.reply("user tracking is disabled")
- return
+ if not self.config["track_users"]:
+ await evt.reply("user tracking is disabled")
+ return
- sync_results = await self.do_sync()
- report = await self.generate_report()
- await evt.respond(
- f"
Users inactive for between {self.config['warn_threshold_days']} and \
- {self.config['kick_threshold_days']} days:
\
- {'
'.join(report['warn_inactive'])}
\
- Users inactive for at least {self.config['kick_threshold_days']} days:
\
- {'
'.join(report['kick_inactive'])}
\
- Ignored users:
\
- {'
'.join(report['ignored'])}
",
- allow_html=True,
- )
+ sync_results = await self.do_sync()
+ report = await self.generate_report()
+ await evt.respond(
+ f"Users inactive for between {self.config['warn_threshold_days']} and \
+ {self.config['kick_threshold_days']} days:
\
+ {'
'.join(report['warn_inactive'])}
\
+ Users inactive for at least {self.config['kick_threshold_days']} days:
\
+ {'
'.join(report['kick_inactive'])}
\
+ Ignored users:
\
+ {'
'.join(report['ignored'])}
",
+ allow_html=True,
+ )
@community.subcommand("purge", help="kick users for excessive inactivity")
async def kick_users(self, evt: MessageEvent) -> None:
@@ -1016,49 +1016,49 @@ class CommunityBot(Plugin):
await evt.reply("You don't have permission to use this command")
return
- msg = await evt.respond("starting the purge...")
- report = await self.generate_report()
- purgeable = report["kick_inactive"]
- roomlist = await self.get_space_roomlist()
- # don't forget to kick from the space itself
- roomlist.append(self.config["parent_room"])
- purge_list = {}
- error_list = {}
+ msg = await evt.respond("starting the purge...")
+ report = await self.generate_report()
+ purgeable = report["kick_inactive"]
+ roomlist = await self.get_space_roomlist()
+ # don't forget to kick from the space itself
+ roomlist.append(self.config["parent_room"])
+ purge_list = {}
+ error_list = {}
- for user in purgeable:
- purge_list[user] = []
- for room in roomlist:
- try:
- roomname = None
- roomnamestate = await self.client.get_state_event(
- room, "m.room.name"
- )
- roomname = roomnamestate["name"]
+ for user in purgeable:
+ purge_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.kick_user(room, user, reason="inactivity")
- if roomname:
- purge_list[user].append(roomname)
- else:
- purge_list[user].append(room)
- time.sleep("sleep")
- except MNotFound:
- pass
- except Exception as e:
- self.log.warning(e)
- error_list[user] = []
- error_list[user].append(roomname or room)
+ await self.client.get_state_event(
+ room, EventType.ROOM_MEMBER, user
+ )
+ await self.client.kick_user(room, user, reason="inactivity")
+ if roomname:
+ purge_list[user].append(roomname)
+ else:
+ purge_list[user].append(room)
+ time.sleep("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 purged:{purge_list}
the following errors were \
- recorded:{error_list}
".format(
- purge_list=purge_list, error_list=error_list
- )
- await evt.respond(results, allow_html=True, edits=msg)
+ results = "the following users were purged:{purge_list}
the following errors were \
+ recorded:{error_list}
".format(
+ purge_list=purge_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()
+ # sync our database after we've made changes to room memberships
+ await self.do_sync()
@community.subcommand(
"kick", help="kick a specific user from the community and all rooms"
@@ -1070,45 +1070,45 @@ class CommunityBot(Plugin):
await evt.reply("You don't have permission to use this command")
return
- user = mxid
- msg = await evt.respond("starting the purge...")
- roomlist = await self.get_space_roomlist()
- # don't forget to kick from the space itself
- roomlist.append(self.config["parent_room"])
- purge_list = {}
- error_list = {}
+ user = mxid
+ msg = await evt.respond("starting the purge...")
+ roomlist = await self.get_space_roomlist()
+ # don't forget to kick from the space itself
+ roomlist.append(self.config["parent_room"])
+ purge_list = {}
+ error_list = {}
- purge_list[user] = []
- for room in roomlist:
- try:
- roomname = None
- roomnamestate = await self.client.get_state_event(
- room, "m.room.name"
- )
- roomname = roomnamestate["name"]
+ purge_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.kick_user(room, user, reason="kicked")
- if roomname:
- purge_list[user].append(roomname)
- else:
- purge_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)
+ 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)
+ else:
+ purge_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 kicked:{purge_list}
the following errors were \
- recorded:{error_list}
".format(
- purge_list=purge_list, error_list=error_list
- )
- await evt.respond(results, allow_html=True, edits=msg)
+ results = "the following users were kicked:{purge_list}
the following errors were \
+ recorded:{error_list}
".format(
+ purge_list=purge_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()
+ # 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"
@@ -1120,18 +1120,18 @@ class CommunityBot(Plugin):
await evt.reply("You don't have permission to use this command")
return
- user = mxid
- msg = await evt.respond("starting the ban...")
- results_map = await self.ban_this_user(user, all_rooms=True)
+ 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:{ban_list}
the following errors were \
- recorded:{error_list}
".format(
- ban_list=results_map["ban_list"], error_list=results_map["error_list"]
- )
- await evt.respond(results, allow_html=True, edits=msg)
+ results = "the following users were kicked and banned:{ban_list}
the following errors were \
+ recorded:{error_list}
".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()
+ # 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"
@@ -1143,45 +1143,45 @@ class CommunityBot(Plugin):
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 = {}
+ 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"]
+ 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)
+ 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:{unban_list}
the following errors were \
- recorded:{error_list}
".format(
- unban_list=unban_list, error_list=error_list
- )
- await evt.respond(results, allow_html=True, edits=msg)
+ results = "the following users were unbanned:{unban_list}
the following errors were \
+ recorded:{error_list}
".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()
+ # sync our database after we've made changes to room memberships
+ await self.do_sync()
@community.subcommand(
"redact",