Skip to content

Commit 8edf433

Browse files
LeoCx1000Rapptz
andauthored
Implement rich role.move interface
Co-authored-by: Danny <[email protected]>
1 parent 4c3ce8f commit 8edf433

File tree

1 file changed

+107
-1
lines changed

1 file changed

+107
-1
lines changed

discord/role.py

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"""
2424

2525
from __future__ import annotations
26-
from typing import Any, Dict, List, Optional, Union, TYPE_CHECKING
26+
from typing import Any, Dict, List, Optional, Union, overload, TYPE_CHECKING
2727

2828
from .asset import Asset
2929
from .permissions import Permissions
@@ -522,6 +522,112 @@ async def edit(
522522
data = await self._state.http.edit_role(self.guild.id, self.id, reason=reason, **payload)
523523
return Role(guild=self.guild, data=data, state=self._state)
524524

525+
@overload
526+
async def move(self, *, beginning: bool, offset: int = ..., reason: Optional[str] = ...):
527+
...
528+
529+
@overload
530+
async def move(self, *, end: bool, offset: int = ..., reason: Optional[str] = ...):
531+
...
532+
533+
@overload
534+
async def move(self, *, above: Role, offset: int = ..., reason: Optional[str] = ...):
535+
...
536+
537+
@overload
538+
async def move(self, *, below: Role, offset: int = ..., reason: Optional[str] = ...):
539+
...
540+
541+
async def move(
542+
self,
543+
*,
544+
beginning: bool = MISSING,
545+
end: bool = MISSING,
546+
above: Role = MISSING,
547+
below: Role = MISSING,
548+
offset: int = 0,
549+
reason: Optional[str] = None,
550+
):
551+
"""|coro|
552+
553+
A rich interface to help move a role relative to other roles.
554+
555+
You must have :attr:`~discord.Permissions.manage_roles` to do this,
556+
and you cannot move roles above the client's top role in the guild.
557+
558+
.. versionadded:: 2.5
559+
560+
Parameters
561+
-----------
562+
beginning: :class:`bool`
563+
Whether to move this at the beginning of the role list, above the default role.
564+
This is mutually exclusive with `end`, `above`, and `below`.
565+
end: :class:`bool`
566+
Whether to move this at the end of the role list.
567+
This is mutually exclusive with `beginning`, `above`, and `below`.
568+
above: :class:`Role`
569+
The role that should be above our current role.
570+
This mutually exclusive with `beginning`, `end`, and `below`.
571+
below: :class:`Role`
572+
The role that should be below our current role.
573+
This mutually exclusive with `beginning`, `end`, and `above`.
574+
offset: :class:`int`
575+
The number of roles to offset the move by. For example,
576+
an offset of ``2`` with ``beginning=True`` would move
577+
it 2 above the beginning. A positive number moves it above
578+
while a negative number moves it below. Note that this
579+
number is relative and computed after the ``beginning``,
580+
``end``, ``before``, and ``after`` parameters.
581+
reason: Optional[:class:`str`]
582+
The reason for editing this role. Shows up on the audit log.
583+
584+
Raises
585+
-------
586+
Forbidden
587+
You cannot move the role there, or lack permissions to do so.
588+
HTTPException
589+
Moving the role failed.
590+
TypeError
591+
A bad mix of arguments were passed.
592+
ValueError
593+
An invalid role was passed.
594+
595+
Returns
596+
--------
597+
List[:class:`Role`]
598+
A list of all the roles in the guild.
599+
"""
600+
if sum(bool(a) for a in (beginning, end, above, below)) > 1:
601+
raise TypeError('Only one of [beginning, end, above, below] can be used.')
602+
603+
target = above or below
604+
guild = self.guild
605+
guild_roles = guild.roles
606+
607+
if target:
608+
if target not in guild_roles:
609+
raise ValueError('Target role is from a different guild')
610+
if above == guild.default_role:
611+
raise ValueError('Role cannot be moved below the default role')
612+
if self == target:
613+
raise ValueError('Target role cannot be itself')
614+
615+
roles = [r for r in guild_roles if r != self]
616+
if beginning:
617+
index = 1
618+
elif end:
619+
index = len(roles)
620+
elif above in roles:
621+
index = roles.index(above)
622+
elif below in roles:
623+
index = roles.index(below) + 1
624+
else:
625+
index = guild_roles.index(self)
626+
roles.insert(max((index + offset), 1), self)
627+
628+
payload: List[RolePositionUpdate] = [{'id': role.id, 'position': idx} for idx, role in enumerate(roles)]
629+
await self._state.http.move_role_position(guild.id, payload, reason=reason)
630+
525631
async def delete(self, *, reason: Optional[str] = None) -> None:
526632
"""|coro|
527633

0 commit comments

Comments
 (0)