From ce5b75921a7c83ba96b8b33b5e6eb11ca39b9145 Mon Sep 17 00:00:00 2001 From: Luna Mendes Date: Sat, 27 Oct 2018 21:50:15 -0300 Subject: [PATCH] members: add role change impl - lazy_guild: add to online/offline groups when role isnt hoisted - schemas: fix MEMBER_UPDATE.nick --- litecord/blueprints/guild/members.py | 63 +++++++++++++++++++++++++++- litecord/pubsub/lazy_guild.py | 5 ++- litecord/schemas.py | 2 +- litecord/storage.py | 4 +- 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/litecord/blueprints/guild/members.py b/litecord/blueprints/guild/members.py index 6fd2ad2..8d90435 100644 --- a/litecord/blueprints/guild/members.py +++ b/litecord/blueprints/guild/members.py @@ -3,6 +3,10 @@ from quart import Blueprint, request, current_app as app, jsonify from litecord.blueprints.auth import token_check from litecord.blueprints.checks import guild_check from litecord.errors import BadRequest +from litecord.schemas import ( + validate, MEMBER_UPDATE +) +from litecord.blueprints.checks import guild_owner_check bp = Blueprint('guild_members', __name__) @@ -42,10 +46,61 @@ async def get_members(guild_id): return jsonify(members) +async def _update_member_roles(guild_id: int, member_id: int, + wanted_roles: list): + """Update the roles a member has.""" + + # first, fetch all current roles + roles = await app.db.fetch(""" + SELECT role_id from member_roles + WHERE guild_id = $1 AND user_id = $2 + """, guild_id, member_id) + + roles = [r['role_id'] for r in roles] + + roles = set(roles) + wanted_roles = set(wanted_roles) + + # first, we need to find all added roles: + # roles that are on wanted_roles but + # not on roles + added_roles = wanted_roles - roles + + # and then the removed roles + # which are roles in roles, but not + # in wanted_roles + removed_roles = roles - wanted_roles + + conn = await app.db.acquire() + + async with conn.transaction(): + # add roles + await app.db.executemany(""" + INSERT INTO member_roles (user_id, guild_id, role_id) + VALUES ($1, $2, $3) + """, [(member_id, guild_id, role_id) + for role_id in added_roles]) + + # remove roles + await app.db.executemany(""" + DELETE FROM member_roles + WHERE + user_id = $1 + AND guild_id = $2 + AND role_id = $3 + """, [(member_id, guild_id, role_id) + for role_id in removed_roles]) + + await app.db.release(conn) + + @bp.route('//members/', methods=['PATCH']) async def modify_guild_member(guild_id, member_id): """Modify a members' information in a guild.""" - j = await request.get_json() + user_id = await token_check() + await guild_owner_check(user_id, guild_id) + + j = validate(await request.get_json(), MEMBER_UPDATE) if 'nick' in j: # TODO: check MANAGE_NICKNAMES @@ -75,10 +130,14 @@ async def modify_guild_member(guild_id, member_id): """, j['deaf'], member_id, guild_id) if 'channel_id' in j: - # TODO: check MOVE_MEMBERS + # TODO: check MOVE_MEMBERS and CONNECT to the channel # TODO: change the member's voice channel pass + if 'roles' in j: + # TODO: check permissions + await _update_member_roles(guild_id, member_id, j['roles']) + member = await app.storage.get_member_data_one(guild_id, member_id) member.pop('joined_at') diff --git a/litecord/pubsub/lazy_guild.py b/litecord/pubsub/lazy_guild.py index 0bcf1f5..d010f78 100644 --- a/litecord/pubsub/lazy_guild.py +++ b/litecord/pubsub/lazy_guild.py @@ -151,7 +151,10 @@ class GuildMemberList: # this user has a best_role that isn't the # @everyone role, so we'll put them in the respective group - group_data[best_role_id].append(presence) + try: + group_data[best_role_id].append(presence) + except KeyError: + group_data[simple_group].append(presence) # go through each group and sort the resulting members by display name diff --git a/litecord/schemas.py b/litecord/schemas.py index 77147ab..822e7b6 100644 --- a/litecord/schemas.py +++ b/litecord/schemas.py @@ -284,7 +284,7 @@ ROLE_UPDATE_POSITION = { MEMBER_UPDATE = { 'nick': { - 'type': 'nickname', + 'type': 'username', 'minlength': 1, 'maxlength': 100, 'required': False, }, diff --git a/litecord/storage.py b/litecord/storage.py index 7337e54..0c141b3 100644 --- a/litecord/storage.py +++ b/litecord/storage.py @@ -164,7 +164,7 @@ class Storage: """, guild_id, member_id) async def _member_dict(self, row, guild_id, member_id) -> Dict[str, Any]: - members_roles = await self.db.fetch(""" + roles = await self.db.fetch(""" SELECT role_id::text FROM member_roles WHERE guild_id = $1 AND user_id = $2 @@ -173,7 +173,7 @@ class Storage: return { 'user': await self.get_user(member_id), 'nick': row['nickname'], - 'roles': [row[0] for row in members_roles], + 'roles': [r['role_id'] for r in roles], 'joined_at': row['joined_at'].isoformat(), 'deaf': row['deafened'], 'mute': row['muted'],