Make emojis and members stateful.
This commit is contained in:
parent
a7a60e433b
commit
5cb3ad14e8
@ -355,7 +355,8 @@ class TextChannel(abc.MessageChannel, CommonGuildChannel):
|
||||
|
||||
Edits the channel.
|
||||
|
||||
You must have the Manage Channel permission to use this.
|
||||
You must have the :attr:`Permissions.manage_channel` permission to
|
||||
use this.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@ -446,7 +447,8 @@ class VoiceChannel(CommonGuildChannel):
|
||||
|
||||
Edits the channel.
|
||||
|
||||
You must have the Manage Channel permission to use this.
|
||||
You must have the :attr:`Permissions.manage_channel` permission to
|
||||
use this.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
@ -24,6 +24,8 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
from . import utils
|
||||
from .mixins import Hashable
|
||||
|
||||
@ -107,3 +109,51 @@ class Emoji(Hashable):
|
||||
def url(self):
|
||||
"""Returns a URL version of the emoji."""
|
||||
return "https://discordapp.com/api/emojis/{0.id}.png".format(self)
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def delete(self):
|
||||
"""|coro|
|
||||
|
||||
Deletes the custom emoji.
|
||||
|
||||
You must have :attr:`Permissions.manage_emojis` permission to
|
||||
do this.
|
||||
|
||||
Guild local emotes can only be deleted by user bots.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You are not allowed to delete emojis.
|
||||
HTTPException
|
||||
An error occurred deleting the emoji.
|
||||
"""
|
||||
|
||||
yield from self._state.http.delete_custom_emoji(self.guild.id, self.id)
|
||||
|
||||
@asyncio.coroutine
|
||||
def edit(self, *, name):
|
||||
"""|coro|
|
||||
|
||||
Edits the custom emoji.
|
||||
|
||||
You must have :attr:`Permissions.manage_emojis` permission to
|
||||
do this.
|
||||
|
||||
Guild local emotes can only be edited by user bots.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
name: str
|
||||
The new emoji name.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You are not allowed to edit emojis.
|
||||
HTTPException
|
||||
An error occurred editing the emoji.
|
||||
"""
|
||||
|
||||
yield from self._state.http.edit_custom_emoji(self.guild.id, self.id, name=name)
|
||||
|
@ -680,3 +680,81 @@ class Guild(Hashable):
|
||||
|
||||
# TODO: add to cache
|
||||
return role
|
||||
|
||||
@asyncio.coroutine
|
||||
def kick(self, user):
|
||||
"""|coro|
|
||||
|
||||
Kicks a user from the guild.
|
||||
|
||||
The user must meet the :class:`abc.Snowflake` abc.
|
||||
|
||||
You must have :attr:`Permissions.kick_members` permissions to
|
||||
do this.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
user: :class:`abc.Snowflake`
|
||||
The user to kick from their guild.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You do not have the proper permissions to kick.
|
||||
HTTPException
|
||||
Kicking failed.
|
||||
"""
|
||||
yield from self._state.http.kick(user.id, self.id)
|
||||
|
||||
@asyncio.coroutine
|
||||
def ban(self, user, *, delete_message_days=1):
|
||||
"""|coro|
|
||||
|
||||
Bans a user from the guild.
|
||||
|
||||
The user must meet the :class:`abc.Snowflake` abc.
|
||||
|
||||
You must have :attr:`Permissions.ban_members` permissions to
|
||||
do this.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
user: :class:`abc.Snowflake`
|
||||
The user to ban from their guild.
|
||||
delete_message_days: int
|
||||
The number of days worth of messages to delete from the user
|
||||
in the guild. The minimum is 0 and the maximum is 7.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You do not have the proper permissions to ban.
|
||||
HTTPException
|
||||
Banning failed.
|
||||
"""
|
||||
yield from self._state.http.ban(user.id, self.id, delete_message_days)
|
||||
|
||||
@asyncio.coroutine
|
||||
def unban(self, user):
|
||||
"""|coro|
|
||||
|
||||
Unbans a user from the guild.
|
||||
|
||||
The user must meet the :class:`abc.Snowflake` abc.
|
||||
|
||||
You must have :attr:`Permissions.ban_members` permissions to
|
||||
do this.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
user: :class:`abc.Snowflake`
|
||||
The user to unban.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You do not have the proper permissions to unban.
|
||||
HTTPException
|
||||
Unbanning failed.
|
||||
"""
|
||||
yield from self._state.http.unban(user.id, self.id)
|
||||
|
@ -383,6 +383,11 @@ class HTTPClient:
|
||||
bucket = 'members:{}'.format(guild_id)
|
||||
return self.patch(url, json=payload, bucket=bucket)
|
||||
|
||||
def edit_member(self, guild_id, user_id, **fields):
|
||||
url = '{0.GUILDS}/{1}/members/{2}'.format(self, guild_id, user_id)
|
||||
bucket = 'members:%s' % guild_id
|
||||
return self.patch(url, json=fields, bucket=bucket)
|
||||
|
||||
# Channel management
|
||||
|
||||
def edit_channel(self, channel_id, **options):
|
||||
|
@ -24,6 +24,8 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
from .user import User
|
||||
from .game import Game
|
||||
from .permissions import Permissions
|
||||
@ -161,16 +163,19 @@ class Member:
|
||||
def __hash__(self):
|
||||
return hash(self._user.id)
|
||||
|
||||
def _update(self, data, user):
|
||||
self._user.name = user['username']
|
||||
self._user.discriminator = user['discriminator']
|
||||
self._user.avatar = user['avatar']
|
||||
self._user.bot = user.get('bot', False)
|
||||
def _update(self, data, user=None):
|
||||
if user:
|
||||
self._user.name = user['username']
|
||||
self._user.discriminator = user['discriminator']
|
||||
self._user.avatar = user['avatar']
|
||||
self._user.bot = user.get('bot', False)
|
||||
|
||||
# the nickname change is optional,
|
||||
# if it isn't in the payload then it didn't change
|
||||
if 'nick' in data:
|
||||
try:
|
||||
self.nick = data['nick']
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# update the roles
|
||||
self.roles = [self.guild.default_role]
|
||||
@ -283,3 +288,187 @@ class Member:
|
||||
def voice(self):
|
||||
"""Optional[:class:`VoiceState`]: Returns the member's current voice state."""
|
||||
return self.guild._voice_state_for(self._user.id)
|
||||
|
||||
@asyncio.coroutine
|
||||
def ban(self):
|
||||
"""|coro|
|
||||
|
||||
Bans this member. Equivalent to :meth:`Guild.ban`
|
||||
"""
|
||||
yield from self.guild.ban(self)
|
||||
|
||||
@asyncio.coroutine
|
||||
def unban(self):
|
||||
"""|coro|
|
||||
|
||||
Unbans this member. Equivalent to :meth:`Guild.unban`
|
||||
"""
|
||||
yield from self.guild.unban(self)
|
||||
|
||||
@asyncio.coroutine
|
||||
def kick(self):
|
||||
"""|coro|
|
||||
|
||||
Kicks this member. Equivalent to :meth:`Guild.kick`
|
||||
"""
|
||||
yield from self.guild.kick(self)
|
||||
|
||||
@asyncio.coroutine
|
||||
def edit(self, **fields):
|
||||
"""|coro|
|
||||
|
||||
Edits the member's data.
|
||||
|
||||
Depending on the parameter passed, this requires different permissions listed below:
|
||||
|
||||
+---------------+--------------------------------------+
|
||||
| Parameter | Permission |
|
||||
+---------------+--------------------------------------+
|
||||
| nick | :attr:`Permissions.manage_nicknames` |
|
||||
+---------------+--------------------------------------+
|
||||
| mute | :attr:`Permissions.mute_members` |
|
||||
+---------------+--------------------------------------+
|
||||
| deafen | :attr:`Permissions.deafen_members` |
|
||||
+---------------+--------------------------------------+
|
||||
| roles | :attr:`Permissions.manage_roles` |
|
||||
+---------------+--------------------------------------+
|
||||
| voice_channel | :attr:`Permissions.move_members` |
|
||||
+---------------+--------------------------------------+
|
||||
|
||||
All parameters are optional.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
nick: str
|
||||
The member's new nickname. Use ``None`` to remove the nickname.
|
||||
mute: bool
|
||||
Indicates if the member should be guild muted or un-muted.
|
||||
deafen: bool
|
||||
Indicates if the member should be guild deafened or un-deafened.
|
||||
roles: List[:class:`Roles`]
|
||||
The member's new list of roles. This *replaces* the roles.
|
||||
voice_channel: :class:`VoiceChannel`
|
||||
The voice channel to move the member to.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You do not have the proper permissions to the action requested.
|
||||
HTTPException
|
||||
The operation failed.
|
||||
"""
|
||||
http = self._state.http
|
||||
guild_id = self.guild.id
|
||||
payload = {}
|
||||
|
||||
try:
|
||||
nick = fields['nick']
|
||||
except KeyError:
|
||||
# nick not present so...
|
||||
pass
|
||||
else:
|
||||
nick = nick if nick else ''
|
||||
if self._state.self_id == self.id:
|
||||
yield from http.change_my_nickname(guild_id, nick)
|
||||
else:
|
||||
payload['nick'] = nick
|
||||
|
||||
deafen = fields.get('deafen')
|
||||
if deafen is not None:
|
||||
payload['deaf'] = deafen
|
||||
|
||||
mute = fields.get('mute')
|
||||
if mute is not None:
|
||||
payload['mute'] = mute
|
||||
|
||||
try:
|
||||
vc = fields['voice_channel']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
payload['channel_id'] = vc.id
|
||||
|
||||
try:
|
||||
roles = fields['roles']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
payload['roles'] = tuple(r.id for r in roles)
|
||||
|
||||
yield from http.edit_member(guild_id, self.id, **payload)
|
||||
|
||||
# TODO: wait for WS event for modify-in-place behaviour
|
||||
|
||||
@asyncio.coroutine
|
||||
def move_to(self, channel):
|
||||
"""|coro|
|
||||
|
||||
Moves a member to a new voice channel (they must be connected first).
|
||||
|
||||
You must have the :attr:`Permissions.move_members` permission to
|
||||
use this.
|
||||
|
||||
This raises the same exceptions as :meth:`edit`.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
channel: :class:`VoiceChannel`
|
||||
The new voice channel to move the member to.
|
||||
"""
|
||||
yield from self.edit(voice_channel=channel)
|
||||
|
||||
@asyncio.coroutine
|
||||
def add_roles(self, *roles):
|
||||
"""|coro|
|
||||
|
||||
Gives the member a number of :class:`Role`\s.
|
||||
|
||||
You must have the :attr:`Permissions.manage_roles` permission to
|
||||
use this.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
\*roles
|
||||
An argument list of :class:`Role`\s to give the member.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You do not have permissions to add these roles.
|
||||
HTTPException
|
||||
Adding roles failed.
|
||||
"""
|
||||
|
||||
new_roles = utils._unique(r for s in (self.roles[1:], roles) for r in s)
|
||||
yield from self.edit(roles=new_roles)
|
||||
|
||||
@asyncio.coroutine
|
||||
def remove_roles(self, *roles):
|
||||
"""|coro|
|
||||
|
||||
Removes :class:`Role`\s from this member.
|
||||
|
||||
You must have the :attr:`Permissions.manage_roles` permission to
|
||||
use this.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
\*roles
|
||||
An argument list of :class:`Role`\s to remove from the member.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You do not have permissions to remove these roles.
|
||||
HTTPException
|
||||
Removing the roles failed.
|
||||
"""
|
||||
|
||||
new_roles = self.roles[1:] # remove @everyone
|
||||
for role in roles:
|
||||
try:
|
||||
new_roles.remove(role)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
yield from self.edit(roles=new_roles)
|
||||
|
@ -47,7 +47,7 @@ class ListenerType(enum.Enum):
|
||||
chunk = 0
|
||||
|
||||
Listener = namedtuple('Listener', ('type', 'future', 'predicate'))
|
||||
StateContext = namedtuple('StateContext', 'try_insert_user http')
|
||||
StateContext = namedtuple('StateContext', 'try_insert_user http self_id')
|
||||
log = logging.getLogger(__name__)
|
||||
ReadyState = namedtuple('ReadyState', ('launch', 'guilds'))
|
||||
|
||||
@ -60,7 +60,7 @@ class ConnectionState:
|
||||
self.syncer = syncer
|
||||
self.is_bot = None
|
||||
self._listeners = []
|
||||
self.ctx = StateContext(try_insert_user=self.try_insert_user, http=http)
|
||||
self.ctx = StateContext(try_insert_user=self.try_insert_user, http=http, self_id=None)
|
||||
self.clear()
|
||||
|
||||
def clear(self):
|
||||
@ -220,6 +220,7 @@ class ConnectionState:
|
||||
def parse_ready(self, data):
|
||||
self._ready_state = ReadyState(launch=asyncio.Event(), guilds=[])
|
||||
self.user = self.try_insert_user(data['user'])
|
||||
self.ctx.self_id = self.user.id
|
||||
guilds = data.get('guilds')
|
||||
|
||||
guilds = self._ready_state.guilds
|
||||
|
Loading…
x
Reference in New Issue
Block a user