Browse Source

Move message creation to a factory method inside ConnectionState.

pull/447/head
Rapptz 8 years ago
parent
commit
98b981848d
  1. 20
      discord/abc.py
  2. 4
      discord/calls.py
  3. 10
      discord/channel.py
  4. 17
      discord/client.py
  5. 5
      discord/embeds.py
  6. 4
      discord/emoji.py
  7. 12
      discord/gateway.py
  8. 28
      discord/guild.py
  9. 8
      discord/http.py
  10. 6
      discord/iterators.py
  11. 8
      discord/member.py
  12. 31
      discord/message.py
  13. 4
      discord/object.py
  14. 41
      discord/state.py

20
discord/abc.py

@ -31,14 +31,12 @@ import asyncio
from collections import namedtuple from collections import namedtuple
from .message import Message
from .iterators import LogsFromIterator from .iterators import LogsFromIterator
from .context_managers import Typing from .context_managers import Typing
from .errors import ClientException, NoMoreMessages, InvalidArgument from .errors import ClientException, NoMoreMessages, InvalidArgument
from .permissions import PermissionOverwrite, Permissions from .permissions import PermissionOverwrite, Permissions
from .role import Role from .role import Role
from . import utils, compat
import discord.utils
class _Undefined: class _Undefined:
def __repr__(self): def __repr__(self):
@ -178,7 +176,7 @@ class GuildChannel:
their default values in the :attr:`Guild.roles` attribute.""" their default values in the :attr:`Guild.roles` attribute."""
ret = [] ret = []
for overwrite in filter(lambda o: o.type == 'role', self._overwrites): for overwrite in filter(lambda o: o.type == 'role', self._overwrites):
role = discord.utils.get(self.guild.roles, id=overwrite.id) role = utils.get(self.guild.roles, id=overwrite.id)
if role is None: if role is None:
continue continue
@ -200,7 +198,7 @@ class GuildChannel:
@property @property
def created_at(self): def created_at(self):
"""Returns the channel's creation time in UTC.""" """Returns the channel's creation time in UTC."""
return discord.utils.snowflake_time(self.id) return utils.snowflake_time(self.id)
def overwrites_for(self, obj): def overwrites_for(self, obj):
"""Returns the channel-specific overwrites for a member or a role. """Returns the channel-specific overwrites for a member or a role.
@ -253,7 +251,7 @@ class GuildChannel:
if ow.type == 'role': if ow.type == 'role':
# accidentally quadratic # accidentally quadratic
target = discord.utils.find(lambda r: r.id == ow.id, self.guild.roles) target = utils.find(lambda r: r.id == ow.id, self.guild.roles)
elif ow.type == 'member': elif ow.type == 'member':
target = self.guild.get_member(ow.id) target = self.guild.get_member(ow.id)
@ -409,7 +407,7 @@ class GuildChannel:
Using :class:`PermissionOverwrite` :: Using :class:`PermissionOverwrite` ::
overwrite = discord.PermissionOverwrite() overwrite = PermissionOverwrite()
overwrite.send_messages = False overwrite.send_messages = False
overwrite.read_messages = True overwrite.read_messages = True
await channel.set_permissions(member, overwrite=overwrite) await channel.set_permissions(member, overwrite=overwrite)
@ -557,7 +555,7 @@ class Messageable(metaclass=abc.ABCMeta):
else: else:
data = yield from state.http.send_message(channel.id, content, guild_id=guild_id, tts=tts, embed=embed) data = yield from state.http.send_message(channel.id, content, guild_id=guild_id, tts=tts, embed=embed)
ret = Message(channel=channel, state=state, data=data) ret = state.create_message(channel=channel, data=data)
if delete_after is not None: if delete_after is not None:
@asyncio.coroutine @asyncio.coroutine
def delete(): def delete():
@ -566,7 +564,7 @@ class Messageable(metaclass=abc.ABCMeta):
yield from ret.delete() yield from ret.delete()
except: except:
pass pass
discord.compat.create_task(delete(), loop=state.loop) compat.create_task(delete(), loop=state.loop)
return ret return ret
@asyncio.coroutine @asyncio.coroutine
@ -630,7 +628,7 @@ class Messageable(metaclass=abc.ABCMeta):
channel = self._get_channel() channel = self._get_channel()
data = yield from self._state.http.get_message(channel.id, id) data = yield from self._state.http.get_message(channel.id, id)
return Message(channel=channel, state=self._state, data=data) return state.create_message(channel=channel, data=data)
@asyncio.coroutine @asyncio.coroutine
def delete_messages(self, messages): def delete_messages(self, messages):
@ -682,7 +680,7 @@ class Messageable(metaclass=abc.ABCMeta):
channel = self._get_channel() channel = self._get_channel()
state = self._state state = self._state
data = yield from state.http.pins_from(channel.id) data = yield from state.http.pins_from(channel.id)
return [Message(channel=channel, state=state, data=m) for m in data] return [state.create_message(channel=channel, data=m) for m in data]
def history(self, *, limit=100, before=None, after=None, around=None, reverse=None): def history(self, *, limit=100, before=None, after=None, around=None, reverse=None):
"""Return an async iterator that enables receiving the destination's message history. """Return an async iterator that enables receiving the destination's message history.

