mirror of https://gitlab.com/litecord/litecord.git
blueprints.guilds: add 2 role endpoints
Add PATCH /api/v6/guilds/:id/roles for multiple position changes for roles and PATCH /api/v6/guilds/:id/roles/:id for single guild role changes - permissions: add int maigc method - schemas: add ROLE_UPDATE and ROLE_UPDATE_POSITION
This commit is contained in:
parent
956498ac65
commit
86705b0645
|
|
@ -4,7 +4,10 @@ from ..auth import token_check
|
|||
from ..snowflake import get_snowflake
|
||||
from ..enums import ChannelType
|
||||
from ..errors import Forbidden, GuildNotFound, BadRequest
|
||||
from ..schemas import validate, GUILD_CREATE, GUILD_UPDATE, ROLE_CREATE
|
||||
from ..schemas import (
|
||||
validate, GUILD_CREATE, GUILD_UPDATE, ROLE_CREATE, ROLE_UPDATE,
|
||||
ROLE_UPDATE_POSITION
|
||||
)
|
||||
from ..utils import dict_get
|
||||
from .channels import channel_ack
|
||||
from .checks import guild_check
|
||||
|
|
@ -88,8 +91,8 @@ async def create_role(guild_id, name: str, **kwargs):
|
|||
# set position = 0 when there isn't any
|
||||
# other role (when we're creating the
|
||||
# @everyone role)
|
||||
max_pos + 1 if max_pos else 0,
|
||||
dict_get(kwargs, 'permissions', default_perms),
|
||||
max_pos + 1 if max_pos is not None else 0,
|
||||
int(dict_get(kwargs, 'permissions', default_perms)),
|
||||
False,
|
||||
dict_get(kwargs, 'mentionable', False)
|
||||
)
|
||||
|
|
@ -397,6 +400,150 @@ async def create_guild_role(guild_id: int):
|
|||
return jsonify(role)
|
||||
|
||||
|
||||
async def _role_update_dispatch(role_id: int, guild_id: int):
|
||||
"""Dispatch a GUILD_ROLE_UPDATE with updated information on a role."""
|
||||
role = await app.storage.get_role(role_id, guild_id)
|
||||
|
||||
await app.dispatcher.dispatch_guild(guild_id, 'GUILD_ROLE_UPDATE', {
|
||||
'guild_id': str(guild_id),
|
||||
'role': role,
|
||||
})
|
||||
|
||||
return role
|
||||
|
||||
|
||||
async def _role_pairs_update(guild_id: int, pairs: list):
|
||||
"""Update the roles' positions.
|
||||
|
||||
Dispatches GUILD_ROLE_UPDATE for all roles being updated.
|
||||
"""
|
||||
for pair in pairs:
|
||||
pair_1, pair_2 = pair
|
||||
|
||||
role_1, new_pos_1 = pair_1
|
||||
role_2, new_pos_2 = pair_2
|
||||
|
||||
conn = await app.db.acquire()
|
||||
async with conn.transaction():
|
||||
# update happens in a transaction
|
||||
# so we don't fuck it up
|
||||
await conn.execute("""
|
||||
UPDATE roles
|
||||
SET position = $1
|
||||
WHERE roles.id = $2
|
||||
""", new_pos_1, role_1)
|
||||
|
||||
await conn.execute("""
|
||||
UPDATE roles
|
||||
SET position = $1
|
||||
WHERE roles.id = $2
|
||||
""", new_pos_2, role_2)
|
||||
|
||||
await app.db.release(conn)
|
||||
|
||||
# the route fires multiple Guild Role Update.
|
||||
await _role_update_dispatch(role_1, guild_id)
|
||||
await _role_update_dispatch(role_2, guild_id)
|
||||
|
||||
|
||||
@bp.route('/<int:guild_id>/roles', methods=['PATCH'])
|
||||
async def update_guild_role_positions(guild_id):
|
||||
"""Update the positions for a bunch of roles."""
|
||||
user_id = await token_check()
|
||||
|
||||
# TODO: check MANAGE_ROLES
|
||||
await guild_owner_check(user_id, guild_id)
|
||||
|
||||
raw_j = await request.get_json()
|
||||
|
||||
# we need to do this hackiness because thats
|
||||
# cerberus for ya.
|
||||
j = validate({'roles': raw_j}, ROLE_UPDATE_POSITION)
|
||||
|
||||
# extract the list out
|
||||
j = j['roles']
|
||||
print(j)
|
||||
|
||||
all_roles = await app.storage.get_role_data(guild_id)
|
||||
|
||||
# we'll have to calculate pairs of changing roles,
|
||||
# then do the changes, etc.
|
||||
roles_pos = {role['position']: int(role['id']) for role in all_roles}
|
||||
new_positions = {role['id']: role['position'] for role in j}
|
||||
|
||||
# always ignore people trying to change the @everyone role
|
||||
# TODO: check if the user can even change the roles in the first place,
|
||||
# preferrably when we have a proper perms system.
|
||||
try:
|
||||
new_positions.pop(guild_id)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
pairs = []
|
||||
|
||||
# we want to find pairs of (role_1, new_position_1)
|
||||
# where new_position_1 is actually pointing to position_2 (for a role 2)
|
||||
# AND we have (role_2, new_position_2) in the list of new_positions.
|
||||
|
||||
# I hope the explanation went through.
|
||||
|
||||
for change in j:
|
||||
role_1, new_pos_1 = change['id'], change['position']
|
||||
|
||||
# check current pairs
|
||||
# so we don't repeat a role
|
||||
flag = False
|
||||
|
||||
for pair in pairs:
|
||||
if (role_1, new_pos_1) in pair:
|
||||
flag = True
|
||||
|
||||
# skip if found
|
||||
if flag:
|
||||
continue
|
||||
|
||||
# find a role that is in that new position
|
||||
role_2 = roles_pos.get(new_pos_1)
|
||||
|
||||
# search role_2 in the new_positions list
|
||||
new_pos_2 = new_positions.get(role_2)
|
||||
|
||||
# if we found it, add it to the pairs array.
|
||||
if new_pos_2:
|
||||
pairs.append(
|
||||
((role_1, new_pos_1), (role_2, new_pos_2))
|
||||
)
|
||||
|
||||
await _role_pairs_update(guild_id, pairs)
|
||||
|
||||
# return the list of all roles back
|
||||
return jsonify(await app.storage.get_role_data(guild_id))
|
||||
|
||||
|
||||
@bp.route('/<int:guild_id>/roles/<int:role_id>', methods=['PATCH'])
|
||||
async def update_guild_role(guild_id, role_id):
|
||||
"""Update a single role's information."""
|
||||
user_id = await token_check()
|
||||
|
||||
# TODO: check MANAGE_ROLES
|
||||
await guild_owner_check(user_id, guild_id)
|
||||
|
||||
j = validate(await request.get_json(), ROLE_UPDATE)
|
||||
|
||||
# we only update ints on the db, not Permissions
|
||||
j['permissions'] = int(j['permissions'])
|
||||
|
||||
for field in j:
|
||||
await app.db.execute(f"""
|
||||
UPDATE roles
|
||||
SET {field} = $1
|
||||
WHERE roles.id = $2 AND roles.guild_id = $3
|
||||
""", j[field], role_id, guild_id)
|
||||
|
||||
role = await _role_update_dispatch(role_id, guild_id)
|
||||
return jsonify(role)
|
||||
|
||||
|
||||
@bp.route('/<int:guild_id>/members/<int:member_id>', methods=['GET'])
|
||||
async def get_guild_member(guild_id, member_id):
|
||||
"""Get a member's information in a guild."""
|
||||
|
|
|
|||
|
|
@ -50,5 +50,8 @@ class Permissions(ctypes.Union):
|
|||
def __init__(self, val: int):
|
||||
self.binary = val
|
||||
|
||||
def __int__(self):
|
||||
return self.binary
|
||||
|
||||
def numby(self):
|
||||
return self.binary
|
||||
|
|
|
|||
|
|
@ -259,6 +259,28 @@ ROLE_CREATE = {
|
|||
'mentionable': {'type': 'boolean', 'default': False},
|
||||
}
|
||||
|
||||
ROLE_UPDATE = {
|
||||
'name': {'type': 'string', 'required': False},
|
||||
'permissions': {'coerce': Permissions, 'required': False},
|
||||
'color': {'coerce': Color, 'required': False},
|
||||
'hoist': {'type': 'boolean', 'required': False},
|
||||
'mentionable': {'type': 'boolean', 'required': False},
|
||||
}
|
||||
|
||||
|
||||
ROLE_UPDATE_POSITION = {
|
||||
'roles': {
|
||||
'type': 'list',
|
||||
'schema': {
|
||||
'type': 'dict',
|
||||
'schema': {
|
||||
'id': {'coerce': int},
|
||||
'position': {'coerce': int},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MEMBER_UPDATE = {
|
||||
'nick': {
|
||||
|
|
|
|||
Loading…
Reference in New Issue