Add support for audit log reasons.
Most routes now have a 'reason' keyword argument.
This commit is contained in:
parent
2b44876955
commit
dff6bcc745
@ -121,7 +121,7 @@ class GuildChannel:
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _move(self, position):
|
def _move(self, position, *, reason):
|
||||||
if position < 0:
|
if position < 0:
|
||||||
raise InvalidArgument('Channel position cannot be less than 0.')
|
raise InvalidArgument('Channel position cannot be less than 0.')
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ class GuildChannel:
|
|||||||
channels.insert(position, self)
|
channels.insert(position, self)
|
||||||
|
|
||||||
payload = [{'id': c.id, 'position': index } for index, c in enumerate(channels)]
|
payload = [{'id': c.id, 'position': index } for index, c in enumerate(channels)]
|
||||||
yield from http.move_channel_position(self.guild.id, payload)
|
yield from http.move_channel_position(self.guild.id, payload, reason=reason)
|
||||||
|
|
||||||
def _fill_overwrites(self, data):
|
def _fill_overwrites(self, data):
|
||||||
self._overwrites = []
|
self._overwrites = []
|
||||||
@ -351,13 +351,19 @@ class GuildChannel:
|
|||||||
return base
|
return base
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def delete(self):
|
def delete(self, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Deletes the channel.
|
Deletes the channel.
|
||||||
|
|
||||||
You must have Manage Channel permission to use this.
|
You must have Manage Channel permission to use this.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
-----------
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for deleting this channel.
|
||||||
|
Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
Forbidden
|
Forbidden
|
||||||
@ -367,10 +373,10 @@ class GuildChannel:
|
|||||||
HTTPException
|
HTTPException
|
||||||
Deleting the channel failed.
|
Deleting the channel failed.
|
||||||
"""
|
"""
|
||||||
yield from self._state.http.delete_channel(self.id)
|
yield from self._state.http.delete_channel(self.id, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def set_permissions(self, target, *, overwrite=_undefined, **permissions):
|
def set_permissions(self, target, *, overwrite=_undefined, reason=None, **permissions):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Sets the channel specific permission overwrites for a target in the
|
Sets the channel specific permission overwrites for a target in the
|
||||||
@ -418,6 +424,8 @@ class GuildChannel:
|
|||||||
\*\*permissions
|
\*\*permissions
|
||||||
A keyword argument list of permissions to set for ease of use.
|
A keyword argument list of permissions to set for ease of use.
|
||||||
Cannot be mixed with ``overwrite``.
|
Cannot be mixed with ``overwrite``.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for doing this action. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -453,15 +461,15 @@ class GuildChannel:
|
|||||||
# TODO: wait for event
|
# TODO: wait for event
|
||||||
|
|
||||||
if overwrite is None:
|
if overwrite is None:
|
||||||
yield from http.delete_channel_permissions(self.id, target.id)
|
yield from http.delete_channel_permissions(self.id, target.id, reason=reason)
|
||||||
elif isinstance(overwrite, PermissionOverwrite):
|
elif isinstance(overwrite, PermissionOverwrite):
|
||||||
(allow, deny) = overwrite.pair()
|
(allow, deny) = overwrite.pair()
|
||||||
yield from http.edit_channel_permissions(self.id, target.id, allow.value, deny.value, perm_type)
|
yield from http.edit_channel_permissions(self.id, target.id, allow.value, deny.value, perm_type, reason=reason)
|
||||||
else:
|
else:
|
||||||
raise InvalidArgument('Invalid overwrite type provided.')
|
raise InvalidArgument('Invalid overwrite type provided.')
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create_invite(self, **fields):
|
def create_invite(self, *, reason=None, **fields):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Creates an instant invite.
|
Creates an instant invite.
|
||||||
@ -481,6 +489,8 @@ class GuildChannel:
|
|||||||
Indicates if a unique invite URL should be created. Defaults to True.
|
Indicates if a unique invite URL should be created. Defaults to True.
|
||||||
If this is set to False then it will return a previously created
|
If this is set to False then it will return a previously created
|
||||||
invite.
|
invite.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for creating this invite. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -493,7 +503,7 @@ class GuildChannel:
|
|||||||
The invite that was created.
|
The invite that was created.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data = yield from self._state.http.create_invite(self.id, **fields)
|
data = yield from self._state.http.create_invite(self.id, reason=reason, **fields)
|
||||||
return Invite.from_incomplete(data=data, state=self._state)
|
return Invite.from_incomplete(data=data, state=self._state)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
@ -537,7 +547,7 @@ class Messageable(metaclass=abc.ABCMeta):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def send(self, content=None, *, tts=False, embed=None, file=None, files=None, delete_after=None):
|
def send(self, content=None, *, tts=False, embed=None, file=None, files=None, reason=None, delete_after=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Sends a message to the destination with the content given.
|
Sends a message to the destination with the content given.
|
||||||
@ -571,6 +581,9 @@ class Messageable(metaclass=abc.ABCMeta):
|
|||||||
If provided, the number of seconds to wait in the background
|
If provided, the number of seconds to wait in the background
|
||||||
before deleting the message we just sent. If the deletion fails,
|
before deleting the message we just sent. If the deletion fails,
|
||||||
then it is silently ignored.
|
then it is silently ignored.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for deleting the message, if necessary.
|
||||||
|
Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
--------
|
--------
|
||||||
@ -626,7 +639,7 @@ class Messageable(metaclass=abc.ABCMeta):
|
|||||||
def delete():
|
def delete():
|
||||||
yield from asyncio.sleep(delete_after, loop=state.loop)
|
yield from asyncio.sleep(delete_after, loop=state.loop)
|
||||||
try:
|
try:
|
||||||
yield from ret.delete()
|
yield from ret.delete(reason=reason)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
compat.create_task(delete(), loop=state.loop)
|
compat.create_task(delete(), loop=state.loop)
|
||||||
|
@ -37,9 +37,9 @@ import asyncio
|
|||||||
__all__ = ('TextChannel', 'VoiceChannel', 'DMChannel', 'GroupChannel', '_channel_factory')
|
__all__ = ('TextChannel', 'VoiceChannel', 'DMChannel', 'GroupChannel', '_channel_factory')
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _single_delete_strategy(messages):
|
def _single_delete_strategy(messages, *, reason):
|
||||||
for m in messages:
|
for m in messages:
|
||||||
yield from m.delete()
|
yield from m.delete(reason=reason)
|
||||||
|
|
||||||
class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
||||||
"""Represents a Discord guild text channel.
|
"""Represents a Discord guild text channel.
|
||||||
@ -116,7 +116,7 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
|||||||
return n == 'nsfw' or n[:5] == 'nsfw-'
|
return n == 'nsfw' or n[:5] == 'nsfw-'
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def edit(self, **options):
|
def edit(self, *, reason=None, **options):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Edits the channel.
|
Edits the channel.
|
||||||
@ -132,6 +132,8 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
|||||||
The new channel's topic.
|
The new channel's topic.
|
||||||
position: int
|
position: int
|
||||||
The new channel's position.
|
The new channel's position.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for editing this channel. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
------
|
------
|
||||||
@ -147,15 +149,15 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
yield from self._move(position)
|
yield from self._move(position, reason=reason)
|
||||||
self.position = position
|
self.position = position
|
||||||
|
|
||||||
if options:
|
if options:
|
||||||
data = yield from self._state.http.edit_channel(self.id, **options)
|
data = yield from self._state.http.edit_channel(self.id, reason=reason, **options)
|
||||||
self._update(self.guild, data)
|
self._update(self.guild, data)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def delete_messages(self, messages):
|
def delete_messages(self, messages, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Deletes a list of messages. This is similar to :meth:`Message.delete`
|
Deletes a list of messages. This is similar to :meth:`Message.delete`
|
||||||
@ -167,6 +169,8 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
|||||||
-----------
|
-----------
|
||||||
messages: iterable of :class:`Message`
|
messages: iterable of :class:`Message`
|
||||||
An iterable of messages denoting which ones to bulk delete.
|
An iterable of messages denoting which ones to bulk delete.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for bulk deleting these messages. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
------
|
------
|
||||||
@ -186,10 +190,10 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
|||||||
message_ids = [m.id for m in messages]
|
message_ids = [m.id for m in messages]
|
||||||
channel = yield from self._get_channel()
|
channel = yield from self._get_channel()
|
||||||
|
|
||||||
yield from self._state.http.delete_messages(channel.id, message_ids)
|
yield from self._state.http.delete_messages(channel.id, message_ids, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def purge(self, *, limit=100, check=None, before=None, after=None, around=None):
|
def purge(self, *, limit=100, check=None, before=None, after=None, around=None, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Purges a list of messages that meet the criteria given by the predicate
|
Purges a list of messages that meet the criteria given by the predicate
|
||||||
@ -219,6 +223,8 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
|||||||
Same as ``after`` in :meth:`history`.
|
Same as ``after`` in :meth:`history`.
|
||||||
around
|
around
|
||||||
Same as ``around`` in :meth:`history`.
|
Same as ``around`` in :meth:`history`.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for doing this action. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -262,17 +268,17 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
|||||||
if count >= 2:
|
if count >= 2:
|
||||||
# more than 2 messages -> bulk delete
|
# more than 2 messages -> bulk delete
|
||||||
to_delete = ret[-count:]
|
to_delete = ret[-count:]
|
||||||
yield from strategy(to_delete)
|
yield from strategy(to_delete, reason=reason)
|
||||||
elif count == 1:
|
elif count == 1:
|
||||||
# delete a single message
|
# delete a single message
|
||||||
yield from ret[-1].delete()
|
yield from ret[-1].delete(reason=reason)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
else:
|
else:
|
||||||
if count == 100:
|
if count == 100:
|
||||||
# we've reached a full 'queue'
|
# we've reached a full 'queue'
|
||||||
to_delete = ret[-100:]
|
to_delete = ret[-100:]
|
||||||
yield from strategy(to_delete)
|
yield from strategy(to_delete, reason=reason)
|
||||||
count = 0
|
count = 0
|
||||||
yield from asyncio.sleep(1)
|
yield from asyncio.sleep(1)
|
||||||
|
|
||||||
@ -283,7 +289,7 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
|
|||||||
yield from ret[-1].delete()
|
yield from ret[-1].delete()
|
||||||
elif count >= 2:
|
elif count >= 2:
|
||||||
to_delete = ret[-count:]
|
to_delete = ret[-count:]
|
||||||
yield from strategy(to_delete)
|
yield from strategy(to_delete, reason=reason)
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
strategy = _single_delete_strategy
|
strategy = _single_delete_strategy
|
||||||
@ -362,7 +368,7 @@ class VoiceChannel(discord.abc.Callable, discord.abc.GuildChannel, Hashable):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def edit(self, **options):
|
def edit(self, *, reason=None, **options):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Edits the channel.
|
Edits the channel.
|
||||||
@ -378,6 +384,8 @@ class VoiceChannel(discord.abc.Callable, discord.abc.GuildChannel, Hashable):
|
|||||||
The new channel's user limit.
|
The new channel's user limit.
|
||||||
position: int
|
position: int
|
||||||
The new channel's position.
|
The new channel's position.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for editing this channel. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
------
|
------
|
||||||
@ -392,11 +400,11 @@ class VoiceChannel(discord.abc.Callable, discord.abc.GuildChannel, Hashable):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
yield from self._move(position)
|
yield from self._move(position, reason=reason)
|
||||||
self.position = position
|
self.position = position
|
||||||
|
|
||||||
if options:
|
if options:
|
||||||
data = yield from self._state.http.edit_channel(self.id, **options)
|
data = yield from self._state.http.edit_channel(self.id, reason=reason, **options)
|
||||||
self._update(self.guild, data)
|
self._update(self.guild, data)
|
||||||
|
|
||||||
class DMChannel(discord.abc.Messageable, Hashable):
|
class DMChannel(discord.abc.Messageable, Hashable):
|
||||||
|
@ -118,7 +118,7 @@ class Emoji(Hashable):
|
|||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def delete(self):
|
def delete(self, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Deletes the custom emoji.
|
Deletes the custom emoji.
|
||||||
@ -128,6 +128,11 @@ class Emoji(Hashable):
|
|||||||
|
|
||||||
Guild local emotes can only be deleted by user bots.
|
Guild local emotes can only be deleted by user bots.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
-----------
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for deleting this emoji. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
Forbidden
|
Forbidden
|
||||||
@ -136,10 +141,10 @@ class Emoji(Hashable):
|
|||||||
An error occurred deleting the emoji.
|
An error occurred deleting the emoji.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self._state.http.delete_custom_emoji(self.guild.id, self.id)
|
yield from self._state.http.delete_custom_emoji(self.guild.id, self.id, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def edit(self, *, name):
|
def edit(self, *, name, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Edits the custom emoji.
|
Edits the custom emoji.
|
||||||
@ -153,6 +158,8 @@ class Emoji(Hashable):
|
|||||||
-----------
|
-----------
|
||||||
name: str
|
name: str
|
||||||
The new emoji name.
|
The new emoji name.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for editing this emoji. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -162,4 +169,4 @@ class Emoji(Hashable):
|
|||||||
An error occurred editing the emoji.
|
An error occurred editing the emoji.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self._state.http.edit_custom_emoji(self.guild.id, self.id, name=name)
|
yield from self._state.http.edit_custom_emoji(self.guild.id, self.id, name=name, reason=reason)
|
||||||
|
@ -427,7 +427,7 @@ class Guild(Hashable):
|
|||||||
|
|
||||||
return utils.find(pred, members)
|
return utils.find(pred, members)
|
||||||
|
|
||||||
def _create_channel(self, name, overwrites, type):
|
def _create_channel(self, name, overwrites, type, reason):
|
||||||
if overwrites is None:
|
if overwrites is None:
|
||||||
overwrites = {}
|
overwrites = {}
|
||||||
elif not isinstance(overwrites, dict):
|
elif not isinstance(overwrites, dict):
|
||||||
@ -452,10 +452,10 @@ class Guild(Hashable):
|
|||||||
|
|
||||||
perms.append(payload)
|
perms.append(payload)
|
||||||
|
|
||||||
return self._state.http.create_channel(self.id, name, str(type), permission_overwrites=perms)
|
return self._state.http.create_channel(self.id, name, str(type), permission_overwrites=perms, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create_text_channel(self, name, *, overwrites=None):
|
def create_text_channel(self, name, *, overwrites=None, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Creates a :class:`TextChannel` for the guild.
|
Creates a :class:`TextChannel` for the guild.
|
||||||
@ -495,6 +495,8 @@ class Guild(Hashable):
|
|||||||
A `dict` of target (either a role or a member) to
|
A `dict` of target (either a role or a member) to
|
||||||
:class:`PermissionOverwrite` to apply upon creation of a channel.
|
:class:`PermissionOverwrite` to apply upon creation of a channel.
|
||||||
Useful for creating secret channels.
|
Useful for creating secret channels.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for creating this channel. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -510,17 +512,17 @@ class Guild(Hashable):
|
|||||||
:class:`TextChannel`
|
:class:`TextChannel`
|
||||||
The channel that was just created.
|
The channel that was just created.
|
||||||
"""
|
"""
|
||||||
data = yield from self._create_channel(name, overwrites, ChannelType.text)
|
data = yield from self._create_channel(name, overwrites, ChannelType.text, reason=reason)
|
||||||
return TextChannel(state=self._state, guild=self, data=data)
|
return TextChannel(state=self._state, guild=self, data=data)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create_voice_channel(self, name, *, overwrites=None):
|
def create_voice_channel(self, name, *, overwrites=None, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Same as :meth:`create_text_channel` except makes a
|
Same as :meth:`create_text_channel` except makes a
|
||||||
:class:`VoiceChannel` instead.
|
:class:`VoiceChannel` instead.
|
||||||
"""
|
"""
|
||||||
data = yield from self._create_channel(name, overwrites, ChannelType.voice)
|
data = yield from self._create_channel(name, overwrites, ChannelType.voice, reason=reason)
|
||||||
return VoiceChannel(state=self._state, guild=self, data=data)
|
return VoiceChannel(state=self._state, guild=self, data=data)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
@ -559,7 +561,7 @@ class Guild(Hashable):
|
|||||||
yield from self._state.http.delete_guild(self.id)
|
yield from self._state.http.delete_guild(self.id)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def edit(self, **fields):
|
def edit(self, *, reason=None, **fields):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Edits the guild.
|
Edits the guild.
|
||||||
@ -590,6 +592,8 @@ class Guild(Hashable):
|
|||||||
be owner of the guild to do this.
|
be owner of the guild to do this.
|
||||||
verification_level: :class:`VerificationLevel`
|
verification_level: :class:`VerificationLevel`
|
||||||
The new verification level for the guild.
|
The new verification level for the guild.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for editing this guild. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -642,7 +646,8 @@ class Guild(Hashable):
|
|||||||
raise InvalidArgument('verification_level field must of type VerificationLevel')
|
raise InvalidArgument('verification_level field must of type VerificationLevel')
|
||||||
|
|
||||||
fields['verification_level'] = level.value
|
fields['verification_level'] = level.value
|
||||||
yield from self._state.http.edit_guild(self.id, **fields)
|
|
||||||
|
yield from self._state.http.edit_guild(self.id, reason=reason, **fields)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
@ -678,7 +683,7 @@ class Guild(Hashable):
|
|||||||
for e in data]
|
for e in data]
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def prune_members(self, *, days):
|
def prune_members(self, *, days, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Prunes the guild from its inactive members.
|
Prunes the guild from its inactive members.
|
||||||
@ -696,6 +701,8 @@ class Guild(Hashable):
|
|||||||
-----------
|
-----------
|
||||||
days: int
|
days: int
|
||||||
The number of days before counting as inactive.
|
The number of days before counting as inactive.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for doing this action. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -715,7 +722,7 @@ class Guild(Hashable):
|
|||||||
if not isinstance(days, int):
|
if not isinstance(days, int):
|
||||||
raise InvalidArgument('Expected int for ``days``, received {0.__class__.__name__} instead.'.format(days))
|
raise InvalidArgument('Expected int for ``days``, received {0.__class__.__name__} instead.'.format(days))
|
||||||
|
|
||||||
data = yield from self._state.http.prune_members(self.id, days)
|
data = yield from self._state.http.prune_members(self.id, days, reason=reason)
|
||||||
return data['pruned']
|
return data['pruned']
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
@ -784,7 +791,7 @@ class Guild(Hashable):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create_invite(self, **fields):
|
def create_invite(self, *, reason=None, **fields):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Creates an instant invite.
|
Creates an instant invite.
|
||||||
@ -804,6 +811,8 @@ class Guild(Hashable):
|
|||||||
Indicates if a unique invite URL should be created. Defaults to True.
|
Indicates if a unique invite URL should be created. Defaults to True.
|
||||||
If this is set to False then it will return a previously created
|
If this is set to False then it will return a previously created
|
||||||
invite.
|
invite.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for creating this invite. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -816,11 +825,11 @@ class Guild(Hashable):
|
|||||||
The invite that was created.
|
The invite that was created.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data = yield from self._state.http.create_invite(self.id, **fields)
|
data = yield from self._state.http.create_invite(self.id, reason=reason, **fields)
|
||||||
return Invite.from_incomplete(data=data, state=self._state)
|
return Invite.from_incomplete(data=data, state=self._state)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create_custom_emoji(self, *, name, image):
|
def create_custom_emoji(self, *, name, image, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Creates a custom :class:`Emoji` for the guild.
|
Creates a custom :class:`Emoji` for the guild.
|
||||||
@ -839,6 +848,8 @@ class Guild(Hashable):
|
|||||||
image: bytes
|
image: bytes
|
||||||
The *bytes-like* object representing the image data to use.
|
The *bytes-like* object representing the image data to use.
|
||||||
Only JPG and PNG images are supported.
|
Only JPG and PNG images are supported.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for creating this emoji. Shows up on the audit log.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
--------
|
--------
|
||||||
@ -854,11 +865,11 @@ class Guild(Hashable):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
img = utils._bytes_to_base64_data(image)
|
img = utils._bytes_to_base64_data(image)
|
||||||
data = yield from self._state.http.create_custom_emoji(self.id, name, img)
|
data = yield from self._state.http.create_custom_emoji(self.id, name, img, reason=reason)
|
||||||
return self._state.store_emoji(self, data)
|
return self._state.store_emoji(self, data)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create_role(self, **fields):
|
def create_role(self, *, reason=None, **fields):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Creates a :class:`Role` for the guild.
|
Creates a :class:`Role` for the guild.
|
||||||
@ -880,6 +891,8 @@ class Guild(Hashable):
|
|||||||
mentionable: bool
|
mentionable: bool
|
||||||
Indicates if the role should be mentionable by others.
|
Indicates if the role should be mentionable by others.
|
||||||
Defaults to False.
|
Defaults to False.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for creating this role. Shows up on the audit log.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
--------
|
--------
|
||||||
@ -915,7 +928,7 @@ class Guild(Hashable):
|
|||||||
if key not in valid_keys:
|
if key not in valid_keys:
|
||||||
raise InvalidArgument('%r is not a valid field.' % key)
|
raise InvalidArgument('%r is not a valid field.' % key)
|
||||||
|
|
||||||
data = yield from self._state.http.create_role(self.id, **fields)
|
data = yield from self._state.http.create_role(self.id, reason=reason, **fields)
|
||||||
role = Role(guild=self, data=data, state=self._state)
|
role = Role(guild=self, data=data, state=self._state)
|
||||||
|
|
||||||
# TODO: add to cache
|
# TODO: add to cache
|
||||||
@ -979,7 +992,7 @@ class Guild(Hashable):
|
|||||||
yield from self._state.http.ban(user.id, self.id, delete_message_days, reason=reason)
|
yield from self._state.http.ban(user.id, self.id, delete_message_days, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def unban(self, user):
|
def unban(self, user, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Unbans a user from the guild.
|
Unbans a user from the guild.
|
||||||
@ -993,6 +1006,8 @@ class Guild(Hashable):
|
|||||||
-----------
|
-----------
|
||||||
user: :class:`abc.Snowflake`
|
user: :class:`abc.Snowflake`
|
||||||
The user to unban.
|
The user to unban.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for doing this action. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -1001,7 +1016,7 @@ class Guild(Hashable):
|
|||||||
HTTPException
|
HTTPException
|
||||||
Unbanning failed.
|
Unbanning failed.
|
||||||
"""
|
"""
|
||||||
yield from self._state.http.unban(user.id, self.id)
|
yield from self._state.http.unban(user.id, self.id, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def vanity_invite(self):
|
def vanity_invite(self):
|
||||||
@ -1038,7 +1053,7 @@ class Guild(Hashable):
|
|||||||
return Invite(state=self._state, data=payload)
|
return Invite(state=self._state, data=payload)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def change_vanity_invite(self, new_code):
|
def change_vanity_invite(self, new_code, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Changes the guild's special vanity invite.
|
Changes the guild's special vanity invite.
|
||||||
@ -1048,6 +1063,13 @@ class Guild(Hashable):
|
|||||||
|
|
||||||
You must have :attr:`Permissions.manage_guild` to use this as well.
|
You must have :attr:`Permissions.manage_guild` to use this as well.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
-----------
|
||||||
|
new_code: str
|
||||||
|
The new vanity URL code.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for changing the vanity invite. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
Forbidden
|
Forbidden
|
||||||
@ -1056,7 +1078,7 @@ class Guild(Hashable):
|
|||||||
Setting the vanity invite failed.
|
Setting the vanity invite failed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self._state.http.change_vanity_code(self.id, new_code)
|
yield from self._state.http.change_vanity_code(self.id, new_code, reason=reason)
|
||||||
|
|
||||||
def ack(self):
|
def ack(self):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
127
discord/http.py
127
discord/http.py
@ -125,6 +125,14 @@ class HTTPClient:
|
|||||||
headers['Content-Type'] = 'application/json'
|
headers['Content-Type'] = 'application/json'
|
||||||
kwargs['data'] = utils.to_json(kwargs.pop('json'))
|
kwargs['data'] = utils.to_json(kwargs.pop('json'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
reason = kwargs.pop('reason')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if reason:
|
||||||
|
headers['X-Audit-Log-Reason'] = reason
|
||||||
|
|
||||||
kwargs['headers'] = headers
|
kwargs['headers'] = headers
|
||||||
|
|
||||||
if not self._global_over.is_set():
|
if not self._global_over.is_set():
|
||||||
@ -336,18 +344,18 @@ class HTTPClient:
|
|||||||
def ack_guild(self, guild_id):
|
def ack_guild(self, guild_id):
|
||||||
return self.request(Route('POST', '/guilds/{guild_id}/ack', guild_id=guild_id))
|
return self.request(Route('POST', '/guilds/{guild_id}/ack', guild_id=guild_id))
|
||||||
|
|
||||||
def delete_message(self, channel_id, message_id):
|
def delete_message(self, channel_id, message_id, *, reason=None):
|
||||||
r = Route('DELETE', '/channels/{channel_id}/messages/{message_id}', channel_id=channel_id,
|
r = Route('DELETE', '/channels/{channel_id}/messages/{message_id}', channel_id=channel_id,
|
||||||
message_id=message_id)
|
message_id=message_id)
|
||||||
return self.request(r)
|
return self.request(r, reason=reason)
|
||||||
|
|
||||||
def delete_messages(self, channel_id, message_ids):
|
def delete_messages(self, channel_id, message_ids, *, reason=None):
|
||||||
r = Route('POST', '/channels/{channel_id}/messages/bulk_delete', channel_id=channel_id)
|
r = Route('POST', '/channels/{channel_id}/messages/bulk_delete', channel_id=channel_id)
|
||||||
payload = {
|
payload = {
|
||||||
'messages': message_ids
|
'messages': message_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.request(r, json=payload)
|
return self.request(r, json=payload, reason=reason)
|
||||||
|
|
||||||
def edit_message(self, message_id, channel_id, **fields):
|
def edit_message(self, message_id, channel_id, **fields):
|
||||||
r = Route('PATCH', '/channels/{channel_id}/messages/{message_id}', channel_id=channel_id,
|
r = Route('PATCH', '/channels/{channel_id}/messages/{message_id}', channel_id=channel_id,
|
||||||
@ -426,11 +434,11 @@ class HTTPClient:
|
|||||||
|
|
||||||
return self.request(r, params=params)
|
return self.request(r, params=params)
|
||||||
|
|
||||||
def unban(self, user_id, guild_id):
|
def unban(self, user_id, guild_id, *, reason=None):
|
||||||
r = Route('DELETE', '/guilds/{guild_id}/bans/{user_id}', guild_id=guild_id, user_id=user_id)
|
r = Route('DELETE', '/guilds/{guild_id}/bans/{user_id}', guild_id=guild_id, user_id=user_id)
|
||||||
return self.request(r)
|
return self.request(r, reason=reason)
|
||||||
|
|
||||||
def guild_voice_state(self, user_id, guild_id, *, mute=None, deafen=None):
|
def guild_voice_state(self, user_id, guild_id, *, mute=None, deafen=None, reason=None):
|
||||||
r = Route('PATCH', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
|
r = Route('PATCH', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
|
||||||
payload = {}
|
payload = {}
|
||||||
if mute is not None:
|
if mute is not None:
|
||||||
@ -439,7 +447,7 @@ class HTTPClient:
|
|||||||
if deafen is not None:
|
if deafen is not None:
|
||||||
payload['deaf'] = deafen
|
payload['deaf'] = deafen
|
||||||
|
|
||||||
return self.request(r, json=payload)
|
return self.request(r, json=payload, reason=reason)
|
||||||
|
|
||||||
def edit_profile(self, password, username, avatar, **fields):
|
def edit_profile(self, password, username, avatar, **fields):
|
||||||
payload = {
|
payload = {
|
||||||
@ -456,38 +464,40 @@ class HTTPClient:
|
|||||||
|
|
||||||
return self.request(Route('PATCH', '/users/@me'), json=payload)
|
return self.request(Route('PATCH', '/users/@me'), json=payload)
|
||||||
|
|
||||||
def change_my_nickname(self, guild_id, nickname):
|
def change_my_nickname(self, guild_id, nickname, *, reason=None):
|
||||||
|
r = Route('PATCH', '/guilds/{guild_id}/members/@me/nick', guild_id=guild_id)
|
||||||
payload = {
|
payload = {
|
||||||
'nick': nickname
|
'nick': nickname
|
||||||
}
|
}
|
||||||
return self.request(Route('PATCH', '/guilds/{guild_id}/members/@me/nick', guild_id=guild_id), json=payload)
|
return self.request(r, json=payload, reason=reason)
|
||||||
|
|
||||||
def change_nickname(self, guild_id, user_id, nickname):
|
def change_nickname(self, guild_id, user_id, nickname, *, reason=None):
|
||||||
r = Route('PATCH', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
|
r = Route('PATCH', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
|
||||||
payload = {
|
payload = {
|
||||||
'nick': nickname
|
'nick': nickname
|
||||||
}
|
}
|
||||||
return self.request(r, json=payload)
|
return self.request(r, json=payload, reason=reason)
|
||||||
|
|
||||||
def edit_member(self, guild_id, user_id, **fields):
|
def edit_member(self, guild_id, user_id, *, reason=None, **fields):
|
||||||
r = Route('PATCH', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
|
r = Route('PATCH', '/guilds/{guild_id}/members/{user_id}', guild_id=guild_id, user_id=user_id)
|
||||||
return self.request(r, json=fields)
|
return self.request(r, json=fields, reason=reason)
|
||||||
|
|
||||||
# Channel management
|
# Channel management
|
||||||
|
|
||||||
def edit_channel(self, channel_id, **options):
|
def edit_channel(self, channel_id, *, reason=None, **options):
|
||||||
|
r = Route('PATCH', '/channels/{channel_id}', channel_id=channel_id)
|
||||||
valid_keys = ('name', 'topic', 'bitrate', 'user_limit', 'position')
|
valid_keys = ('name', 'topic', 'bitrate', 'user_limit', 'position')
|
||||||
payload = {
|
payload = {
|
||||||
k: v for k, v in options.items() if k in valid_keys
|
k: v for k, v in options.items() if k in valid_keys
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.request(Route('PATCH', '/channels/{channel_id}', channel_id=channel_id), json=payload)
|
return self.request(r, reason=reason, json=payload)
|
||||||
|
|
||||||
def move_channel_position(self, guild_id, positions):
|
def move_channel_position(self, guild_id, positions, *, reason=None):
|
||||||
r = Route('PATCH', '/guilds/{guild_id}/channels', guild_id=guild_id)
|
r = Route('PATCH', '/guilds/{guild_id}/channels', guild_id=guild_id)
|
||||||
return self.request(r, json=positions)
|
return self.request(r, json=positions, reason=reason)
|
||||||
|
|
||||||
def create_channel(self, guild_id, name, channe_type, permission_overwrites=None):
|
def create_channel(self, guild_id, name, channe_type, permission_overwrites=None, *, reason=None):
|
||||||
payload = {
|
payload = {
|
||||||
'name': name,
|
'name': name,
|
||||||
'type': channe_type
|
'type': channe_type
|
||||||
@ -496,10 +506,10 @@ class HTTPClient:
|
|||||||
if permission_overwrites is not None:
|
if permission_overwrites is not None:
|
||||||
payload['permission_overwrites'] = permission_overwrites
|
payload['permission_overwrites'] = permission_overwrites
|
||||||
|
|
||||||
return self.request(Route('POST', '/guilds/{guild_id}/channels', guild_id=guild_id), json=payload)
|
return self.request(Route('POST', '/guilds/{guild_id}/channels', guild_id=guild_id), json=payload, reason=reason)
|
||||||
|
|
||||||
def delete_channel(self, channel_id):
|
def delete_channel(self, channel_id, *, reason=None):
|
||||||
return self.request(Route('DELETE', '/channels/{channel_id}', channel_id=channel_id))
|
return self.request(Route('DELETE', '/channels/{channel_id}', channel_id=channel_id), reason=reason)
|
||||||
|
|
||||||
# Guild management
|
# Guild management
|
||||||
|
|
||||||
@ -518,7 +528,7 @@ class HTTPClient:
|
|||||||
|
|
||||||
return self.request(Route('POST', '/guilds'), json=payload)
|
return self.request(Route('POST', '/guilds'), json=payload)
|
||||||
|
|
||||||
def edit_guild(self, guild_id, **fields):
|
def edit_guild(self, guild_id, *, reason=None, **fields):
|
||||||
valid_keys = ('name', 'region', 'icon', 'afk_timeout', 'owner_id',
|
valid_keys = ('name', 'region', 'icon', 'afk_timeout', 'owner_id',
|
||||||
'afk_channel_id', 'splash', 'verification_level')
|
'afk_channel_id', 'splash', 'verification_level')
|
||||||
|
|
||||||
@ -526,7 +536,7 @@ class HTTPClient:
|
|||||||
k: v for k, v in fields.items() if k in valid_keys
|
k: v for k, v in fields.items() if k in valid_keys
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.request(Route('PATCH', '/guilds/{guild_id}', guild_id=guild_id), json=payload)
|
return self.request(Route('PATCH', '/guilds/{guild_id}', guild_id=guild_id), json=payload, reason=reason)
|
||||||
|
|
||||||
def get_bans(self, guild_id):
|
def get_bans(self, guild_id):
|
||||||
return self.request(Route('GET', '/guilds/{guild_id}/bans', guild_id=guild_id))
|
return self.request(Route('GET', '/guilds/{guild_id}/bans', guild_id=guild_id))
|
||||||
@ -534,15 +544,15 @@ class HTTPClient:
|
|||||||
def get_vanity_code(self, guild_id):
|
def get_vanity_code(self, guild_id):
|
||||||
return self.request(Route('GET', '/guilds/{guild_id}/vanity-url', guild_id=guild_id))
|
return self.request(Route('GET', '/guilds/{guild_id}/vanity-url', guild_id=guild_id))
|
||||||
|
|
||||||
def change_vanity_code(self, guild_id, code):
|
def change_vanity_code(self, guild_id, code, *, reason=None):
|
||||||
payload = { 'code': code }
|
payload = { 'code': code }
|
||||||
return self.request(Route('PATCH', '/guilds/{guild_id}/vanity-url', guild_id=guild_id), json=payload)
|
return self.request(Route('PATCH', '/guilds/{guild_id}/vanity-url', guild_id=guild_id), json=payload, reason=reason)
|
||||||
|
|
||||||
def prune_members(self, guild_id, days):
|
def prune_members(self, guild_id, days, *, reason=None):
|
||||||
params = {
|
params = {
|
||||||
'days': days
|
'days': days
|
||||||
}
|
}
|
||||||
return self.request(Route('POST', '/guilds/{guild_id}/prune', guild_id=guild_id), params=params)
|
return self.request(Route('POST', '/guilds/{guild_id}/prune', guild_id=guild_id), params=params, reason=reason)
|
||||||
|
|
||||||
def estimate_pruned_members(self, guild_id, days):
|
def estimate_pruned_members(self, guild_id, days):
|
||||||
params = {
|
params = {
|
||||||
@ -550,24 +560,25 @@ class HTTPClient:
|
|||||||
}
|
}
|
||||||
return self.request(Route('GET', '/guilds/{guild_id}/prune', guild_id=guild_id), params=params)
|
return self.request(Route('GET', '/guilds/{guild_id}/prune', guild_id=guild_id), params=params)
|
||||||
|
|
||||||
def create_custom_emoji(self, guild_id, name, image):
|
def create_custom_emoji(self, guild_id, name, image, *, reason=None):
|
||||||
payload = {
|
payload = {
|
||||||
'name': name,
|
'name': name,
|
||||||
'image': image
|
'image': image
|
||||||
}
|
}
|
||||||
|
|
||||||
r = Route('POST', '/guilds/{guild_id}/emojis', guild_id=guild_id)
|
r = Route('POST', '/guilds/{guild_id}/emojis', guild_id=guild_id)
|
||||||
return self.request(r, json=payload)
|
return self.request(r, json=payload, reason=reason)
|
||||||
|
|
||||||
def delete_custom_emoji(self, guild_id, emoji_id):
|
def delete_custom_emoji(self, guild_id, emoji_id, *, reason=None):
|
||||||
return self.request(Route('DELETE', '/guilds/{guild_id}/emojis/{emoji_id}', guild_id=guild_id, emoji_id=emoji_id))
|
r = Route('DELETE', '/guilds/{guild_id}/emojis/{emoji_id}', guild_id=guild_id, emoji_id=emoji_id)
|
||||||
|
return self.request(r, reason=reason)
|
||||||
|
|
||||||
def edit_custom_emoji(self, guild_id, emoji_id, *, name):
|
def edit_custom_emoji(self, guild_id, emoji_id, *, name, reason=None):
|
||||||
payload = {
|
payload = {
|
||||||
'name': name
|
'name': name
|
||||||
}
|
}
|
||||||
r = Route('PATCH', '/guilds/{guild_id}/emojis/{emoji_id}', guild_id=guild_id, emoji_id=emoji_id)
|
r = Route('PATCH', '/guilds/{guild_id}/emojis/{emoji_id}', guild_id=guild_id, emoji_id=emoji_id)
|
||||||
return self.request(r, json=payload)
|
return self.request(r, json=payload, reason=reason)
|
||||||
|
|
||||||
def get_audit_logs(self, guild_id, limit=100, before=None, after=None, user_id=None, action_type=None):
|
def get_audit_logs(self, guild_id, limit=100, before=None, after=None, user_id=None, action_type=None):
|
||||||
params = { 'limit': limit }
|
params = { 'limit': limit }
|
||||||
@ -585,7 +596,7 @@ class HTTPClient:
|
|||||||
|
|
||||||
# Invite management
|
# Invite management
|
||||||
|
|
||||||
def create_invite(self, channel_id, **options):
|
def create_invite(self, channel_id, *, reason=None, **options):
|
||||||
r = Route('POST', '/channels/{channel_id}/invites', channel_id=channel_id)
|
r = Route('POST', '/channels/{channel_id}/invites', channel_id=channel_id)
|
||||||
payload = {
|
payload = {
|
||||||
'max_age': options.get('max_age', 0),
|
'max_age': options.get('max_age', 0),
|
||||||
@ -594,7 +605,7 @@ class HTTPClient:
|
|||||||
'unique': options.get('unique', True)
|
'unique': options.get('unique', True)
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.request(r, json=payload)
|
return self.request(r, reason=reason, json=payload)
|
||||||
|
|
||||||
def get_invite(self, invite_id):
|
def get_invite(self, invite_id):
|
||||||
return self.request(Route('GET', '/invite/{invite_id}', invite_id=invite_id))
|
return self.request(Route('GET', '/invite/{invite_id}', invite_id=invite_id))
|
||||||
@ -605,45 +616,45 @@ class HTTPClient:
|
|||||||
def invites_from_channel(self, channel_id):
|
def invites_from_channel(self, channel_id):
|
||||||
return self.request(Route('GET', '/channels/{channel_id}/invites', channel_id=channel_id))
|
return self.request(Route('GET', '/channels/{channel_id}/invites', channel_id=channel_id))
|
||||||
|
|
||||||
def delete_invite(self, invite_id):
|
def delete_invite(self, invite_id, *, reason=None):
|
||||||
return self.request(Route('DELETE', '/invite/{invite_id}', invite_id=invite_id))
|
return self.request(Route('DELETE', '/invite/{invite_id}', invite_id=invite_id), reason=reason)
|
||||||
|
|
||||||
# Role management
|
# Role management
|
||||||
|
|
||||||
def edit_role(self, guild_id, role_id, **fields):
|
def edit_role(self, guild_id, role_id, *, reason=None, **fields):
|
||||||
r = Route('PATCH', '/guilds/{guild_id}/roles/{role_id}', guild_id=guild_id, role_id=role_id)
|
r = Route('PATCH', '/guilds/{guild_id}/roles/{role_id}', guild_id=guild_id, role_id=role_id)
|
||||||
valid_keys = ('name', 'permissions', 'color', 'hoist', 'mentionable')
|
valid_keys = ('name', 'permissions', 'color', 'hoist', 'mentionable')
|
||||||
payload = {
|
payload = {
|
||||||
k: v for k, v in fields.items() if k in valid_keys
|
k: v for k, v in fields.items() if k in valid_keys
|
||||||
}
|
}
|
||||||
return self.request(r, json=payload)
|
return self.request(r, json=payload, reason=reason)
|
||||||
|
|
||||||
def delete_role(self, guild_id, role_id):
|
def delete_role(self, guild_id, role_id, *, reason=None):
|
||||||
r = Route('DELETE', '/guilds/{guild_id}/roles/{role_id}', guild_id=guild_id, role_id=role_id)
|
r = Route('DELETE', '/guilds/{guild_id}/roles/{role_id}', guild_id=guild_id, role_id=role_id)
|
||||||
return self.request(r)
|
return self.request(r, reason=reason)
|
||||||
|
|
||||||
def replace_roles(self, user_id, guild_id, role_ids):
|
def replace_roles(self, user_id, guild_id, role_ids, *, reason=None):
|
||||||
return self.edit_member(guild_id=guild_id, user_id=user_id, roles=role_ids)
|
return self.edit_member(guild_id=guild_id, user_id=user_id, roles=role_ids, reason=reason)
|
||||||
|
|
||||||
def create_role(self, guild_id, **fields):
|
def create_role(self, guild_id, *, reason=None, **fields):
|
||||||
r = Route('POST', '/guilds/{guild_id}/roles', guild_id=guild_id)
|
r = Route('POST', '/guilds/{guild_id}/roles', guild_id=guild_id)
|
||||||
return self.request(r, json=fields)
|
return self.request(r, json=fields, reason=reason)
|
||||||
|
|
||||||
def move_role_position(self, guild_id, positions):
|
def move_role_position(self, guild_id, positions, *, reason=None):
|
||||||
r = Route('PATCH', '/guilds/{guild_id}/roles', guild_id=guild_id)
|
r = Route('PATCH', '/guilds/{guild_id}/roles', guild_id=guild_id)
|
||||||
return self.request(r, json=positions)
|
return self.request(r, json=positions, reason=reason)
|
||||||
|
|
||||||
def add_role(self, guild_id, user_id, role_id):
|
def add_role(self, guild_id, user_id, role_id, *, reason=None):
|
||||||
r = Route('PUT', '/guilds/{guild_id}/members/{user_id}/roles/{role_id}',
|
r = Route('PUT', '/guilds/{guild_id}/members/{user_id}/roles/{role_id}',
|
||||||
guild_id=guild_id, user_id=user_id, role_id=role_id)
|
guild_id=guild_id, user_id=user_id, role_id=role_id)
|
||||||
return self.request(r)
|
return self.request(r, reason=reason)
|
||||||
|
|
||||||
def remove_role(self, guild_id, user_id, role_id):
|
def remove_role(self, guild_id, user_id, role_id, *, reason=None):
|
||||||
r = Route('DELETE', '/guilds/{guild_id}/members/{user_id}/roles/{role_id}',
|
r = Route('DELETE', '/guilds/{guild_id}/members/{user_id}/roles/{role_id}',
|
||||||
guild_id=guild_id, user_id=user_id, role_id=role_id)
|
guild_id=guild_id, user_id=user_id, role_id=role_id)
|
||||||
return self.request(r)
|
return self.request(r, reason=reason)
|
||||||
|
|
||||||
def edit_channel_permissions(self, channel_id, target, allow, deny, type):
|
def edit_channel_permissions(self, channel_id, target, allow, deny, type, *, reason=None):
|
||||||
payload = {
|
payload = {
|
||||||
'id': target,
|
'id': target,
|
||||||
'allow': allow,
|
'allow': allow,
|
||||||
@ -651,16 +662,16 @@ class HTTPClient:
|
|||||||
'type': type
|
'type': type
|
||||||
}
|
}
|
||||||
r = Route('PUT', '/channels/{channel_id}/permissions/{target}', channel_id=channel_id, target=target)
|
r = Route('PUT', '/channels/{channel_id}/permissions/{target}', channel_id=channel_id, target=target)
|
||||||
return self.request(r, json=payload)
|
return self.request(r, json=payload, reason=reason)
|
||||||
|
|
||||||
def delete_channel_permissions(self, channel_id, target):
|
def delete_channel_permissions(self, channel_id, target, *, reason=None):
|
||||||
r = Route('DELETE', '/channels/{channel_id}/permissions/{target}', channel_id=channel_id, target=target)
|
r = Route('DELETE', '/channels/{channel_id}/permissions/{target}', channel_id=channel_id, target=target)
|
||||||
return self.request(r)
|
return self.request(r, reason=reason)
|
||||||
|
|
||||||
# Voice management
|
# Voice management
|
||||||
|
|
||||||
def move_member(self, user_id, guild_id, channel_id):
|
def move_member(self, user_id, guild_id, channel_id, *, reason=None):
|
||||||
return self.edit_member(guild_id=guild_id, user_id=user_id, channel_id=channel_id)
|
return self.edit_member(guild_id=guild_id, user_id=user_id, channel_id=channel_id, reason=reason)
|
||||||
|
|
||||||
|
|
||||||
# Relationship related
|
# Relationship related
|
||||||
|
@ -147,11 +147,16 @@ class Invite(Hashable):
|
|||||||
yield from self._state.http.accept_invite(self.code)
|
yield from self._state.http.accept_invite(self.code)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def delete(self):
|
def delete(self, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Revokes the instant invite.
|
Revokes the instant invite.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
-----------
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for deleting this invite. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
Forbidden
|
Forbidden
|
||||||
@ -162,4 +167,4 @@ class Invite(Hashable):
|
|||||||
Revoking the invite failed.
|
Revoking the invite failed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self._state.http.delete_invite(self.code)
|
yield from self._state.http.delete_invite(self.code, reason=reason)
|
||||||
|
@ -349,12 +349,12 @@ class Member(discord.abc.Messageable):
|
|||||||
yield from self.guild.ban(self, **kwargs)
|
yield from self.guild.ban(self, **kwargs)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def unban(self):
|
def unban(self, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Unbans this member. Equivalent to :meth:`Guild.unban`
|
Unbans this member. Equivalent to :meth:`Guild.unban`
|
||||||
"""
|
"""
|
||||||
yield from self.guild.unban(self)
|
yield from self.guild.unban(self, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def kick(self, *, reason=None):
|
def kick(self, *, reason=None):
|
||||||
@ -365,7 +365,7 @@ class Member(discord.abc.Messageable):
|
|||||||
yield from self.guild.kick(self, reason=reason)
|
yield from self.guild.kick(self, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def edit(self, **fields):
|
def edit(self, *, reason=None, **fields):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Edits the member's data.
|
Edits the member's data.
|
||||||
@ -400,6 +400,8 @@ class Member(discord.abc.Messageable):
|
|||||||
The member's new list of roles. This *replaces* the roles.
|
The member's new list of roles. This *replaces* the roles.
|
||||||
voice_channel: :class:`VoiceChannel`
|
voice_channel: :class:`VoiceChannel`
|
||||||
The voice channel to move the member to.
|
The voice channel to move the member to.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for editing this member. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -420,7 +422,7 @@ class Member(discord.abc.Messageable):
|
|||||||
else:
|
else:
|
||||||
nick = nick if nick else ''
|
nick = nick if nick else ''
|
||||||
if self._state.self_id == self.id:
|
if self._state.self_id == self.id:
|
||||||
yield from http.change_my_nickname(guild_id, nick)
|
yield from http.change_my_nickname(guild_id, nick, reason=reason)
|
||||||
else:
|
else:
|
||||||
payload['nick'] = nick
|
payload['nick'] = nick
|
||||||
|
|
||||||
@ -446,12 +448,12 @@ class Member(discord.abc.Messageable):
|
|||||||
else:
|
else:
|
||||||
payload['roles'] = tuple(r.id for r in roles)
|
payload['roles'] = tuple(r.id for r in roles)
|
||||||
|
|
||||||
yield from http.edit_member(guild_id, self.id, **payload)
|
yield from http.edit_member(guild_id, self.id, reason=reason, **payload)
|
||||||
|
|
||||||
# TODO: wait for WS event for modify-in-place behaviour
|
# TODO: wait for WS event for modify-in-place behaviour
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def move_to(self, channel):
|
def move_to(self, channel, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Moves a member to a new voice channel (they must be connected first).
|
Moves a member to a new voice channel (they must be connected first).
|
||||||
@ -465,11 +467,13 @@ class Member(discord.abc.Messageable):
|
|||||||
-----------
|
-----------
|
||||||
channel: :class:`VoiceChannel`
|
channel: :class:`VoiceChannel`
|
||||||
The new voice channel to move the member to.
|
The new voice channel to move the member to.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for doing this action. Shows up on the audit log.
|
||||||
"""
|
"""
|
||||||
yield from self.edit(voice_channel=channel)
|
yield from self.edit(voice_channel=channel, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def add_roles(self, *roles):
|
def add_roles(self, *roles, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Gives the member a number of :class:`Role`\s.
|
Gives the member a number of :class:`Role`\s.
|
||||||
@ -481,6 +485,8 @@ class Member(discord.abc.Messageable):
|
|||||||
-----------
|
-----------
|
||||||
\*roles
|
\*roles
|
||||||
An argument list of :class:`Role`\s to give the member.
|
An argument list of :class:`Role`\s to give the member.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for adding these roles. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -491,10 +497,10 @@ class Member(discord.abc.Messageable):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
new_roles = utils._unique(r for s in (self.roles[1:], roles) for r in s)
|
new_roles = utils._unique(r for s in (self.roles[1:], roles) for r in s)
|
||||||
yield from self.edit(roles=new_roles)
|
yield from self.edit(roles=new_roles, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def remove_roles(self, *roles):
|
def remove_roles(self, *roles, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Removes :class:`Role`\s from this member.
|
Removes :class:`Role`\s from this member.
|
||||||
@ -506,6 +512,8 @@ class Member(discord.abc.Messageable):
|
|||||||
-----------
|
-----------
|
||||||
\*roles
|
\*roles
|
||||||
An argument list of :class:`Role`\s to remove from the member.
|
An argument list of :class:`Role`\s to remove from the member.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for removing these roles. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -522,4 +530,4 @@ class Member(discord.abc.Messageable):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
yield from self.edit(roles=new_roles)
|
yield from self.edit(roles=new_roles, reason=reason)
|
||||||
|
@ -407,7 +407,7 @@ class Message:
|
|||||||
return '{0.author.name} started a call \N{EM DASH} Join the call.'.format(self)
|
return '{0.author.name} started a call \N{EM DASH} Join the call.'.format(self)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def delete(self):
|
def delete(self, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Deletes the message.
|
Deletes the message.
|
||||||
@ -416,6 +416,11 @@ class Message:
|
|||||||
delete other people's messages, you need the :attr:`Permissions.manage_messages`
|
delete other people's messages, you need the :attr:`Permissions.manage_messages`
|
||||||
permission.
|
permission.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
------------
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for deleting this message. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
------
|
------
|
||||||
Forbidden
|
Forbidden
|
||||||
@ -423,7 +428,7 @@ class Message:
|
|||||||
HTTPException
|
HTTPException
|
||||||
Deleting the message failed.
|
Deleting the message failed.
|
||||||
"""
|
"""
|
||||||
yield from self._state.http.delete_message(self.channel.id, self.id)
|
yield from self._state.http.delete_message(self.channel.id, self.id, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def edit(self, **fields):
|
def edit(self, **fields):
|
||||||
|
@ -160,7 +160,7 @@ class Role(Hashable):
|
|||||||
return [member for member in all_members if self in member.roles]
|
return [member for member in all_members if self in member.roles]
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _move(self, position):
|
def _move(self, position, reason):
|
||||||
if position <= 0:
|
if position <= 0:
|
||||||
raise InvalidArgument("Cannot move role to position 0 or below")
|
raise InvalidArgument("Cannot move role to position 0 or below")
|
||||||
|
|
||||||
@ -184,10 +184,10 @@ class Role(Hashable):
|
|||||||
roles.append(self.id)
|
roles.append(self.id)
|
||||||
|
|
||||||
payload = [{"id": z[0], "position": z[1]} for z in zip(roles, change_range)]
|
payload = [{"id": z[0], "position": z[1]} for z in zip(roles, change_range)]
|
||||||
yield from http.move_role_position(self.guild.id, payload)
|
yield from http.move_role_position(self.guild.id, payload, reason=reason)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def edit(self, **fields):
|
def edit(self, *, reason=None, **fields):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Edits the role.
|
Edits the role.
|
||||||
@ -212,6 +212,8 @@ class Role(Hashable):
|
|||||||
position: int
|
position: int
|
||||||
The new role's position. This must be below your top role's
|
The new role's position. This must be below your top role's
|
||||||
position or it will fail.
|
position or it will fail.
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for editing this role. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
-------
|
-------
|
||||||
@ -226,7 +228,7 @@ class Role(Hashable):
|
|||||||
|
|
||||||
position = fields.get('position')
|
position = fields.get('position')
|
||||||
if position is not None:
|
if position is not None:
|
||||||
yield from self._move(position)
|
yield from self._move(position, reason=reason)
|
||||||
self.position = position
|
self.position = position
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -242,11 +244,11 @@ class Role(Hashable):
|
|||||||
'mentionable': fields.get('mentionable', self.mentionable)
|
'mentionable': fields.get('mentionable', self.mentionable)
|
||||||
}
|
}
|
||||||
|
|
||||||
data = yield from self._state.http.edit_role(self.guild.id, self.id, **payload)
|
data = yield from self._state.http.edit_role(self.guild.id, self.id, reason=reason, **payload)
|
||||||
self._update(data)
|
self._update(data)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def delete(self):
|
def delete(self, *, reason=None):
|
||||||
"""|coro|
|
"""|coro|
|
||||||
|
|
||||||
Deletes the role.
|
Deletes the role.
|
||||||
@ -254,6 +256,11 @@ class Role(Hashable):
|
|||||||
You must have the :attr:`Permissions.manage_roles` permission to
|
You must have the :attr:`Permissions.manage_roles` permission to
|
||||||
use this.
|
use this.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
-----------
|
||||||
|
reason: Optional[str]
|
||||||
|
The reason for deleting this role. Shows up on the audit log.
|
||||||
|
|
||||||
Raises
|
Raises
|
||||||
--------
|
--------
|
||||||
Forbidden
|
Forbidden
|
||||||
@ -262,4 +269,4 @@ class Role(Hashable):
|
|||||||
Deleting the role failed.
|
Deleting the role failed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self._state.http.delete_role(self.guild.id, self.id)
|
yield from self._state.http.delete_role(self.guild.id, self.id, reason=reason)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user