4
discord/calls.py

@ -25,8 +25,8 @@ DEALINGS IN THE SOFTWARE.
""" """
import datetime import datetime
import discord.utils
from . import utils
from .enums import GuildRegion, try_enum from .enums import GuildRegion, try_enum
from .member import VoiceState from .member import VoiceState
@ -48,7 +48,7 @@ class CallMessage:
def __init__(self, message, **kwargs): def __init__(self, message, **kwargs):
self.message = message self.message = message
self.ended_timestamp = discord.utils.parse_time(kwargs.get('ended_timestamp')) self.ended_timestamp = utils.parse_time(kwargs.get('ended_timestamp'))
self.participants = kwargs.get('participants') self.participants = kwargs.get('participants')
@property @property

10
discord/channel.py

@ -29,8 +29,8 @@ from .mixins import Hashable
from .role import Role from .role import Role
from .user import User from .user import User
from .member import Member from .member import Member
from . import utils
import discord.utils
import discord.abc import discord.abc
import copy import copy
@ -277,7 +277,7 @@ class DMChannel(discord.abc.Messageable, Hashable):
@property @property
def created_at(self): def created_at(self):
"""Returns the direct message channel's creation time in UTC.""" """Returns the direct message channel's creation time in UTC."""
return discord.utils.snowflake_time(self.id) return utils.snowflake_time(self.id)
def permissions_for(self, user=None): def permissions_for(self, user=None):
"""Handles permission resolution for a :class:`User`. """Handles permission resolution for a :class:`User`.
@ -351,14 +351,14 @@ class GroupChannel(discord.abc.Messageable, Hashable):
self._update_group(data) self._update_group(data)
def _update_group(self, data): def _update_group(self, data):
owner_id = discord.utils._get_as_snowflake(data, 'owner_id') owner_id = utils._get_as_snowflake(data, 'owner_id')
self.icon = data.get('icon') self.icon = data.get('icon')
self.name = data.get('name') self.name = data.get('name')
if owner_id == self.me.id: if owner_id == self.me.id:
self.owner = self.me self.owner = self.me
else: else:
self.owner = discord.utils.find(lambda u: u.id == owner_id, self.recipients) self.owner = utils.find(lambda u: u.id == owner_id, self.recipients)
def _get_channel(self): def _get_channel(self):
return self return self
@ -389,7 +389,7 @@ class GroupChannel(discord.abc.Messageable, Hashable):
@property @property
def created_at(self): def created_at(self):
"""Returns the channel's creation time in UTC.""" """Returns the channel's creation time in UTC."""
return discord.utils.snowflake_time(self.id) return utils.snowflake_time(self.id)
def permissions_for(self, user): def permissions_for(self, user):
"""Handles permission resolution for a :class:`User`. """Handles permission resolution for a :class:`User`.

17
discord/client.py

@ -33,10 +33,8 @@ from .enums import ChannelType, Status
from .gateway import * from .gateway import *
from .emoji import Emoji from .emoji import Emoji
from .http import HTTPClient from .http import HTTPClient
from .state import ConnectionState
import discord.utils from . import utils, compat
import discord.compat
import discord.state
import asyncio import asyncio
import aiohttp import aiohttp
@ -141,11 +139,8 @@ class Client:
connector = options.pop('connector', None) connector = options.pop('connector', None)
self.http = HTTPClient(connector, loop=self.loop) self.http = HTTPClient(connector, loop=self.loop)
self.connection = discord.state.ConnectionState(dispatch=self.dispatch, self.connection = ConnectionState(dispatch=self.dispatch, chunker=self.request_offline_members,
chunker=self.request_offline_members, syncer=self._syncer, http=self.http, loop=self.loop, **options)
syncer=self._syncer,
http=self.http, loop=self.loop,
**options)
self._closed = asyncio.Event(loop=self.loop) self._closed = asyncio.Event(loop=self.loop)
self._is_logged_in = asyncio.Event(loop=self.loop) self._is_logged_in = asyncio.Event(loop=self.loop)
@ -287,7 +282,7 @@ class Client:
getattr(self, handler)(*args, **kwargs) getattr(self, handler)(*args, **kwargs)
if hasattr(self, method): if hasattr(self, method):
discord.compat.create_task(self._run_event(method, *args, **kwargs), loop=self.loop) compat.create_task(self._run_event(method, *args, **kwargs), loop=self.loop)
@asyncio.coroutine @asyncio.coroutine
def on_error(self, event_method, *args, **kwargs): def on_error(self, event_method, *args, **kwargs):
@ -937,7 +932,7 @@ class Client:
avatar = self.user.avatar avatar = self.user.avatar
else: else:
if avatar_bytes is not None: if avatar_bytes is not None:
avatar = discord.utils._bytes_to_base64_data(avatar_bytes) avatar = utils._bytes_to_base64_data(avatar_bytes)
else: else:
avatar = None avatar = None

