mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-05-15 18:29:52 +00:00
Add application command permissions to audit log
This commit is contained in:
parent
5f0cf58b2e
commit
619bc50e5d
@ -39,6 +39,7 @@ __all__ = (
|
|||||||
'AppCommandThread',
|
'AppCommandThread',
|
||||||
'Argument',
|
'Argument',
|
||||||
'Choice',
|
'Choice',
|
||||||
|
'AllChannels',
|
||||||
)
|
)
|
||||||
|
|
||||||
ChoiceT = TypeVar('ChoiceT', str, int, float, Union[str, int, float])
|
ChoiceT = TypeVar('ChoiceT', str, int, float, Union[str, int, float])
|
||||||
@ -70,6 +71,32 @@ if TYPE_CHECKING:
|
|||||||
ApplicationCommandParent = Union['AppCommand', 'AppCommandGroup']
|
ApplicationCommandParent = Union['AppCommand', 'AppCommandGroup']
|
||||||
|
|
||||||
|
|
||||||
|
class AllChannels:
|
||||||
|
"""Represents all channels for application command permissions.
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
-----------
|
||||||
|
id: :class:`int`
|
||||||
|
The guilds id - 1.
|
||||||
|
guild: :class:`~discord.Guild`
|
||||||
|
The guild the application command permission is for.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = (
|
||||||
|
'id',
|
||||||
|
'guild',
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, guild: Guild):
|
||||||
|
self.id = guild.id - 1
|
||||||
|
self.guild = guild
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'<All Channels guild={self.guild}>'
|
||||||
|
|
||||||
|
|
||||||
class AppCommand(Hashable):
|
class AppCommand(Hashable):
|
||||||
"""Represents a application command.
|
"""Represents a application command.
|
||||||
|
|
||||||
|
@ -61,10 +61,13 @@ if TYPE_CHECKING:
|
|||||||
from .types.invite import Invite as InvitePayload
|
from .types.invite import Invite as InvitePayload
|
||||||
from .types.role import Role as RolePayload
|
from .types.role import Role as RolePayload
|
||||||
from .types.snowflake import Snowflake
|
from .types.snowflake import Snowflake
|
||||||
|
from .types.command import ApplicationCommandPermissions
|
||||||
from .user import User
|
from .user import User
|
||||||
from .stage_instance import StageInstance
|
from .stage_instance import StageInstance
|
||||||
from .sticker import GuildSticker
|
from .sticker import GuildSticker
|
||||||
from .threads import Thread
|
from .threads import Thread
|
||||||
|
from .integrations import PartialIntegration
|
||||||
|
from .app_commands import AppCommand
|
||||||
|
|
||||||
TargetType = Union[
|
TargetType = Union[
|
||||||
Guild, abc.GuildChannel, Member, User, Role, Invite, Emoji, StageInstance, GuildSticker, Thread, Object, None
|
Guild, abc.GuildChannel, Member, User, Role, Invite, Emoji, StageInstance, GuildSticker, Thread, Object, None
|
||||||
@ -253,6 +256,24 @@ class AuditLogChanges:
|
|||||||
self.before: AuditLogDiff = AuditLogDiff()
|
self.before: AuditLogDiff = AuditLogDiff()
|
||||||
self.after: AuditLogDiff = AuditLogDiff()
|
self.after: AuditLogDiff = AuditLogDiff()
|
||||||
|
|
||||||
|
if entry.action is enums.AuditLogAction.app_command_permission_update:
|
||||||
|
# special case entire process since each
|
||||||
|
# element in data is a different target
|
||||||
|
self.before.app_command_permissions = []
|
||||||
|
self.after.app_command_permissions = []
|
||||||
|
|
||||||
|
for d in data:
|
||||||
|
|
||||||
|
self._handle_app_command_permissions(
|
||||||
|
self.before,
|
||||||
|
self.after,
|
||||||
|
entry,
|
||||||
|
int(d['key']),
|
||||||
|
d.get('old_value'), # type: ignore # old value will be an ApplicationCommandPermissions if present
|
||||||
|
d.get('new_value'), # type: ignore # new value will be an ApplicationCommandPermissions if present
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
for elem in data:
|
for elem in data:
|
||||||
attr = elem['key']
|
attr = elem['key']
|
||||||
|
|
||||||
@ -324,6 +345,52 @@ class AuditLogChanges:
|
|||||||
|
|
||||||
setattr(second, 'roles', data)
|
setattr(second, 'roles', data)
|
||||||
|
|
||||||
|
def _handle_app_command_permissions(
|
||||||
|
self,
|
||||||
|
before: AuditLogDiff,
|
||||||
|
after: AuditLogDiff,
|
||||||
|
entry: AuditLogEntry,
|
||||||
|
target_id: int,
|
||||||
|
old_value: Optional[ApplicationCommandPermissions],
|
||||||
|
new_value: Optional[ApplicationCommandPermissions],
|
||||||
|
):
|
||||||
|
guild = entry.guild
|
||||||
|
|
||||||
|
old_permission = new_permission = target = None
|
||||||
|
|
||||||
|
if target_id == (guild.id - 1):
|
||||||
|
# avoid circular import
|
||||||
|
from .app_commands import AllChannels
|
||||||
|
|
||||||
|
# all channels
|
||||||
|
target = AllChannels(guild)
|
||||||
|
else:
|
||||||
|
# get type and determine role, user or channel
|
||||||
|
_value = old_value or new_value
|
||||||
|
if _value is None:
|
||||||
|
return
|
||||||
|
permission_type = _value['type']
|
||||||
|
if permission_type == 1:
|
||||||
|
# role
|
||||||
|
target = guild.get_role(target_id)
|
||||||
|
elif permission_type == 2:
|
||||||
|
# user
|
||||||
|
target = entry._get_member(target_id)
|
||||||
|
elif permission_type == 3:
|
||||||
|
# channel
|
||||||
|
target = guild.get_channel(target_id)
|
||||||
|
|
||||||
|
if target is None:
|
||||||
|
target = Object(target_id)
|
||||||
|
|
||||||
|
if old_value is not None:
|
||||||
|
old_permission = old_value['permission']
|
||||||
|
before.app_command_permissions.append((target, old_permission))
|
||||||
|
|
||||||
|
if new_value is not None:
|
||||||
|
new_permission = new_value['permission']
|
||||||
|
after.app_command_permissions.append((target, new_permission))
|
||||||
|
|
||||||
|
|
||||||
class _AuditLogProxy:
|
class _AuditLogProxy:
|
||||||
def __init__(self, **kwargs: Any) -> None:
|
def __init__(self, **kwargs: Any) -> None:
|
||||||
@ -397,10 +464,20 @@ class AuditLogEntry(Hashable):
|
|||||||
which actions have this field filled out.
|
which actions have this field filled out.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *, users: Dict[int, User], data: AuditLogEntryPayload, guild: Guild):
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
users: Dict[int, User],
|
||||||
|
integrations: Dict[int, PartialIntegration],
|
||||||
|
app_commands: Dict[int, AppCommand],
|
||||||
|
data: AuditLogEntryPayload,
|
||||||
|
guild: Guild,
|
||||||
|
):
|
||||||
self._state: ConnectionState = guild._state
|
self._state: ConnectionState = guild._state
|
||||||
self.guild: Guild = guild
|
self.guild: Guild = guild
|
||||||
self._users: Dict[int, User] = users
|
self._users: Dict[int, User] = users
|
||||||
|
self._integrations: Dict[int, PartialIntegration] = integrations
|
||||||
|
self._app_commands: Dict[int, AppCommand] = app_commands
|
||||||
self._from_data(data)
|
self._from_data(data)
|
||||||
|
|
||||||
def _from_data(self, data: AuditLogEntryPayload) -> None:
|
def _from_data(self, data: AuditLogEntryPayload) -> None:
|
||||||
@ -418,7 +495,7 @@ class AuditLogEntry(Hashable):
|
|||||||
_AuditLogProxyMemberDisconnect,
|
_AuditLogProxyMemberDisconnect,
|
||||||
_AuditLogProxyPinAction,
|
_AuditLogProxyPinAction,
|
||||||
_AuditLogProxyStageInstanceAction,
|
_AuditLogProxyStageInstanceAction,
|
||||||
Member, User, None,
|
Member, User, None, PartialIntegration,
|
||||||
Role, Object
|
Role, Object
|
||||||
] = None
|
] = None
|
||||||
# fmt: on
|
# fmt: on
|
||||||
@ -463,6 +540,9 @@ class AuditLogEntry(Hashable):
|
|||||||
self.extra = _AuditLogProxyStageInstanceAction(
|
self.extra = _AuditLogProxyStageInstanceAction(
|
||||||
channel=self.guild.get_channel(channel_id) or Object(id=channel_id)
|
channel=self.guild.get_channel(channel_id) or Object(id=channel_id)
|
||||||
)
|
)
|
||||||
|
elif self.action.name.startswith('app_command'):
|
||||||
|
application_id = int(extra['application_id'])
|
||||||
|
self.extra = self._get_integration_by_app_id(application_id) or Object(application_id)
|
||||||
|
|
||||||
# this key is not present when the above is present, typically.
|
# this key is not present when the above is present, typically.
|
||||||
# It's a list of { new_value: a, old_value: b, key: c }
|
# It's a list of { new_value: a, old_value: b, key: c }
|
||||||
@ -481,6 +561,25 @@ class AuditLogEntry(Hashable):
|
|||||||
|
|
||||||
return self.guild.get_member(user_id) or self._users.get(user_id)
|
return self.guild.get_member(user_id) or self._users.get(user_id)
|
||||||
|
|
||||||
|
def _get_integration(self, integration_id: Optional[int]) -> Optional[PartialIntegration]:
|
||||||
|
if integration_id is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self._integrations.get(integration_id)
|
||||||
|
|
||||||
|
def _get_integration_by_app_id(self, application_id: Optional[int]) -> Optional[PartialIntegration]:
|
||||||
|
if application_id is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# get PartialIntegration by application id
|
||||||
|
return utils.get(self._integrations.values(), application_id=application_id)
|
||||||
|
|
||||||
|
def _get_app_command(self, app_command_id: Optional[int]) -> Optional[AppCommand]:
|
||||||
|
if app_command_id is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self._app_commands.get(app_command_id)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f'<AuditLogEntry id={self.id} action={self.action} user={self.user!r}>'
|
return f'<AuditLogEntry id={self.id} action={self.action} user={self.user!r}>'
|
||||||
|
|
||||||
@ -575,3 +674,12 @@ class AuditLogEntry(Hashable):
|
|||||||
|
|
||||||
def _convert_target_guild_scheduled_event(self, target_id: int) -> Union[ScheduledEvent, Object]:
|
def _convert_target_guild_scheduled_event(self, target_id: int) -> Union[ScheduledEvent, Object]:
|
||||||
return self.guild.get_scheduled_event(target_id) or Object(id=target_id)
|
return self.guild.get_scheduled_event(target_id) or Object(id=target_id)
|
||||||
|
|
||||||
|
def _convert_target_integration(self, target_id: int) -> Union[PartialIntegration, Object]:
|
||||||
|
return self._get_integration(target_id) or Object(target_id)
|
||||||
|
|
||||||
|
def _convert_target_app_command(self, target_id: int) -> Union[AppCommand, Object]:
|
||||||
|
return self._get_app_command(target_id) or Object(target_id)
|
||||||
|
|
||||||
|
def _convert_target_integration_or_app_command(self, target_id: int) -> Union[PartialIntegration, AppCommand, Object]:
|
||||||
|
return self._get_integration_by_app_id(target_id) or self._get_app_command(target_id) or Object(target_id)
|
||||||
|
192
discord/enums.py
192
discord/enums.py
@ -298,106 +298,108 @@ class AuditLogActionCategory(Enum):
|
|||||||
|
|
||||||
class AuditLogAction(Enum):
|
class AuditLogAction(Enum):
|
||||||
# fmt: off
|
# fmt: off
|
||||||
guild_update = 1
|
guild_update = 1
|
||||||
channel_create = 10
|
channel_create = 10
|
||||||
channel_update = 11
|
channel_update = 11
|
||||||
channel_delete = 12
|
channel_delete = 12
|
||||||
overwrite_create = 13
|
overwrite_create = 13
|
||||||
overwrite_update = 14
|
overwrite_update = 14
|
||||||
overwrite_delete = 15
|
overwrite_delete = 15
|
||||||
kick = 20
|
kick = 20
|
||||||
member_prune = 21
|
member_prune = 21
|
||||||
ban = 22
|
ban = 22
|
||||||
unban = 23
|
unban = 23
|
||||||
member_update = 24
|
member_update = 24
|
||||||
member_role_update = 25
|
member_role_update = 25
|
||||||
member_move = 26
|
member_move = 26
|
||||||
member_disconnect = 27
|
member_disconnect = 27
|
||||||
bot_add = 28
|
bot_add = 28
|
||||||
role_create = 30
|
role_create = 30
|
||||||
role_update = 31
|
role_update = 31
|
||||||
role_delete = 32
|
role_delete = 32
|
||||||
invite_create = 40
|
invite_create = 40
|
||||||
invite_update = 41
|
invite_update = 41
|
||||||
invite_delete = 42
|
invite_delete = 42
|
||||||
webhook_create = 50
|
webhook_create = 50
|
||||||
webhook_update = 51
|
webhook_update = 51
|
||||||
webhook_delete = 52
|
webhook_delete = 52
|
||||||
emoji_create = 60
|
emoji_create = 60
|
||||||
emoji_update = 61
|
emoji_update = 61
|
||||||
emoji_delete = 62
|
emoji_delete = 62
|
||||||
message_delete = 72
|
message_delete = 72
|
||||||
message_bulk_delete = 73
|
message_bulk_delete = 73
|
||||||
message_pin = 74
|
message_pin = 74
|
||||||
message_unpin = 75
|
message_unpin = 75
|
||||||
integration_create = 80
|
integration_create = 80
|
||||||
integration_update = 81
|
integration_update = 81
|
||||||
integration_delete = 82
|
integration_delete = 82
|
||||||
stage_instance_create = 83
|
stage_instance_create = 83
|
||||||
stage_instance_update = 84
|
stage_instance_update = 84
|
||||||
stage_instance_delete = 85
|
stage_instance_delete = 85
|
||||||
sticker_create = 90
|
sticker_create = 90
|
||||||
sticker_update = 91
|
sticker_update = 91
|
||||||
sticker_delete = 92
|
sticker_delete = 92
|
||||||
scheduled_event_create = 100
|
scheduled_event_create = 100
|
||||||
scheduled_event_update = 101
|
scheduled_event_update = 101
|
||||||
scheduled_event_delete = 102
|
scheduled_event_delete = 102
|
||||||
thread_create = 110
|
thread_create = 110
|
||||||
thread_update = 111
|
thread_update = 111
|
||||||
thread_delete = 112
|
thread_delete = 112
|
||||||
|
app_command_permission_update = 121
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def category(self) -> Optional[AuditLogActionCategory]:
|
def category(self) -> Optional[AuditLogActionCategory]:
|
||||||
# fmt: off
|
# fmt: off
|
||||||
lookup: Dict[AuditLogAction, Optional[AuditLogActionCategory]] = {
|
lookup: Dict[AuditLogAction, Optional[AuditLogActionCategory]] = {
|
||||||
AuditLogAction.guild_update: AuditLogActionCategory.update,
|
AuditLogAction.guild_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.channel_create: AuditLogActionCategory.create,
|
AuditLogAction.channel_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.channel_update: AuditLogActionCategory.update,
|
AuditLogAction.channel_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.channel_delete: AuditLogActionCategory.delete,
|
AuditLogAction.channel_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.overwrite_create: AuditLogActionCategory.create,
|
AuditLogAction.overwrite_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.overwrite_update: AuditLogActionCategory.update,
|
AuditLogAction.overwrite_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.overwrite_delete: AuditLogActionCategory.delete,
|
AuditLogAction.overwrite_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.kick: None,
|
AuditLogAction.kick: None,
|
||||||
AuditLogAction.member_prune: None,
|
AuditLogAction.member_prune: None,
|
||||||
AuditLogAction.ban: None,
|
AuditLogAction.ban: None,
|
||||||
AuditLogAction.unban: None,
|
AuditLogAction.unban: None,
|
||||||
AuditLogAction.member_update: AuditLogActionCategory.update,
|
AuditLogAction.member_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.member_role_update: AuditLogActionCategory.update,
|
AuditLogAction.member_role_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.member_move: None,
|
AuditLogAction.member_move: None,
|
||||||
AuditLogAction.member_disconnect: None,
|
AuditLogAction.member_disconnect: None,
|
||||||
AuditLogAction.bot_add: None,
|
AuditLogAction.bot_add: None,
|
||||||
AuditLogAction.role_create: AuditLogActionCategory.create,
|
AuditLogAction.role_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.role_update: AuditLogActionCategory.update,
|
AuditLogAction.role_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.role_delete: AuditLogActionCategory.delete,
|
AuditLogAction.role_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.invite_create: AuditLogActionCategory.create,
|
AuditLogAction.invite_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.invite_update: AuditLogActionCategory.update,
|
AuditLogAction.invite_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.invite_delete: AuditLogActionCategory.delete,
|
AuditLogAction.invite_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.webhook_create: AuditLogActionCategory.create,
|
AuditLogAction.webhook_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.webhook_update: AuditLogActionCategory.update,
|
AuditLogAction.webhook_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.webhook_delete: AuditLogActionCategory.delete,
|
AuditLogAction.webhook_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.emoji_create: AuditLogActionCategory.create,
|
AuditLogAction.emoji_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.emoji_update: AuditLogActionCategory.update,
|
AuditLogAction.emoji_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.emoji_delete: AuditLogActionCategory.delete,
|
AuditLogAction.emoji_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.message_delete: AuditLogActionCategory.delete,
|
AuditLogAction.message_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.message_bulk_delete: AuditLogActionCategory.delete,
|
AuditLogAction.message_bulk_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.message_pin: None,
|
AuditLogAction.message_pin: None,
|
||||||
AuditLogAction.message_unpin: None,
|
AuditLogAction.message_unpin: None,
|
||||||
AuditLogAction.integration_create: AuditLogActionCategory.create,
|
AuditLogAction.integration_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.integration_update: AuditLogActionCategory.update,
|
AuditLogAction.integration_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.integration_delete: AuditLogActionCategory.delete,
|
AuditLogAction.integration_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.stage_instance_create: AuditLogActionCategory.create,
|
AuditLogAction.stage_instance_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.stage_instance_update: AuditLogActionCategory.update,
|
AuditLogAction.stage_instance_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.stage_instance_delete: AuditLogActionCategory.delete,
|
AuditLogAction.stage_instance_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.sticker_create: AuditLogActionCategory.create,
|
AuditLogAction.sticker_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.sticker_update: AuditLogActionCategory.update,
|
AuditLogAction.sticker_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.sticker_delete: AuditLogActionCategory.delete,
|
AuditLogAction.sticker_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.scheduled_event_create: AuditLogActionCategory.create,
|
AuditLogAction.scheduled_event_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.scheduled_event_update: AuditLogActionCategory.update,
|
AuditLogAction.scheduled_event_update: AuditLogActionCategory.update,
|
||||||
AuditLogAction.scheduled_event_delete: AuditLogActionCategory.delete,
|
AuditLogAction.scheduled_event_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.thread_create: AuditLogActionCategory.create,
|
AuditLogAction.thread_create: AuditLogActionCategory.create,
|
||||||
AuditLogAction.thread_update: AuditLogActionCategory.update,
|
AuditLogAction.thread_delete: AuditLogActionCategory.delete,
|
||||||
AuditLogAction.thread_delete: AuditLogActionCategory.delete,
|
AuditLogAction.thread_update: AuditLogActionCategory.update,
|
||||||
|
AuditLogAction.app_command_permission_update: AuditLogActionCategory.update,
|
||||||
}
|
}
|
||||||
# fmt: on
|
# fmt: on
|
||||||
return lookup[self]
|
return lookup[self]
|
||||||
@ -435,6 +437,8 @@ class AuditLogAction(Enum):
|
|||||||
return 'guild_scheduled_event'
|
return 'guild_scheduled_event'
|
||||||
elif v < 113:
|
elif v < 113:
|
||||||
return 'thread'
|
return 'thread'
|
||||||
|
elif v < 122:
|
||||||
|
return 'integration_or_app_command'
|
||||||
|
|
||||||
|
|
||||||
class UserFlags(Enum):
|
class UserFlags(Enum):
|
||||||
|
@ -78,7 +78,7 @@ from .invite import Invite
|
|||||||
from .widget import Widget
|
from .widget import Widget
|
||||||
from .asset import Asset
|
from .asset import Asset
|
||||||
from .flags import SystemChannelFlags
|
from .flags import SystemChannelFlags
|
||||||
from .integrations import Integration, _integration_factory
|
from .integrations import Integration, PartialIntegration, _integration_factory
|
||||||
from .scheduled_event import ScheduledEvent
|
from .scheduled_event import ScheduledEvent
|
||||||
from .stage_instance import StageInstance
|
from .stage_instance import StageInstance
|
||||||
from .threads import Thread, ThreadMember
|
from .threads import Thread, ThreadMember
|
||||||
@ -3346,11 +3346,11 @@ class Guild(Hashable):
|
|||||||
|
|
||||||
if data and entries:
|
if data and entries:
|
||||||
if limit is not None:
|
if limit is not None:
|
||||||
limit -= len(data)
|
limit -= len(entries)
|
||||||
|
|
||||||
before = Object(id=int(entries[-1]['id']))
|
before = Object(id=int(entries[-1]['id']))
|
||||||
|
|
||||||
return data.get('users', []), entries, before, limit
|
return data, entries, after, limit
|
||||||
|
|
||||||
async def _after_strategy(retrieve, after, limit):
|
async def _after_strategy(retrieve, after, limit):
|
||||||
after_id = after.id if after else None
|
after_id = after.id if after else None
|
||||||
@ -3362,11 +3362,11 @@ class Guild(Hashable):
|
|||||||
|
|
||||||
if data and entries:
|
if data and entries:
|
||||||
if limit is not None:
|
if limit is not None:
|
||||||
limit -= len(data)
|
limit -= len(entries)
|
||||||
|
|
||||||
after = Object(id=int(entries[0]['id']))
|
after = Object(id=int(entries[0]['id']))
|
||||||
|
|
||||||
return data.get('users', []), entries, after, limit
|
return data, entries, after, limit
|
||||||
|
|
||||||
if user is not MISSING:
|
if user is not MISSING:
|
||||||
user_id = user.id
|
user_id = user.id
|
||||||
@ -3397,31 +3397,46 @@ class Guild(Hashable):
|
|||||||
if after and after != OLDEST_OBJECT:
|
if after and after != OLDEST_OBJECT:
|
||||||
predicate = lambda m: int(m['id']) > after.id
|
predicate = lambda m: int(m['id']) > after.id
|
||||||
|
|
||||||
|
# avoid circular import
|
||||||
|
from .app_commands import AppCommand
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
retrieve = min(100 if limit is None else limit, 100)
|
retrieve = min(100 if limit is None else limit, 100)
|
||||||
if retrieve < 1:
|
if retrieve < 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
raw_users, data, state, limit = await strategy(retrieve, state, limit)
|
data, raw_entries, state, limit = await strategy(retrieve, state, limit)
|
||||||
|
|
||||||
# Terminate loop on next iteration; there's no data left after this
|
# Terminate loop on next iteration; there's no data left after this
|
||||||
if len(data) < 100:
|
if len(raw_entries) < 100:
|
||||||
limit = 0
|
limit = 0
|
||||||
|
|
||||||
if reverse:
|
if reverse:
|
||||||
data = reversed(data)
|
raw_entries = reversed(raw_entries)
|
||||||
if predicate:
|
if predicate:
|
||||||
data = filter(predicate, data)
|
raw_entries = filter(predicate, raw_entries)
|
||||||
|
|
||||||
users = (User(data=raw_user, state=self._state) for raw_user in raw_users)
|
users = (User(data=raw_user, state=self._state) for raw_user in data.get('users', []))
|
||||||
user_map = {user.id: user for user in users}
|
user_map = {user.id: user for user in users}
|
||||||
|
|
||||||
for raw_entry in data:
|
integrations = (PartialIntegration(data=raw_i, guild=self) for raw_i in data.get('integrations', []))
|
||||||
|
integration_map = {integration.id: integration for integration in integrations}
|
||||||
|
|
||||||
|
app_commands = (AppCommand(data=raw_cmd, state=self._state) for raw_cmd in data.get('application_commands', []))
|
||||||
|
app_command_map = {app_command.id: app_command for app_command in app_commands}
|
||||||
|
|
||||||
|
for raw_entry in raw_entries:
|
||||||
# Weird Discord quirk
|
# Weird Discord quirk
|
||||||
if raw_entry['action_type'] is None:
|
if raw_entry['action_type'] is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
yield AuditLogEntry(data=raw_entry, users=user_map, guild=self)
|
yield AuditLogEntry(
|
||||||
|
data=raw_entry,
|
||||||
|
users=user_map,
|
||||||
|
integrations=integration_map,
|
||||||
|
app_commands=app_command_map,
|
||||||
|
guild=self,
|
||||||
|
)
|
||||||
|
|
||||||
async def widget(self) -> Widget:
|
async def widget(self) -> Widget:
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
@ -36,6 +36,7 @@ __all__ = (
|
|||||||
'Integration',
|
'Integration',
|
||||||
'StreamIntegration',
|
'StreamIntegration',
|
||||||
'BotIntegration',
|
'BotIntegration',
|
||||||
|
'PartialIntegration',
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -49,6 +50,7 @@ if TYPE_CHECKING:
|
|||||||
BotIntegration as BotIntegrationPayload,
|
BotIntegration as BotIntegrationPayload,
|
||||||
IntegrationType,
|
IntegrationType,
|
||||||
IntegrationApplication as IntegrationApplicationPayload,
|
IntegrationApplication as IntegrationApplicationPayload,
|
||||||
|
PartialIntegration as PartialIntegrationPayload,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -115,7 +117,7 @@ class Integration:
|
|||||||
self._from_data(data)
|
self._from_data(data)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"<{self.__class__.__name__} id={self.id} name={self.name!r}>"
|
return f'<{self.__class__.__name__} id={self.id} name={self.name!r}>'
|
||||||
|
|
||||||
def _from_data(self, data: IntegrationPayload) -> None:
|
def _from_data(self, data: IntegrationPayload) -> None:
|
||||||
self.id: int = int(data['id'])
|
self.id: int = int(data['id'])
|
||||||
@ -362,6 +364,53 @@ class BotIntegration(Integration):
|
|||||||
self.application: IntegrationApplication = IntegrationApplication(data=data['application'], state=self._state)
|
self.application: IntegrationApplication = IntegrationApplication(data=data['application'], state=self._state)
|
||||||
|
|
||||||
|
|
||||||
|
class PartialIntegration:
|
||||||
|
"""Represents a partial guild integration.
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
-----------
|
||||||
|
id: :class:`int`
|
||||||
|
The integration ID.
|
||||||
|
name: :class:`str`
|
||||||
|
The integration name.
|
||||||
|
guild: :class:`Guild`
|
||||||
|
The guild of the integration.
|
||||||
|
type: :class:`str`
|
||||||
|
The integration type (i.e. Twitch).
|
||||||
|
account: :class:`IntegrationAccount`
|
||||||
|
The account linked to this integration.
|
||||||
|
application_id: Optional[:class:`int`]
|
||||||
|
The id of the application this integration belongs to.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = (
|
||||||
|
'guild',
|
||||||
|
'_state',
|
||||||
|
'id',
|
||||||
|
'type',
|
||||||
|
'name',
|
||||||
|
'account',
|
||||||
|
'application_id',
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, *, data: PartialIntegrationPayload, guild: Guild):
|
||||||
|
self.guild: Guild = guild
|
||||||
|
self._state: ConnectionState = guild._state
|
||||||
|
self._from_data(data)
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f'<{self.__class__.__name__} id={self.id} name={self.name!r}>'
|
||||||
|
|
||||||
|
def _from_data(self, data: PartialIntegrationPayload) -> None:
|
||||||
|
self.id: int = int(data['id'])
|
||||||
|
self.type: IntegrationType = data['type']
|
||||||
|
self.name: str = data['name']
|
||||||
|
self.account: IntegrationAccount = IntegrationAccount(data['account'])
|
||||||
|
self.application_id: Optional[int] = _get_as_snowflake(data, 'application_id')
|
||||||
|
|
||||||
|
|
||||||
def _integration_factory(value: str) -> Tuple[Type[Integration], str]:
|
def _integration_factory(value: str) -> Tuple[Type[Integration], str]:
|
||||||
if value == 'discord':
|
if value == 'discord':
|
||||||
return BotIntegration, value
|
return BotIntegration, value
|
||||||
|
@ -36,6 +36,7 @@ from .snowflake import Snowflake
|
|||||||
from .role import Role
|
from .role import Role
|
||||||
from .channel import ChannelType, PrivacyLevel, VideoQualityMode, PermissionOverwrite
|
from .channel import ChannelType, PrivacyLevel, VideoQualityMode, PermissionOverwrite
|
||||||
from .threads import Thread
|
from .threads import Thread
|
||||||
|
from .command import ApplicationCommand, ApplicationCommandPermissions
|
||||||
|
|
||||||
AuditLogEvent = Literal[
|
AuditLogEvent = Literal[
|
||||||
1,
|
1,
|
||||||
@ -85,6 +86,7 @@ AuditLogEvent = Literal[
|
|||||||
110,
|
110,
|
||||||
111,
|
111,
|
||||||
112,
|
112,
|
||||||
|
121,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -242,6 +244,12 @@ class _AuditLogChange_EntityType(TypedDict):
|
|||||||
old_value: EntityType
|
old_value: EntityType
|
||||||
|
|
||||||
|
|
||||||
|
class _AuditLogChange_AppCommandPermissions(TypedDict):
|
||||||
|
key: str
|
||||||
|
new_value: ApplicationCommandPermissions
|
||||||
|
old_value: ApplicationCommandPermissions
|
||||||
|
|
||||||
|
|
||||||
AuditLogChange = Union[
|
AuditLogChange = Union[
|
||||||
_AuditLogChange_Str,
|
_AuditLogChange_Str,
|
||||||
_AuditLogChange_AssetHash,
|
_AuditLogChange_AssetHash,
|
||||||
@ -260,6 +268,7 @@ AuditLogChange = Union[
|
|||||||
_AuditLogChange_PrivacyLevel,
|
_AuditLogChange_PrivacyLevel,
|
||||||
_AuditLogChange_Status,
|
_AuditLogChange_Status,
|
||||||
_AuditLogChange_EntityType,
|
_AuditLogChange_EntityType,
|
||||||
|
_AuditLogChange_AppCommandPermissions,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -272,6 +281,8 @@ class AuditEntryInfo(TypedDict):
|
|||||||
id: Snowflake
|
id: Snowflake
|
||||||
type: Literal['0', '1']
|
type: Literal['0', '1']
|
||||||
role_name: str
|
role_name: str
|
||||||
|
application_id: Snowflake
|
||||||
|
guild_id: Snowflake
|
||||||
|
|
||||||
|
|
||||||
class AuditLogEntry(TypedDict):
|
class AuditLogEntry(TypedDict):
|
||||||
@ -291,3 +302,4 @@ class AuditLog(TypedDict):
|
|||||||
integrations: List[PartialIntegration]
|
integrations: List[PartialIntegration]
|
||||||
threads: List[Thread]
|
threads: List[Thread]
|
||||||
guild_scheduled_events: List[GuildScheduledEvent]
|
guild_scheduled_events: List[GuildScheduledEvent]
|
||||||
|
application_commands: List[ApplicationCommand]
|
||||||
|
@ -192,7 +192,7 @@ ApplicationCommand = Union[
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
ApplicationCommandPermissionType = Literal[1, 2]
|
ApplicationCommandPermissionType = Literal[1, 2, 3]
|
||||||
|
|
||||||
|
|
||||||
class ApplicationCommandPermissions(TypedDict):
|
class ApplicationCommandPermissions(TypedDict):
|
||||||
|
@ -53,6 +53,7 @@ class PartialIntegration(TypedDict):
|
|||||||
name: str
|
name: str
|
||||||
type: IntegrationType
|
type: IntegrationType
|
||||||
account: IntegrationAccount
|
account: IntegrationAccount
|
||||||
|
application_id: Snowflake
|
||||||
|
|
||||||
|
|
||||||
IntegrationType = Literal['twitch', 'youtube', 'discord']
|
IntegrationType = Literal['twitch', 'youtube', 'discord']
|
||||||
|
43
docs/api.rst
43
docs/api.rst
@ -2239,7 +2239,8 @@ of :class:`enum.Enum`.
|
|||||||
A guild integration was created.
|
A guild integration was created.
|
||||||
|
|
||||||
When this is the action, the type of :attr:`~AuditLogEntry.target` is
|
When this is the action, the type of :attr:`~AuditLogEntry.target` is
|
||||||
the :class:`Object` with the integration ID of the integration which was created.
|
a :class:`PartialIntegration` or :class:`Object` with the
|
||||||
|
integration ID of the integration which was created.
|
||||||
|
|
||||||
.. versionadded:: 1.3
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
@ -2248,7 +2249,8 @@ of :class:`enum.Enum`.
|
|||||||
A guild integration was updated.
|
A guild integration was updated.
|
||||||
|
|
||||||
When this is the action, the type of :attr:`~AuditLogEntry.target` is
|
When this is the action, the type of :attr:`~AuditLogEntry.target` is
|
||||||
the :class:`Object` with the integration ID of the integration which was updated.
|
a :class:`PartialIntegration` or :class:`Object` with the
|
||||||
|
integration ID of the integration which was updated.
|
||||||
|
|
||||||
.. versionadded:: 1.3
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
@ -2257,7 +2259,8 @@ of :class:`enum.Enum`.
|
|||||||
A guild integration was deleted.
|
A guild integration was deleted.
|
||||||
|
|
||||||
When this is the action, the type of :attr:`~AuditLogEntry.target` is
|
When this is the action, the type of :attr:`~AuditLogEntry.target` is
|
||||||
the :class:`Object` with the integration ID of the integration which was deleted.
|
a :class:`PartialIntegration` or :class:`Object` with the
|
||||||
|
integration ID of the integration which was deleted.
|
||||||
|
|
||||||
.. versionadded:: 1.3
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
@ -2465,6 +2468,27 @@ of :class:`enum.Enum`.
|
|||||||
|
|
||||||
.. versionadded:: 2.0
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
.. attribute:: app_command_permission_update
|
||||||
|
|
||||||
|
An application command or integrations application command permissions
|
||||||
|
were updated.
|
||||||
|
|
||||||
|
When this is the action, the type of :attr:`~AuditLogEntry.target` is
|
||||||
|
a :class:`PartialIntegration` for an integrations general permissions,
|
||||||
|
:class:`~discord.app_commands.AppCommand` for a specific commands permissions,
|
||||||
|
or :class:`Object` with the ID of the command or integration which
|
||||||
|
was updated.
|
||||||
|
|
||||||
|
When this is the action, the type of :attr:`~AuditLogEntry.extra` is
|
||||||
|
set to an :class:`PartialIntegration` or :class:`Object` with the ID of
|
||||||
|
application that command or integration belongs to.
|
||||||
|
|
||||||
|
Possible attributes for :class:`AuditLogDiff`:
|
||||||
|
|
||||||
|
- :attr:`~AuditLogDiff.app_command_permissions`
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
.. class:: AuditLogActionCategory
|
.. class:: AuditLogActionCategory
|
||||||
|
|
||||||
Represents the category that the :class:`AuditLogAction` belongs to.
|
Represents the category that the :class:`AuditLogAction` belongs to.
|
||||||
@ -3477,6 +3501,16 @@ AuditLogDiff
|
|||||||
|
|
||||||
:type: :class:`Asset`
|
:type: :class:`Asset`
|
||||||
|
|
||||||
|
.. attribute:: app_command_permissions
|
||||||
|
|
||||||
|
A list of application command permission tuples that represents a
|
||||||
|
target and a :class:`bool` for said target.
|
||||||
|
|
||||||
|
The first element is the object being targeted, which can either
|
||||||
|
be a :class:`Member`, :class:`abc.GuildChannel`,
|
||||||
|
:class:`~discord.app_commands.AllChannels`, or :class:`Role`.
|
||||||
|
:type: List[Tuple[target, :class:`bool`]]
|
||||||
|
|
||||||
.. this is currently missing the following keys: reason and application_id
|
.. this is currently missing the following keys: reason and application_id
|
||||||
I'm not sure how to about porting these
|
I'm not sure how to about porting these
|
||||||
|
|
||||||
@ -3727,6 +3761,9 @@ Integration
|
|||||||
.. autoclass:: StreamIntegration()
|
.. autoclass:: StreamIntegration()
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: PartialIntegration()
|
||||||
|
:members:
|
||||||
|
|
||||||
Member
|
Member
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
|
@ -129,6 +129,14 @@ Argument
|
|||||||
.. autoclass:: discord.app_commands.Argument()
|
.. autoclass:: discord.app_commands.Argument()
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
AllChannels
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. attributetable:: discord.app_commands.AllChannels
|
||||||
|
|
||||||
|
.. autoclass:: discord.app_commands.AllChannels()
|
||||||
|
:members:
|
||||||
|
|
||||||
Data Classes
|
Data Classes
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user