power level management
apply admin and mod power levels across all rooms managed by the bot readme updates for readability
This commit is contained in:
@@ -50,12 +50,24 @@ need to rejoin all rooms themselves or be re-invited.
|
|||||||
use the `guests` subcommand to see who is in a room but NOT a member of the parent space (invited guests) e.g.
|
use the `guests` subcommand to see who is in a room but NOT a member of the parent space (invited guests) e.g.
|
||||||
`!community guests #myroom:alias.here`.
|
`!community guests #myroom:alias.here`.
|
||||||
|
|
||||||
|
## admin/moderator management
|
||||||
|
|
||||||
|
set consistent power levels across all your rooms for your community administrators! the config defines a list of both
|
||||||
|
admins and moderators (admins have a Power Level of 100, mods have PL50). running the setpower subcommand (i.e.
|
||||||
|
`!community setpower`) will roll through all rooms in the space (including the space itself) and attempt to true-up user
|
||||||
|
permissions to match. if you are running legacy rooms not managed by the bot, and the bot does not have permission to
|
||||||
|
send power-level state events to the room, it will return a list for you to handle manually. users who have a PL greater
|
||||||
|
than 0 and are not listed as either an admin or moderator will be removed from the permission list, effectively
|
||||||
|
returning their power to whatever the room default is (usually 0).
|
||||||
|
|
||||||
## room creation
|
## room creation
|
||||||
|
|
||||||
use the `createroom` subcommand to create a new room according to your preferences, and join it into the parent space.
|
use the `createroom` subcommand to create a new room according to your preferences, and join it into the parent space.
|
||||||
will attempt to sanitize the room name and assign a room alias automatically. the bot user will be assigned very high
|
will attempt to sanitize the room name and assign a room alias automatically. the bot user will be assigned very high
|
||||||
power level (1000) and set an admin power level (100) to plugin administrators. this ensures that the bot is still able
|
power level (1000) and set an admin power level (100) to plugin administrators, 50 to moderators. this ensures that the
|
||||||
to manage room admins. the bot will also invite other users to these new rooms as configured.
|
bot is still able to manage room admins. the bot will also invite other users to these new rooms as configured.
|
||||||
|
|
||||||
|
rooms created by the bot will have join restriction limited to members of the space.
|
||||||
|
|
||||||
## get room ID
|
## get room ID
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -19,12 +19,16 @@ track_messages: True
|
|||||||
# will update the user's last-active date when they add a reaction to a message
|
# will update the user's last-active date when they add a reaction to a message
|
||||||
track_reactions: True
|
track_reactions: True
|
||||||
|
|
||||||
# list of users who can use administrative commands, these users will also be made room admins (PL100)
|
# list of users who can use administrative commands. these users will also be made room admins (PL100)
|
||||||
# in new rooms created with the create room commands
|
|
||||||
admins:
|
admins:
|
||||||
- '@user1:server.tld'
|
- '@user1:server.tld'
|
||||||
- '@user2:server.tld'
|
- '@user2:server.tld'
|
||||||
|
|
||||||
|
# list of users who should be considered community moderators. these users will be made room mods (PL50)
|
||||||
|
moderators:
|
||||||
|
- '@user3:server.tld'
|
||||||
|
- '@user4:server.tld'
|
||||||
|
|
||||||
# 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 perhaps)
|
||||||
invitees:
|
invitees:
|
||||||
- "@mybot:server.tld"
|
- "@mybot:server.tld"
|
||||||
|
|||||||
+72
-1
@@ -8,7 +8,7 @@ import re
|
|||||||
from mautrix.client import Client, InternalEventType, MembershipEventDispatcher, SyncStream
|
from mautrix.client import Client, InternalEventType, MembershipEventDispatcher, SyncStream
|
||||||
from mautrix.types import (Event, StateEvent, EventID, UserID, FileInfo, EventType,
|
from mautrix.types import (Event, StateEvent, EventID, UserID, FileInfo, EventType,
|
||||||
MediaMessageEventContent, ReactionEvent, RedactionEvent, RoomID,
|
MediaMessageEventContent, ReactionEvent, RedactionEvent, RoomID,
|
||||||
RoomAlias)
|
RoomAlias, PowerLevelStateEventContent)
|
||||||
from mautrix.errors import MNotFound
|
from mautrix.errors import MNotFound
|
||||||
from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper
|
from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper
|
||||||
from maubot import Plugin, MessageEvent
|
from maubot import Plugin, MessageEvent
|
||||||
@@ -22,6 +22,7 @@ from .db import upgrade_table
|
|||||||
class Config(BaseProxyConfig):
|
class Config(BaseProxyConfig):
|
||||||
def do_update(self, helper: ConfigUpdateHelper) -> None:
|
def do_update(self, helper: ConfigUpdateHelper) -> None:
|
||||||
helper.copy("admins")
|
helper.copy("admins")
|
||||||
|
helper.copy("moderators")
|
||||||
helper.copy("parent_room")
|
helper.copy("parent_room")
|
||||||
helper.copy("track_messages")
|
helper.copy("track_messages")
|
||||||
helper.copy("track_reactions")
|
helper.copy("track_reactions")
|
||||||
@@ -421,6 +422,8 @@ class CommunityBot(Plugin):
|
|||||||
pl_override = {"users": {self.client.mxid: 1000}}
|
pl_override = {"users": {self.client.mxid: 1000}}
|
||||||
for u in self.config['admins']:
|
for u in self.config['admins']:
|
||||||
pl_override["users"][u] = 100
|
pl_override["users"][u] = 100
|
||||||
|
for u in self.config['moderators']:
|
||||||
|
pl_override["users"][u] = 50
|
||||||
pl_json = json.dumps(pl_override)
|
pl_json = json.dumps(pl_override)
|
||||||
|
|
||||||
mymsg = await evt.respond(f"creating {sanitized_name}, give me a minute...")
|
mymsg = await evt.respond(f"creating {sanitized_name}, give me a minute...")
|
||||||
@@ -510,6 +513,74 @@ class CommunityBot(Plugin):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
await evt.respond(f"something went wrong: {e}")
|
await evt.respond(f"something went wrong: {e}")
|
||||||
|
|
||||||
|
@community.subcommand("setpower", help="set power levels according to the community configuration")
|
||||||
|
async def set_powerlevels(self, evt: MessageEvent,) -> None:
|
||||||
|
await evt.mark_read()
|
||||||
|
if evt.sender in self.config["admins"]:
|
||||||
|
msg = await evt.respond("truing up power levels, this could take a minute...")
|
||||||
|
admins = self.config['admins']
|
||||||
|
moderators = self.config['moderators']
|
||||||
|
roomlist = await self.get_space_roomlist()
|
||||||
|
# don't forget to include the space itself
|
||||||
|
roomlist.append(self.config["parent_room"])
|
||||||
|
success_list = []
|
||||||
|
error_list = []
|
||||||
|
adminpl = 100
|
||||||
|
modpl = 50
|
||||||
|
defaultpl = 0
|
||||||
|
|
||||||
|
for room in roomlist:
|
||||||
|
# need to get and evaluate the current state that contains powerlevels first
|
||||||
|
current_pl = await self.client.get_state_event(room, 'm.room.power_levels')
|
||||||
|
users = current_pl['users'].serialize()
|
||||||
|
updated_user_map = dict(users)
|
||||||
|
try:
|
||||||
|
roomname = None
|
||||||
|
roomnamestate = await self.client.get_state_event(room, 'm.room.name')
|
||||||
|
roomname = roomnamestate['name']
|
||||||
|
except Exception as e:
|
||||||
|
self.log.warning(e)
|
||||||
|
|
||||||
|
# update our powerlevel map values
|
||||||
|
for user in admins:
|
||||||
|
updated_user_map[user] = adminpl
|
||||||
|
for user in moderators:
|
||||||
|
updated_user_map[user] = modpl
|
||||||
|
|
||||||
|
# revoke values for people no longer in the config
|
||||||
|
for user in users.keys():
|
||||||
|
if ( user not in admins and
|
||||||
|
user not in moderators and
|
||||||
|
updated_user_map[user] > defaultpl and
|
||||||
|
user != self.client.mxid ):
|
||||||
|
del updated_user_map[user]
|
||||||
|
|
||||||
|
|
||||||
|
# and send the new state event back to the room
|
||||||
|
new_pl = current_pl
|
||||||
|
new_pl['users'] = updated_user_map
|
||||||
|
try:
|
||||||
|
self.log.debug(f"DEBUG sending finalized PL map to room {room}: {updated_user_map}")
|
||||||
|
await self.client.send_state_event(room, 'm.room.power_levels', new_pl)
|
||||||
|
success_list.append(roomname or room)
|
||||||
|
except Exception as e:
|
||||||
|
self.log.warning(e)
|
||||||
|
error_list.append(roomname or room)
|
||||||
|
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
results = "the following rooms were updated:<p><code>{success_list}</code></p>the following errors were \
|
||||||
|
recorded:<p><code>{error_list}</code></p>".format(success_list=success_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()
|
||||||
|
|
||||||
|
else:
|
||||||
|
await evt.reply("lol you don't have permission to do that")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_db_upgrade_table(cls) -> None:
|
def get_db_upgrade_table(cls) -> None:
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
maubot: 0.1.0
|
maubot: 0.1.0
|
||||||
id: org.jobmachine.communitybot
|
id: org.jobmachine.communitybot
|
||||||
version: 0.1.3
|
version: 0.1.4
|
||||||
license: MIT
|
license: MIT
|
||||||
modules:
|
modules:
|
||||||
- community
|
- community
|
||||||
|
|||||||
Reference in New Issue
Block a user