5
discord/embeds.py

@ -26,8 +26,7 @@ DEALINGS IN THE SOFTWARE.
import datetime import datetime
import discord.utils from . import utils
from .colour import Colour from .colour import Colour
class _EmptyEmbed: class _EmptyEmbed:
@ -129,7 +128,7 @@ class Embed:
pass pass
try: try:
self._timestamp = discord.utils.parse_time(data['timestamp']) self._timestamp = utils.parse_time(data['timestamp'])
except KeyError: except KeyError:
pass pass

4
discord/emoji.py

@ -27,7 +27,7 @@ DEALINGS IN THE SOFTWARE.
import asyncio import asyncio
from collections import namedtuple from collections import namedtuple
import discord.utils from . import utils
from .mixins import Hashable from .mixins import Hashable
PartialEmoji = namedtuple('PartialEmoji', 'id name') PartialEmoji = namedtuple('PartialEmoji', 'id name')
@ -109,7 +109,7 @@ class Emoji(Hashable):
@property @property
def created_at(self): def created_at(self):
"""Returns the emoji's creation time in UTC.""" """Returns the emoji's creation time in UTC."""
return discord.utils.snowflake_time(self.id) return utils.snowflake_time(self.id)
@property @property
def url(self): def url(self):

12
discord/gateway.py

@ -29,9 +29,7 @@ import websockets
import asyncio import asyncio
import aiohttp import aiohttp
import discord.utils from . import utils, compat
import discord.compat
from .enums import Status, try_enum from .enums import Status, try_enum
from .game import Game from .game import Game
from .errors import GatewayNotFound, ConnectionClosed, InvalidArgument from .errors import GatewayNotFound, ConnectionClosed, InvalidArgument
@ -73,7 +71,7 @@ class KeepAliveHandler(threading.Thread):
data = self.get_payload() data = self.get_payload()
log.debug(self.msg.format(data)) log.debug(self.msg.format(data))
coro = self.ws.send_as_json(data) coro = self.ws.send_as_json(data)
f = discord.compat.run_coroutine_threadsafe(coro, loop=self.ws.loop) f = compat.run_coroutine_threadsafe(coro, loop=self.ws.loop)
try: try:
# block until sending is complete # block until sending is complete
f.result() f.result()
@ -403,7 +401,7 @@ class DiscordWebSocket(websockets.client.WebSocketClientProtocol):
@asyncio.coroutine @asyncio.coroutine
def send_as_json(self, data): def send_as_json(self, data):
try: try:
yield from super().send(discord.utils.to_json(data)) yield from super().send(utils.to_json(data))
except websockets.exceptions.ConnectionClosed as e: except websockets.exceptions.ConnectionClosed as e:
if not self._can_handle_close(e.code): if not self._can_handle_close(e.code):
raise ConnectionClosed(e) from e raise ConnectionClosed(e) from e
@ -431,7 +429,7 @@ class DiscordWebSocket(websockets.client.WebSocketClientProtocol):
} }
} }
sent = discord.utils.to_json(payload) sent = utils.to_json(payload)
log.debug('Sending "{}" to change status'.format(sent)) log.debug('Sending "{}" to change status'.format(sent))
yield from self.send(sent) yield from self.send(sent)
@ -513,7 +511,7 @@ class DiscordVoiceWebSocket(websockets.client.WebSocketClientProtocol):
@asyncio.coroutine @asyncio.coroutine
def send_as_json(self, data): def send_as_json(self, data):
yield from self.send(discord.utils.to_json(data)) yield from self.send(utils.to_json(data))
@classmethod @classmethod
@asyncio.coroutine @asyncio.coroutine

28
discord/guild.py

