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 ..snowflake import get_snowflake
|
||||||
from ..enums import ChannelType
|
from ..enums import ChannelType
|
||||||
from ..errors import Forbidden, GuildNotFound, BadRequest
|
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 ..utils import dict_get
|
||||||
from .channels import channel_ack
|
from .channels import channel_ack
|
||||||
from .checks import guild_check
|
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
|
# set position = 0 when there isn't any
|
||||||
# other role (when we're creating the
|
# other role (when we're creating the
|
||||||
# @everyone role)
|
# @everyone role)
|
||||||
max_pos + 1 if max_pos else 0,
|
max_pos + 1 if max_pos is not None else 0,
|
||||||
dict_get(kwargs, 'permissions', default_perms),
|
int(dict_get(kwargs, 'permissions', default_perms)),
|
||||||
False,
|
False,
|
||||||
dict_get(kwargs, 'mentionable', False)
|
dict_get(kwargs, 'mentionable', False)
|
||||||
)
|
)
|
||||||
|
|
@ -397,6 +400,150 @@ async def create_guild_role(guild_id: int):
|
||||||
return jsonify(role)
|
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'])
|
@bp.route('/<int:guild_id>/members/<int:member_id>', methods=['GET'])
|
||||||
async def get_guild_member(guild_id, member_id):
|
async def get_guild_member(guild_id, member_id):
|
||||||
"""Get a member's information in a guild."""
|
"""Get a member's information in a guild."""
|
||||||
|
|
|
||||||
|
|
@ -50,5 +50,8 @@ class Permissions(ctypes.Union):
|
||||||
def __init__(self, val: int):
|
def __init__(self, val: int):
|
||||||
self.binary = val
|
self.binary = val
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self.binary
|
||||||
|
|
||||||
def numby(self):
|
def numby(self):
|
||||||
return self.binary
|
return self.binary
|
||||||
|
|
|
||||||
|
|
@ -259,6 +259,28 @@ ROLE_CREATE = {
|
||||||
'mentionable': {'type': 'boolean', 'default': False},
|
'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 = {
|
MEMBER_UPDATE = {
|
||||||
'nick': {
|
'nick': {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue