Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add TeamMember.role #1094

Merged
merged 13 commits into from
Nov 17, 2023
1 change: 1 addition & 0 deletions changelog/1094.doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add inherited attributes to :class:`TeamMember`, and fix :attr:`TeamMember.avatar` documentation.
1 change: 1 addition & 0 deletions changelog/1094.feature.0.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add :attr:`TeamMember.role`.
1 change: 1 addition & 0 deletions changelog/1094.feature.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
|commands| Update :meth:`Bot.is_owner <ext.commands.Bot.is_owner>` to take team member roles into account.
10 changes: 10 additions & 0 deletions disnake/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"ActivityType",
"NotificationLevel",
"TeamMembershipState",
"TeamMemberRole",
"WebhookType",
"ExpireBehaviour",
"ExpireBehavior",
Expand Down Expand Up @@ -551,6 +552,15 @@ class TeamMembershipState(Enum):
accepted = 2


class TeamMemberRole(Enum):
admin = "admin"
developer = "developer"
read_only = "read_only"

def __str__(self) -> str:
return self.name


class WebhookType(Enum):
incoming = 1
channel_follower = 2
Expand Down
4 changes: 2 additions & 2 deletions disnake/ext/commands/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class Bot(BotBase, InteractionBotBase, disnake.Client):
owner_ids: Optional[Collection[:class:`int`]]
The IDs of the users that own the bot. This is similar to :attr:`owner_id`.
If this is not set and the application is team based, then it is
fetched automatically using :meth:`~.Bot.application_info`.
fetched automatically using :meth:`~.Bot.application_info` (taking team roles into account).
For performance reasons it is recommended to use a :class:`set`
for the collection. You cannot set both ``owner_id`` and ``owner_ids``.

Expand Down Expand Up @@ -403,7 +403,7 @@ class InteractionBot(InteractionBotBase, disnake.Client):
owner_ids: Optional[Collection[:class:`int`]]
The IDs of the users that own the bot. This is similar to :attr:`owner_id`.
If this is not set and the application is team based, then it is
fetched automatically using :meth:`~.Bot.application_info`.
fetched automatically using :meth:`~.Bot.application_info` (taking team roles into account).
For performance reasons it is recommended to use a :class:`set`
for the collection. You cannot set both ``owner_id`` and ``owner_ids``.

Expand Down
13 changes: 11 additions & 2 deletions disnake/ext/commands/common_bot_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,13 @@ async def _fill_owners(self) -> None:

app: disnake.AppInfo = await self.application_info() # type: ignore
if app.team:
self.owners = set(app.team.members)
self.owner_ids = {m.id for m in app.team.members}
self.owners = owners = {
member
for member in app.team.members
# these roles can access the bot token, consider them bot owners
if member.role in (disnake.TeamMemberRole.admin, disnake.TeamMemberRole.developer)
}
self.owner_ids = {m.id for m in owners}
else:
self.owner = app.owner
self.owner_id = app.owner.id
Expand Down Expand Up @@ -130,6 +135,10 @@ async def is_owner(self, user: Union[disnake.User, disnake.Member]) -> bool:
The function also checks if the application is team-owned if
:attr:`owner_ids` is not set.

.. versionchanged:: 2.10
Also takes team roles into account; only team members with the :attr:`~disnake.TeamMemberRole.admin`
or :attr:`~disnake.TeamMemberRole.developer` roles are considered bot owners.

Parameters
----------
user: :class:`.abc.User`
Expand Down
23 changes: 11 additions & 12 deletions disnake/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from . import utils
from .asset import Asset
from .enums import TeamMembershipState, try_enum
from .enums import TeamMemberRole, TeamMembershipState, try_enum
from .user import BaseUser

if TYPE_CHECKING:
Expand All @@ -21,7 +21,8 @@


class Team:
"""Represents an application team for a bot provided by Discord.
"""Represents an application team.
Teams are groups of users who share access to an application's configuration.

Attributes
----------
Expand All @@ -30,7 +31,7 @@ class Team:
name: :class:`str`
The team name.
owner_id: :class:`int`
The team's owner ID.
The team owner's ID.
members: List[:class:`TeamMember`]
A list of the members in the team.

Expand All @@ -44,7 +45,7 @@ def __init__(self, state: ConnectionState, data: TeamPayload) -> None:

self.id: int = int(data["id"])
self.name: str = data["name"]
self._icon: Optional[str] = data["icon"]
self._icon: Optional[str] = data.get("icon")
self.owner_id: Optional[int] = utils._get_as_snowflake(data, "owner_user_id")
self.members: List[TeamMember] = [
TeamMember(self, self._state, member) for member in data["members"]
Expand Down Expand Up @@ -113,29 +114,27 @@ class TeamMember(BaseUser):
See the `help article <https://dis.gd/app-usernames>`__ for details.

global_name: Optional[:class:`str`]
The team members's global display name, if set.
The team member's global display name, if set.
This takes precedence over :attr:`.name` when shown.

.. versionadded:: 2.9

avatar: Optional[:class:`str`]
The avatar hash the team member has. Could be None.
bot: :class:`bool`
Specifies if the user is a bot account.
team: :class:`Team`
The team that the member is from.
membership_state: :class:`TeamMembershipState`
The membership state of the member (e.g. invited or accepted)
The membership state of the member (e.g. invited or accepted).
role: :class:`TeamMemberRole`
The role of the team member in the team.
"""

__slots__ = ("team", "membership_state", "permissions")
__slots__ = ("team", "membership_state", "role")

def __init__(self, team: Team, state: ConnectionState, data: TeamMemberPayload) -> None:
self.team: Team = team
self.membership_state: TeamMembershipState = try_enum(
TeamMembershipState, data["membership_state"]
)
self.permissions: List[str] = data["permissions"]
self.role: TeamMemberRole = try_enum(TeamMemberRole, data.get("role"))
super().__init__(state=state, data=data["user"])

def __repr__(self) -> str:
Expand Down
5 changes: 3 additions & 2 deletions disnake/types/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
from .user import PartialUser

TeamMembershipState = Literal[1, 2]
TeamMemberRole = Literal["admin", "developer", "read_only"]


class TeamMember(TypedDict):
user: PartialUser
membership_state: TeamMembershipState
permissions: List[str]
team_id: Snowflake
user: PartialUser
role: TeamMemberRole


class Team(TypedDict):
Expand Down
22 changes: 22 additions & 0 deletions docs/api/app_info.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ TeamMember

.. autoclass:: TeamMember()
:members:
:inherited-members:

Data Classes
------------
Expand Down Expand Up @@ -89,6 +90,27 @@ TeamMembershipState

Represents a member currently in the team.

TeamMemberRole
~~~~~~~~~~~~~~

.. class:: TeamMemberRole

Represents the role of a team member retrieved through :func:`Client.application_info`.

.. versionadded:: 2.10

.. attribute:: admin

Admins have the most permissions. An admin can only take destructive actions on the team or team-owned apps if they are the team owner.

.. attribute:: developer

Developers can access information about a team and team-owned applications, and take limited actions on them, like configuring interaction endpoints or resetting the bot token.

.. attribute:: read_only

Read-only members can access information about a team and team-owned applications.

ApplicationRoleConnectionMetadataType
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down