@ -27,9 +27,7 @@ DEALINGS IN THE SOFTWARE.
import copy import copy
import asyncio import asyncio
from . import utils
import discord.utils
from .role import Role from .role import Role
from .member import Member, VoiceState from .member import Member, VoiceState
from .emoji import Emoji from .emoji import Emoji
@ -230,7 +228,7 @@ class Guild(Hashable):
for mdata in guild.get('members', []): for mdata in guild.get('members', []):
roles = [self.default_role] roles = [self.default_role]
for role_id in mdata['roles']: for role_id in mdata['roles']:
role = discord.utils.find(lambda r: r.id == role_id, self.roles) role = utils.find(lambda r: r.id == role_id, self.roles)
if role is not None: if role is not None:
roles.append(role) roles.append(role)
@ -241,8 +239,8 @@ class Guild(Hashable):
self._sync(guild) self._sync(guild)
self.large = None if member_count is None else self._member_count >= 250 self.large = None if member_count is None else self._member_count >= 250
self.owner_id = discord.utils._get_as_snowflake(guild, 'owner_id') self.owner_id = utils._get_as_snowflake(guild, 'owner_id')
self.afk_channel = self.get_channel(discord.utils._get_as_snowflake(guild, 'afk_channel_id')) self.afk_channel = self.get_channel(utils._get_as_snowflake(guild, 'afk_channel_id'))
for obj in guild.get('voice_states', []): for obj in guild.get('voice_states', []):
self._update_voice_state(obj, int(obj['channel_id'])) self._update_voice_state(obj, int(obj['channel_id']))
@ -299,15 +297,15 @@ class Guild(Hashable):
"""Returns a :class:`Member` with the given ID. If not found, returns None.""" """Returns a :class:`Member` with the given ID. If not found, returns None."""
return self._members.get(user_id) return self._members.get(user_id)
@discord.utils.cached_slot_property('_default_role') @utils.cached_slot_property('_default_role')
def default_role(self): def default_role(self):
"""Gets the @everyone role that all members have by default.""" """Gets the @everyone role that all members have by default."""
return discord.utils.find(lambda r: r.is_everyone, self.roles) return utils.find(lambda r: r.is_everyone, self.roles)
@discord.utils.cached_slot_property('_default_channel') @utils.cached_slot_property('_default_channel')
def default_channel(self): def default_channel(self):
"""Gets the default :class:`Channel` for the guild.""" """Gets the default :class:`Channel` for the guild."""
return discord.utils.find(lambda c: c.is_default, self.channels) return utils.find(lambda c: c.is_default, self.channels)
@property @property
def owner(self): def owner(self):
@ -336,7 +334,7 @@ class Guild(Hashable):
@property @property
def created_at(self): def created_at(self):
"""Returns the guild's creation time in UTC.""" """Returns the guild's creation time in UTC."""
return discord.utils.snowflake_time(self.id) return utils.snowflake_time(self.id)
@property @property
def role_hierarchy(self): def role_hierarchy(self):
@ -384,14 +382,14 @@ class Guild(Hashable):
# do the actual lookup and return if found # do the actual lookup and return if found
# if it isn't found then we'll do a full name lookup below. # if it isn't found then we'll do a full name lookup below.
result = discord.utils.get(members, name=name[:-5], discriminator=potential_discriminator) result = utils.get(members, name=name[:-5], discriminator=potential_discriminator)
if result is not None: if result is not None:
return result return result
def pred(m): def pred(m):
return m.nick == name or m.name == name return m.nick == name or m.name == name
return discord.utils.find(pred, members) return utils.find(pred, members)
@asyncio.coroutine @asyncio.coroutine
@ -475,7 +473,7 @@ class Guild(Hashable):
icon = self.icon icon = self.icon
else: else:
if icon_bytes is not None: if icon_bytes is not None:
icon = discord.utils._bytes_to_base64_data(icon_bytes) icon = utils._bytes_to_base64_data(icon_bytes)
else: else:
icon = None icon = None
@ -665,7 +663,7 @@ class Guild(Hashable):
An error occurred creating an emoji. An error occurred creating an emoji.
""" """
img = discord.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)
return self._state.store_emoji(self, data) return self._state.store_emoji(self, data)

8
discord/http.py

