aboutsummaryrefslogtreecommitdiff
path: root/discord/server.py
diff options
context:
space:
mode:
authorRapptz <[email protected]>2016-10-17 18:25:23 -0400
committerRapptz <[email protected]>2017-01-03 09:51:54 -0500
commitd1d54a468a88323a8ef7798ff084a1371d5893ec (patch)
tree21dd315df95acd2c8d6cf63cc51fa4cadc0c7155 /discord/server.py
parentStateful Message and remove Invite.xkcd since it is removed. (diff)
downloaddiscord.py-d1d54a468a88323a8ef7798ff084a1371d5893ec.tar.xz
discord.py-d1d54a468a88323a8ef7798ff084a1371d5893ec.zip
Rename Server to Guild everywhere.
Diffstat (limited to 'discord/server.py')
-rw-r--r--discord/server.py375
1 files changed, 0 insertions, 375 deletions
diff --git a/discord/server.py b/discord/server.py
deleted file mode 100644
index d1523d6f..00000000
--- a/discord/server.py
+++ /dev/null
@@ -1,375 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""
-The MIT License (MIT)
-
-Copyright (c) 2015-2016 Rapptz
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-"""
-
-from . import utils
-from .role import Role
-from .member import Member, VoiceState
-from .emoji import Emoji
-from .game import Game
-from .channel import *
-from .enums import ServerRegion, Status, ChannelType, try_enum, VerificationLevel
-from .mixins import Hashable
-
-import copy
-
-class Server(Hashable):
- """Represents a Discord server.
-
- Supported Operations:
-
- +-----------+--------------------------------------+
- | Operation | Description |
- +===========+======================================+
- | x == y | Checks if two servers are equal. |
- +-----------+--------------------------------------+
- | x != y | Checks if two servers are not equal. |
- +-----------+--------------------------------------+
- | hash(x) | Returns the server's hash. |
- +-----------+--------------------------------------+
- | str(x) | Returns the server's name. |
- +-----------+--------------------------------------+
-
- Attributes
- ----------
- name: str
- The server name.
- me: :class:`Member`
- Similar to :attr:`Client.user` except an instance of :class:`Member`.
- This is essentially used to get the member version of yourself.
- roles
- A list of :class:`Role` that the server has available.
- emojis
- A list of :class:`Emoji` that the server owns.
- region: :class:`ServerRegion`
- The region the server belongs on. There is a chance that the region
- will be a ``str`` if the value is not recognised by the enumerator.
- afk_timeout: int
- The timeout to get sent to the AFK channel.
- afk_channel: :class:`Channel`
- The channel that denotes the AFK channel. None if it doesn't exist.
- members
- An iterable of :class:`Member` that are currently on the server.
- channels
- An iterable of :class:`Channel` that are currently on the server.
- icon: str
- The server's icon.
- id: int
- The server's ID.
- owner_id: int
- The server owner's ID. Use :attr:`Server.owner` instead.
- unavailable: bool
- Indicates if the server is unavailable. If this is ``True`` then the
- reliability of other attributes outside of :meth:`Server.id` is slim and they might
- all be None. It is best to not do anything with the server if it is unavailable.
-
- Check the :func:`on_server_unavailable` and :func:`on_server_available` events.
- large: bool
- Indicates if the server is a 'large' server. A large server is defined as having
- more than ``large_threshold`` count members, which for this library is set to
- the maximum of 250.
- voice_client: Optional[:class:`VoiceClient`]
- The VoiceClient associated with this server. A shortcut for the
- :meth:`Client.voice_client_in` call.
- mfa_level: int
- Indicates the server's two factor authorisation level. If this value is 0 then
- the server does not require 2FA for their administrative members. If the value is
- 1 then they do.
- verification_level: :class:`VerificationLevel`
- The server's verification level.
- features: List[str]
- A list of features that the server has. They are currently as follows:
-
- - ``VIP_REGIONS``: Server has VIP voice regions
- - ``VANITY_URL``: Server has a vanity invite URL (e.g. discord.gg/discord-api)
- - ``INVITE_SPLASH``: Server's invite page has a special splash.
-
- splash: str
- The server's invite splash.
- """
-
- __slots__ = ('afk_timeout', 'afk_channel', '_members', '_channels', 'icon',
- 'name', 'id', 'unavailable', 'name', 'region',
- '_default_role', '_default_channel', 'roles', '_member_count',
- 'large', 'owner_id', 'mfa_level', 'emojis', 'features',
- 'verification_level', 'splash', '_voice_states' )
-
- def __init__(self, *, data, state):
- self._channels = {}
- self._members = {}
- self._voice_states = {}
- self._state = state
- self._from_data(data)
-
- @property
- def channels(self):
- return self._channels.values()
-
- def get_channel(self, channel_id):
- """Returns a :class:`Channel` with the given ID. If not found, returns None."""
- return self._channels.get(channel_id)
-
- def _add_channel(self, channel):
- self._channels[channel.id] = channel
-
- def _remove_channel(self, channel):
- self._channels.pop(channel.id, None)
-
- def _voice_state_for(self, user_id):
- return self._voice_states.get(user_id)
-
- @property
- def members(self):
- return self._members.values()
-
- def get_member(self, user_id):
- """Returns a :class:`Member` with the given ID. If not found, returns None."""
- return self._members.get(user_id)
-
- def _add_member(self, member):
- self._members[member.id] = member
-
- def _remove_member(self, member):
- self._members.pop(member.id, None)
-
- def __str__(self):
- return self.name
-
- def _update_voice_state(self, data, channel_id):
- user_id = int(data['user_id'])
- channel = self.get_channel(channel_id)
- try:
- # check if we should remove the voice state from cache
- if channel is None:
- after = self._voice_states.pop(user_id)
- else:
- after = self._voice_states[user_id]
-
- before = copy.copy(after)
- after._update(data, channel)
- except KeyError:
- # if we're here then we're getting added into the cache
- after = VoiceState(data=data, channel=channel)
- before = VoiceState(data=data, channel=None)
- self._voice_states[user_id] = after
-
- member = self.get_member(user_id)
- if member is not None:
- old = before.channel
- # update the references pointed to by the voice channels
- if old is None and channel is not None:
- # we joined a channel
- channel.voice_members.append(member)
- elif old is not None:
- try:
- # we either left a channel or switched channels
- old.voice_members.remove(member)
- except ValueError:
- pass
- finally:
- # we switched channels
- if channel is not None:
- channel.voice_members.append(self)
-
- return member, before, after
-
- def _add_role(self, role):
- # roles get added to the bottom (position 1, pos 0 is @everyone)
- # so since self.roles has the @everyone role, we can't increment
- # its position because it's stuck at position 0. Luckily x += False
- # is equivalent to adding 0. So we cast the position to a bool and
- # increment it.
- for r in self.roles:
- r.position += bool(r.position)
-
- self.roles.append(role)
-
- def _remove_role(self, role):
- # this raises ValueError if it fails..
- self.roles.remove(role)
-
- # since it didn't, we can change the positions now
- # basically the same as above except we only decrement
- # the position if we're above the role we deleted.
- for r in self.roles:
- r.position -= r.position > role.position
-
- def _from_data(self, guild):
- # according to Stan, this is always available even if the guild is unavailable
- # I don't have this guarantee when someone updates the server.
- member_count = guild.get('member_count', None)
- if member_count:
- self._member_count = member_count
-
- self.name = guild.get('name')
- self.region = try_enum(ServerRegion, guild.get('region'))
- self.verification_level = try_enum(VerificationLevel, guild.get('verification_level'))
- self.afk_timeout = guild.get('afk_timeout')
- self.icon = guild.get('icon')
- self.unavailable = guild.get('unavailable', False)
- self.id = int(guild['id'])
- self.roles = [Role(server=self, data=r, state=self._state) for r in guild.get('roles', [])]
- self.mfa_level = guild.get('mfa_level')
- self.emojis = [Emoji(server=self, data=r, state=self._state) for r in guild.get('emojis', [])]
- self.features = guild.get('features', [])
- self.splash = guild.get('splash')
-
- for mdata in guild.get('members', []):
- roles = [self.default_role]
- for role_id in mdata['roles']:
- role = utils.find(lambda r: r.id == role_id, self.roles)
- if role is not None:
- roles.append(role)
-
- mdata['roles'] = roles
- member = Member(data=mdata, server=self, state=self._state)
- self._add_member(member)
-
- self._sync(guild)
- self.large = None if member_count is None else self._member_count >= 250
-
- self.owner_id = utils._get_as_snowflake(guild, 'owner_id')
- self.afk_channel = self.get_channel(utils._get_as_snowflake(guild, 'afk_channel_id'))
-
- for obj in guild.get('voice_states', []):
- self._update_voice_state(obj, int(obj['channel_id']))
-
- def _sync(self, data):
- try:
- self.large = data['large']
- except KeyError:
- pass
-
- for presence in data.get('presences', []):
- user_id = int(presence['user']['id'])
- member = self.get_member(user_id)
- if member is not None:
- member.status = try_enum(Status, presence['status'])
- game = presence.get('game', {})
- member.game = Game(**game) if game else None
-
- if 'channels' in data:
- channels = data['channels']
- for c in channels:
- if c['type'] == ChannelType.text.value:
- channel = TextChannel(server=self, data=c, state=self._state)
- else:
- channel = VoiceChannel(server=self, data=c, state=self._state)
-
- self._add_channel(channel)
-
- @utils.cached_slot_property('_default_role')
- def default_role(self):
- """Gets the @everyone role that all members have by default."""
- return utils.find(lambda r: r.is_everyone, self.roles)
-
- @utils.cached_slot_property('_default_channel')
- def default_channel(self):
- """Gets the default :class:`Channel` for the server."""
- return utils.find(lambda c: c.is_default, self.channels)
-
- @property
- def owner(self):
- """:class:`Member`: The member that owns the server."""
- return self.get_member(self.owner_id)
-
- @property
- def icon_url(self):
- """Returns the URL version of the server's icon. Returns an empty string if it has no icon."""
- if self.icon is None:
- return ''
- return 'https://discordapp.com/api/guilds/{0.id}/icons/{0.icon}.jpg'.format(self)
-
- @property
- def splash_url(self):
- """Returns the URL version of the server's invite splash. Returns an empty string if it has no splash."""
- if self.splash is None:
- return ''
- return 'https://cdn.discordapp.com/splashes/{0.id}/{0.splash}.jpg?size=2048'.format(self)
-
- @property
- def member_count(self):
- """Returns the true member count regardless of it being loaded fully or not."""
- return self._member_count
-
- @property
- def created_at(self):
- """Returns the server's creation time in UTC."""
- return utils.snowflake_time(self.id)
-
- @property
- def role_hierarchy(self):
- """Returns the server's roles in the order of the hierarchy.
-
- The first element of this list will be the highest role in the
- hierarchy.
- """
- return sorted(self.roles, reverse=True)
-
- def get_member_named(self, name):
- """Returns the first member found that matches the name provided.
-
- The name can have an optional discriminator argument, e.g. "Jake#0001"
- or "Jake" will both do the lookup. However the former will give a more
- precise result. Note that the discriminator must have all 4 digits
- for this to work.
-
- If a nickname is passed, then it is looked up via the nickname. Note
- however, that a nickname + discriminator combo will not lookup the nickname
- but rather the username + discriminator combo due to nickname + discriminator
- not being unique.
-
- If no member is found, ``None`` is returned.
-
- Parameters
- -----------
- name: str
- The name of the member to lookup with an optional discriminator.
-
- Returns
- --------
- :class:`Member`
- The member in this server with the associated name. If not found
- then ``None`` is returned.
- """
-
- result = None
- members = self.members
- if len(name) > 5 and name[-5] == '#':
- # The 5 length is checking to see if #0000 is in the string,
- # as a#0000 has a length of 6, the minimum for a potential
- # discriminator lookup.
- potential_discriminator = name[-4:]
-
- # do the actual lookup and return if found
- # if it isn't found then we'll do a full name lookup below.
- result = utils.get(members, name=name[:-5], discriminator=potential_discriminator)
- if result is not None:
- return result
-
- def pred(m):
- return m.nick == name or m.name == name
-
- return utils.find(pred, members)