@ -36,9 +36,7 @@ from random import randint as random_integer
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
from .errors import HTTPException, Forbidden, NotFound, LoginFailure, GatewayNotFound from .errors import HTTPException, Forbidden, NotFound, LoginFailure, GatewayNotFound
from . import __version__ from . import __version__, utils
import discord.utils
@asyncio.coroutine @asyncio.coroutine
def json_or_text(response): def json_or_text(response):
@ -99,7 +97,7 @@ class HTTPClient:
# some checking if it's a JSON request # some checking if it's a JSON request
if 'json' in kwargs: if 'json' in kwargs:
headers['Content-Type'] = 'application/json' headers['Content-Type'] = 'application/json'
kwargs['data'] = discord.utils.to_json(kwargs.pop('json')) kwargs['data'] = utils.to_json(kwargs.pop('json'))
kwargs['headers'] = headers kwargs['headers'] = headers
with (yield from lock): with (yield from lock):
@ -246,7 +244,7 @@ class HTTPClient:
if embed: if embed:
payload['embed'] = embed payload['embed'] = embed
form.add_field('payload_json', discord.utils.to_json(payload)) form.add_field('payload_json', utils.to_json(payload))
form.add_field('file', buffer, filename=filename, content_type='application/octet-stream') form.add_field('file', buffer, filename=filename, content_type='application/octet-stream')
return self.post(url, data=form, bucket='messages:' + str(guild_id)) return self.post(url, data=form, bucket='messages:' + str(guild_id))

6
discord/iterators.py

@ -31,7 +31,6 @@ import datetime
from .errors import NoMoreMessages from .errors import NoMoreMessages
from .utils import time_snowflake from .utils import time_snowflake
from .message import Message
from .object import Object from .object import Object
PY35 = sys.version_info >= (3, 5) PY35 = sys.version_info >= (3, 5)
@ -143,8 +142,11 @@ class LogsFromIterator:
data = reversed(data) data = reversed(data)
if self._filter: if self._filter:
data = filter(self._filter, data) data = filter(self._filter, data)
channel = self.channel
state = self.ctx
for element in data: for element in data:
yield from self.messages.put(Message(channel=self.channel, state=self.ctx, data=element)) yield from self.messages.put(state.create_message(channel=channel, data=element))
@asyncio.coroutine @asyncio.coroutine
def _retrieve_messages(self, retrieve): def _retrieve_messages(self, retrieve):

8
discord/member.py

@ -26,7 +26,7 @@ DEALINGS IN THE SOFTWARE.
import asyncio import asyncio
import discord.utils from . import utils
from .user import User from .user import User
from .game import Game from .game import Game
from .permissions import Permissions from .permissions import Permissions
@ -143,7 +143,7 @@ class Member:
def __init__(self, *, data, guild, state): def __init__(self, *, data, guild, state):
self._state = state self._state = state
self._user = state.store_user(data['user']) self._user = state.store_user(data['user'])
self.joined_at = discord.utils.parse_time(data.get('joined_at')) self.joined_at = utils.parse_time(data.get('joined_at'))
self.roles = data.get('roles', []) self.roles = data.get('roles', [])
self.status = Status.offline self.status = Status.offline
game = data.get('game', {}) game = data.get('game', {})
@ -243,7 +243,7 @@ class Member:
return True return True
for role in message.role_mentions: for role in message.role_mentions:
has_role = discord.utils.get(self.roles, id=role.id) is not None has_role = utils.get(self.roles, id=role.id) is not None
if has_role: if has_role:
return True return True
@ -443,7 +443,7 @@ class Member:
Adding roles failed. Adding roles failed.
""" """
new_roles = discord.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)
@asyncio.coroutine @asyncio.coroutine

31
discord/message.py

@ -27,8 +27,9 @@ DEALINGS IN THE SOFTWARE.
import asyncio import asyncio
import re import re
import discord.utils
import discord.abc import discord.abc
from . import utils
from .user import User from .user import User
from .reaction import Reaction from .reaction import Reaction
from .emoji import Emoji from .emoji import Emoji
@ -136,7 +137,7 @@ class Message:
def _add_reaction(self, data): def _add_reaction(self, data):
emoji = self._state.get_reaction_emoji(data['emoji']) emoji = self._state.get_reaction_emoji(data['emoji'])
reaction = discord.utils.find(lambda r: r.emoji == emoji, self.reactions) reaction = utils.find(lambda r: r.emoji == emoji, self.reactions)
is_me = data['me'] = int(data['user_id']) == self._state.self_id is_me = data['me'] = int(data['user_id']) == self._state.self_id
if reaction is None: if reaction is None:
@ -151,7 +152,7 @@ class Message:
def _remove_reaction(self, data): def _remove_reaction(self, data):
emoji = self._state.get_reaction_emoji(data['emoji']) emoji = self._state.get_reaction_emoji(data['emoji'])
reaction = discord.utils.find(lambda r: r.emoji == emoji, self.reactions) reaction = utils.find(lambda r: r.emoji == emoji, self.reactions)
if reaction is None: if reaction is None:
# already removed? # already removed?
@ -177,7 +178,7 @@ class Message:
except KeyError: except KeyError:
continue continue
self._try_patch(data, 'edited_timestamp', discord.utils.parse_time) self._try_patch(data, 'edited_timestamp', utils.parse_time)
self._try_patch(data, 'pinned', bool) self._try_patch(data, 'pinned', bool)
self._try_patch(data, 'mention_everyone', bool) self._try_patch(data, 'mention_everyone', bool)
self._try_patch(data, 'tts', bool) self._try_patch(data, 'tts', bool)
@ -218,7 +219,7 @@ class Message:
self.role_mentions = [] self.role_mentions = []
if self.guild is not None: if self.guild is not None:
for role_id in role_mentions: for role_id in role_mentions:
role = discord.utils.get(self.guild.roles, id=role_id) role = utils.get(self.guild.roles, id=role_id)
if role is not None: if role is not None:
self.role_mentions.append(role) self.role_mentions.append(role)
@ -235,19 +236,19 @@ class Message:
if uid == self.author.id: if uid == self.author.id:
participants.append(self.author) participants.append(self.author)
else: else:
user = discord.utils.find(lambda u: u.id == uid, self.mentions) user = utils.find(lambda u: u.id == uid, self.mentions)
if user is not None: if user is not None:
participants.append(user) participants.append(user)
call['participants'] = participants call['participants'] = participants
self.call = CallMessage(message=self, **call) self.call = CallMessage(message=self, **call)
@discord.utils.cached_slot_property('_cs_guild') @utils.cached_slot_property('_cs_guild')
def guild(self): def guild(self):
"""Optional[:class:`Guild`]: The guild that the message belongs to, if applicable.""" """Optional[:class:`Guild`]: The guild that the message belongs to, if applicable."""
return getattr(self.channel, 'guild', None) return getattr(self.channel, 'guild', None)
@discord.utils.cached_slot_property('_cs_raw_mentions') @utils.cached_slot_property('_cs_raw_mentions')
def raw_mentions(self): def raw_mentions(self):
"""A property that returns an array of user IDs matched with """A property that returns an array of user IDs matched with
the syntax of <@user_id> in the message content. the syntax of <@user_id> in the message content.
@ -257,28 +258,28 @@ class Message:
""" """
return [int(x) for x in re.findall(r'<@!?([0-9]+)>', self.content)] return [int(x) for x in re.findall(r'<@!?([0-9]+)>', self.content)]
@discord.utils.cached_slot_property('_cs_raw_channel_mentions') @utils.cached_slot_property('_cs_raw_channel_mentions')
def raw_channel_mentions(self): def raw_channel_mentions(self):
"""A property that returns an array of channel IDs matched with """A property that returns an array of channel IDs matched with
the syntax of <#channel_id> in the message content. the syntax of <#channel_id> in the message content.
""" """
return [int(x) for x in re.findall(r'<#([0-9]+)>', self.content)] return [int(x) for x in re.findall(r'<#([0-9]+)>', self.content)]
@discord.utils.cached_slot_property('_cs_raw_role_mentions') @utils.cached_slot_property('_cs_raw_role_mentions')
def raw_role_mentions(self): def raw_role_mentions(self):
"""A property that returns an array of role IDs matched with """A property that returns an array of role IDs matched with
the syntax of <@&role_id> in the message content. the syntax of <@&role_id> in the message content.
""" """
return [int(x) for x in re.findall(r'<@&([0-9]+)>', self.content)] return [int(x) for x in re.findall(r'<@&([0-9]+)>', self.content)]
@discord.utils.cached_slot_property('_cs_channel_mentions') @utils.cached_slot_property('_cs_channel_mentions')
def channel_mentions(self): def channel_mentions(self):
if self.guild is None: if self.guild is None:
return [] return []
it = filter(None, map(lambda m: self.guild.get_channel(m), self.raw_channel_mentions)) it = filter(None, map(lambda m: self.guild.get_channel(m), self.raw_channel_mentions))
return discord.utils._unique(it) return utils._unique(it)
@discord.utils.cached_slot_property('_cs_clean_content') @utils.cached_slot_property('_cs_clean_content')
def clean_content(self): def clean_content(self):
"""A property that returns the content in a "cleaned up" """A property that returns the content in a "cleaned up"
manner. This basically means that mentions are transformed manner. This basically means that mentions are transformed
@ -352,9 +353,9 @@ class Message:
@property @property
def created_at(self): def created_at(self):
"""Returns the message's creation time in UTC.""" """Returns the message's creation time in UTC."""
return discord.utils.snowflake_time(self.id) return utils.snowflake_time(self.id)
@discord.utils.cached_slot_property('_cs_system_content') @utils.cached_slot_property('_cs_system_content')
def system_content(self): def system_content(self):
"""A property that returns the content that is rendered """A property that returns the content that is rendered
regardless of the :attr:`Message.type`. regardless of the :attr:`Message.type`.

4
discord/object.py

@ -23,7 +23,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
""" """
import discord.utils from . import utils
class Object: class Object:
"""Represents a generic Discord object. """Represents a generic Discord object.
@ -51,4 +51,4 @@ class Object:
@property @property
def created_at(self): def created_at(self):
"""Returns the snowflake's creation time in UTC.""" """Returns the snowflake's creation time in UTC."""
return discord.utils.snowflake_time(self.id) return utils.snowflake_time(self.id)

41
discord/state.py

@ -35,9 +35,7 @@ from .member import Member
from .role import Role from .role import Role
from .enums import Status, ChannelType, try_enum from .enums import Status, ChannelType, try_enum
from .calls import GroupCall from .calls import GroupCall
from . import utils, compat
import discord.utils
import discord.compat
from collections import deque, namedtuple from collections import deque, namedtuple
import copy, enum, math import copy, enum, math
@ -177,7 +175,7 @@ class ConnectionState:
self._private_channels_by_user.pop(channel.recipient.id, None) self._private_channels_by_user.pop(channel.recipient.id, None)
def _get_message(self, msg_id): def _get_message(self, msg_id):
return discord.utils.find(lambda m: m.id == msg_id, self.messages) return utils.find(lambda m: m.id == msg_id, self.messages)
def _add_guild_from_data(self, guild): def _add_guild_from_data(self, guild):
guild = Guild(data=guild, state=self) guild = Guild(data=guild, state=self)
@ -247,7 +245,7 @@ class ConnectionState:
factory, _ = _channel_factory(pm['type']) factory, _ = _channel_factory(pm['type'])
self._add_private_channel(factory(me=self.user, data=pm, state=self)) self._add_private_channel(factory(me=self.user, data=pm, state=self))
discord.compat.create_task(self._delay_ready(), loop=self.loop) compat.create_task(self._delay_ready(), loop=self.loop)
def parse_resumed(self, data): def parse_resumed(self, data):
self.dispatch('resumed') self.dispatch('resumed')
@ -313,7 +311,7 @@ class ConnectionState:
self.dispatch('reaction_remove', reaction, user) self.dispatch('reaction_remove', reaction, user)
def parse_presence_update(self, data): def parse_presence_update(self, data):
guild = self._get_guild(discord.utils._get_as_snowflake(data, 'guild_id')) guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
if guild is None: if guild is None:
return return
@ -338,7 +336,7 @@ class ConnectionState:
self.user = User(state=self, data=data) self.user = User(state=self, data=data)
def parse_channel_delete(self, data): def parse_channel_delete(self, data):
guild = self._get_guild(discord.utils._get_as_snowflake(data, 'guild_id')) guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
channel_id = int(data['id']) channel_id = int(data['id'])
if guild is not None: if guild is not None:
channel = guild.get_channel(channel_id) channel = guild.get_channel(channel_id)
@ -361,7 +359,7 @@ class ConnectionState:
self.dispatch('channel_update', old_channel, channel) self.dispatch('channel_update', old_channel, channel)
return return
guild = self._get_guild(discord.utils._get_as_snowflake(data, 'guild_id')) guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
if guild is not None: if guild is not None:
channel = guild.get_channel(channel_id) channel = guild.get_channel(channel_id)
if channel is not None: if channel is not None:
@ -376,7 +374,7 @@ class ConnectionState:
channel = factory(me=self.user, data=data, state=self) channel = factory(me=self.user, data=data, state=self)
self._add_private_channel(channel) self._add_private_channel(channel)
else: else:
guild = self._get_guild(discord.utils._get_as_snowflake(data, 'guild_id')) guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
if guild is not None: if guild is not None:
channel = factory(guild=guild, state=self, data=data) channel = factory(guild=guild, state=self, data=data)
guild._add_channel(channel) guild._add_channel(channel)
@ -402,7 +400,7 @@ class ConnectionState:
def _make_member(self, guild, data): def _make_member(self, guild, data):
roles = [guild.default_role] roles = [guild.default_role]
for roleid in data.get('roles', []): for roleid in data.get('roles', []):
role = discord.utils.get(guild.roles, id=roleid) role = utils.get(guild.roles, id=roleid)
if role is not None: if role is not None:
roles.append(role) roles.append(role)
@ -510,7 +508,7 @@ class ConnectionState:
# since we're not waiting for 'useful' READY we'll just # since we're not waiting for 'useful' READY we'll just
# do the chunk request here # do the chunk request here
discord.compat.create_task(self._chunk_and_dispatch(guild, unavailable), loop=self.loop) compat.create_task(self._chunk_and_dispatch(guild, unavailable), loop=self.loop)
return return
# Dispatch available if newly available # Dispatch available if newly available
@ -557,7 +555,7 @@ class ConnectionState:
guild = self._get_guild(int(data['guild_id'])) guild = self._get_guild(int(data['guild_id']))
if guild is not None: if guild is not None:
user_id = data.get('user', {}).get('id') user_id = data.get('user', {}).get('id')
member = discord.utils.get(guild.members, id=user_id) member = utils.get(guild.members, id=user_id)
if member is not None: if member is not None:
self.dispatch('member_ban', member) self.dispatch('member_ban', member)
@ -579,7 +577,7 @@ class ConnectionState:
guild = self._get_guild(int(data['guild_id'])) guild = self._get_guild(int(data['guild_id']))
if guild is not None: if guild is not None:
role_id = int(data['role_id']) role_id = int(data['role_id'])
role = discord.utils.find(lambda r: r.id == role_id, guild.roles) role = utils.find(lambda r: r.id == role_id, guild.roles)
try: try:
guild._remove_role(role) guild._remove_role(role)
except ValueError: except ValueError:
@ -592,7 +590,7 @@ class ConnectionState:
if guild is not None: if guild is not None:
role_data = data['role'] role_data = data['role']
role_id = int(role_data['id']) role_id = int(role_data['id'])
role = discord.utils.find(lambda r: r.id == role_id, guild.roles) role = utils.find(lambda r: r.id == role_id, guild.roles)
if role is not None: if role is not None:
old_role = copy.copy(role) old_role = copy.copy(role)
role._update(role_data) role._update(role_data)
@ -611,8 +609,8 @@ class ConnectionState:
self.process_listeners(ListenerType.chunk, guild, len(members)) self.process_listeners(ListenerType.chunk, guild, len(members))
def parse_voice_state_update(self, data): def parse_voice_state_update(self, data):
guild = self._get_guild(discord.utils._get_as_snowflake(data, 'guild_id')) guild = self._get_guild(utils._get_as_snowflake(data, 'guild_id'))
channel_id = discord.utils._get_as_snowflake(data, 'channel_id') channel_id = utils._get_as_snowflake(data, 'channel_id')
if guild is not None: if guild is not None:
if int(data['user_id']) == self.user.id: if int(data['user_id']) == self.user.id:
voice = self._get_voice_client(guild.id) voice = self._get_voice_client(guild.id)
@ -632,13 +630,13 @@ class ConnectionState:
channel = self.get_channel(int(data['channel_id'])) channel = self.get_channel(int(data['channel_id']))
if channel is not None: if channel is not None:
member = None member = None
user_id = discord.utils._get_as_snowflake(data, 'user_id') user_id = utils._get_as_snowflake(data, 'user_id')
if isinstance(channel, DMChannel): if isinstance(channel, DMChannel):
member = channel.recipient member = channel.recipient
elif isinstance(channel, TextChannel): elif isinstance(channel, TextChannel):
member = channel.guild.get_member(user_id) member = channel.guild.get_member(user_id)
elif isinstance(channel, GroupChannel): elif isinstance(channel, GroupChannel):
member = discord.utils.find(lambda x: x.id == user_id, channel.recipients) member = utils.find(lambda x: x.id == user_id, channel.recipients)
if member is not None: if member is not None:
timestamp = datetime.datetime.utcfromtimestamp(data.get('timestamp')) timestamp = datetime.datetime.utcfromtimestamp(data.get('timestamp'))
@ -669,12 +667,12 @@ class ConnectionState:
elif isinstance(channel, TextChannel): elif isinstance(channel, TextChannel):
return channel.guild.get_member(user_id) return channel.guild.get_member(user_id)
elif isinstance(channel, GroupChannel): elif isinstance(channel, GroupChannel):
return discord.utils.find(lambda m: m.id == user_id, channel.recipients) return utils.find(lambda m: m.id == user_id, channel.recipients)
else: else:
return None return None
def get_reaction_emoji(self, data): def get_reaction_emoji(self, data):
emoji_id = discord.utils._get_as_snowflake(data, 'id') emoji_id = utils._get_as_snowflake(data, 'id')
if not emoji_id: if not emoji_id:
return data['name'] return data['name']
@ -697,6 +695,9 @@ class ConnectionState:
if pm is not None: if pm is not None:
return pm return pm
def create_message(self, *, channel, data):
return Message(state=self, channel=channel, data=data)
def receive_chunk(self, guild_id): def receive_chunk(self, guild_id):
future = asyncio.Future(loop=self.loop) future = asyncio.Future(loop=self.loop)
listener = Listener(ListenerType.chunk, future, lambda s: s.id == guild_id) listener = Listener(ListenerType.chunk, future, lambda s: s.id == guild_id)

Loading…
Cancel
Save