Remove Message.timestamp and make Message.channel_mentions lazy.
Message.timestamp is replaced with Message.created_at. This commit also affects how MESSAGE_UPDATE is handled by only assuming that two keys are provided rather than overwriting data with missing keys.
This commit is contained in:
parent
31229a53e9
commit
aa8a328f0a
@ -39,11 +39,9 @@ class Message:
|
|||||||
|
|
||||||
Attributes
|
Attributes
|
||||||
-----------
|
-----------
|
||||||
edited_timestamp : Optional[datetime.datetime]
|
edited_timestamp: Optional[datetime.datetime]
|
||||||
A naive UTC datetime object containing the edited time of the message.
|
A naive UTC datetime object containing the edited time of the message.
|
||||||
timestamp : datetime.datetime
|
tts: bool
|
||||||
A naive UTC datetime object containing the time the message was created.
|
|
||||||
tts : bool
|
|
||||||
Specifies if the message was done with text-to-speech.
|
Specifies if the message was done with text-to-speech.
|
||||||
type: :class:`MessageType`
|
type: :class:`MessageType`
|
||||||
The type of message. In most cases this should not be checked, but it is helpful
|
The type of message. In most cases this should not be checked, but it is helpful
|
||||||
@ -51,12 +49,12 @@ class Message:
|
|||||||
author
|
author
|
||||||
A :class:`Member` that sent the message. If :attr:`channel` is a
|
A :class:`Member` that sent the message. If :attr:`channel` is a
|
||||||
private channel, then it is a :class:`User` instead.
|
private channel, then it is a :class:`User` instead.
|
||||||
content : str
|
content: str
|
||||||
The actual contents of the message.
|
The actual contents of the message.
|
||||||
nonce
|
nonce
|
||||||
The value used by the discord server and the client to verify that the message is successfully sent.
|
The value used by the discord server and the client to verify that the message is successfully sent.
|
||||||
This is typically non-important.
|
This is typically non-important.
|
||||||
embeds : list
|
embeds: list
|
||||||
A list of embedded objects. The elements are objects that meet oEmbed's specification_.
|
A list of embedded objects. The elements are objects that meet oEmbed's specification_.
|
||||||
|
|
||||||
.. _specification: http://oembed.com/
|
.. _specification: http://oembed.com/
|
||||||
@ -66,12 +64,12 @@ class Message:
|
|||||||
In :issue:`very rare cases <21>` this could be a :class:`Object` instead.
|
In :issue:`very rare cases <21>` this could be a :class:`Object` instead.
|
||||||
|
|
||||||
For the sake of convenience, this :class:`Object` instance has an attribute ``is_private`` set to ``True``.
|
For the sake of convenience, this :class:`Object` instance has an attribute ``is_private`` set to ``True``.
|
||||||
server : Optional[:class:`Server`]
|
server: Optional[:class:`Server`]
|
||||||
The server that the message belongs to. If not applicable (i.e. a PM) then it's None instead.
|
The server that the message belongs to. If not applicable (i.e. a PM) then it's None instead.
|
||||||
call: Optional[:class:`CallMessage`]
|
call: Optional[:class:`CallMessage`]
|
||||||
The call that the message refers to. This is only applicable to messages of type
|
The call that the message refers to. This is only applicable to messages of type
|
||||||
:attr:`MessageType.call`.
|
:attr:`MessageType.call`.
|
||||||
mention_everyone : bool
|
mention_everyone: bool
|
||||||
Specifies if the message mentions everyone.
|
Specifies if the message mentions everyone.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@ -91,15 +89,18 @@ class Message:
|
|||||||
The order of the mentions list is not in any particular order so you should
|
The order of the mentions list is not in any particular order so you should
|
||||||
not rely on it. This is a discord limitation, not one with the library.
|
not rely on it. This is a discord limitation, not one with the library.
|
||||||
|
|
||||||
channel_mentions : list
|
channel_mentions: list
|
||||||
A list of :class:`Channel` that were mentioned. If the message is in a private message
|
A list of :class:`Channel` that were mentioned. If the message is in a private message
|
||||||
then the list is always empty.
|
then the list is always empty.
|
||||||
role_mentions : list
|
role_mentions: list
|
||||||
A list of :class:`Role` that were mentioned. If the message is in a private message
|
A list of :class:`Role` that were mentioned. If the message is in a private message
|
||||||
then the list is always empty.
|
then the list is always empty.
|
||||||
id : str
|
id: str
|
||||||
The message ID.
|
The message ID.
|
||||||
attachments : list
|
webhook_id: Optional[str]
|
||||||
|
If this message was sent by a webhook, then this is the webhook ID's that sent this
|
||||||
|
message.
|
||||||
|
attachments: list
|
||||||
A list of attachments given to a message.
|
A list of attachments given to a message.
|
||||||
pinned: bool
|
pinned: bool
|
||||||
Specifies if the message is currently pinned.
|
Specifies if the message is currently pinned.
|
||||||
@ -107,9 +108,9 @@ class Message:
|
|||||||
Reactions to a message. Reactions can be either custom emoji or standard unicode emoji.
|
Reactions to a message. Reactions can be either custom emoji or standard unicode emoji.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ( 'edited_timestamp', 'timestamp', 'tts', 'content', 'channel',
|
__slots__ = ( 'edited_timestamp', 'tts', 'content', 'channel', 'webhook_id',
|
||||||
'mention_everyone', 'embeds', 'id', 'mentions', 'author',
|
'mention_everyone', 'embeds', 'id', 'mentions', 'author',
|
||||||
'channel_mentions', 'server', '_cs_raw_mentions', 'attachments',
|
'_cs_channel_mentions', 'server', '_cs_raw_mentions', 'attachments',
|
||||||
'_cs_clean_content', '_cs_raw_channel_mentions', 'nonce', 'pinned',
|
'_cs_clean_content', '_cs_raw_channel_mentions', 'nonce', 'pinned',
|
||||||
'role_mentions', '_cs_raw_role_mentions', 'type', 'call',
|
'role_mentions', '_cs_raw_role_mentions', 'type', 'call',
|
||||||
'_cs_system_content', '_state', 'reactions' )
|
'_cs_system_content', '_state', 'reactions' )
|
||||||
@ -121,27 +122,31 @@ class Message:
|
|||||||
reaction.message = self
|
reaction.message = self
|
||||||
self._update(channel, data)
|
self._update(channel, data)
|
||||||
|
|
||||||
|
def _try_patch(self, data, key, transform):
|
||||||
|
try:
|
||||||
|
value = data[key]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
setattr(self, key, transform(value))
|
||||||
|
|
||||||
def _update(self, channel, data):
|
def _update(self, channel, data):
|
||||||
# at the moment, the timestamps seem to be naive so they have no time zone and operate on UTC time.
|
|
||||||
# we can use this to our advantage to use strptime instead of a complicated parsing routine.
|
|
||||||
# example timestamp: 2015-08-21T12:03:45.782000+00:00
|
|
||||||
# sometimes the .%f modifier is missing
|
|
||||||
self.edited_timestamp = utils.parse_time(data['edited_timestamp'])
|
|
||||||
self.timestamp = utils.parse_time(data['timestamp'])
|
|
||||||
self.tts = data.get('tts', False)
|
|
||||||
self.pinned = data.get('pinned', False)
|
|
||||||
self.content = data['content']
|
|
||||||
self.mention_everyone = data['mention_everyone']
|
|
||||||
self.embeds = data['embeds']
|
|
||||||
self.id = data['id']
|
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
self.author = self._state.try_insert_user(data['author'])
|
for handler in ('mentions', 'mention_roles', 'call'):
|
||||||
self.nonce = data.get('nonce')
|
try:
|
||||||
self.attachments = data['attachments']
|
getattr(self, '_handle_%s' % handler)(data[handler])
|
||||||
self.type = try_enum(MessageType, data.get('type'))
|
except KeyError:
|
||||||
self._handle_upgrades(data['channel_id'])
|
continue
|
||||||
self._handle_mentions(data.get('mentions', []), data.get('mention_roles', []))
|
|
||||||
self._handle_call(data.get('call'))
|
self._try_patch(data, 'edited_timestamp', utils.parse_time)
|
||||||
|
self._try_patch(data, 'author', self._state.try_insert_user)
|
||||||
|
self._try_patch(data, 'pinned', bool)
|
||||||
|
self._try_patch(data, 'mention_everyone', bool)
|
||||||
|
self._try_patch(data, 'tts', bool)
|
||||||
|
self._try_patch(data, 'content', str)
|
||||||
|
self._try_patch(data, 'attachments', lambda x: x)
|
||||||
|
self._try_patch(data, 'embeds', lambda x: x)
|
||||||
|
self._try_patch(data, 'nonce', lambda x: x)
|
||||||
|
|
||||||
# clear the cached properties
|
# clear the cached properties
|
||||||
cached = filter(lambda attr: attr.startswith('_cs_'), self.__slots__)
|
cached = filter(lambda attr: attr.startswith('_cs_'), self.__slots__)
|
||||||
@ -151,24 +156,21 @@ class Message:
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _handle_mentions(self, mentions, role_mentions):
|
def _handle_mentions(self, mentions):
|
||||||
self.mentions = []
|
self.mentions = []
|
||||||
self.channel_mentions = []
|
if self.server is None:
|
||||||
self.role_mentions = []
|
|
||||||
if getattr(self.channel, 'is_private', True):
|
|
||||||
self.mentions = [self._state.try_insert_user(m) for m in mentions]
|
self.mentions = [self._state.try_insert_user(m) for m in mentions]
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.server is not None:
|
|
||||||
for mention in mentions:
|
for mention in mentions:
|
||||||
id_search = mention.get('id')
|
id_search = mention['id']
|
||||||
member = self.server.get_member(id_search)
|
member = self.server.get_member(id_search)
|
||||||
if member is not None:
|
if member is not None:
|
||||||
self.mentions.append(member)
|
self.mentions.append(member)
|
||||||
|
|
||||||
it = filter(None, map(lambda m: self.server.get_channel(m), self.raw_channel_mentions))
|
def _handle_mention_roles(self, role_mentions):
|
||||||
self.channel_mentions = utils._unique(it)
|
self.role_mentions = []
|
||||||
|
if self.server is not None:
|
||||||
for role_id in role_mentions:
|
for role_id in role_mentions:
|
||||||
role = utils.get(self.server.roles, id=role_id)
|
role = utils.get(self.server.roles, id=role_id)
|
||||||
if role is not None:
|
if role is not None:
|
||||||
@ -218,6 +220,13 @@ class Message:
|
|||||||
"""
|
"""
|
||||||
return re.findall(r'<@&([0-9]+)>', self.content)
|
return re.findall(r'<@&([0-9]+)>', self.content)
|
||||||
|
|
||||||
|
@utils.cached_slot_property('_cs_channel_mentions')
|
||||||
|
def channel_mentions(self):
|
||||||
|
if self.server is None:
|
||||||
|
return []
|
||||||
|
it = filter(None, map(lambda m: self.server.get_channel(m), self.raw_channel_mentions))
|
||||||
|
return utils._unique(it)
|
||||||
|
|
||||||
@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"
|
||||||
@ -289,6 +298,11 @@ class Message:
|
|||||||
if found is not None:
|
if found is not None:
|
||||||
self.author = found
|
self.author = found
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created_at(self):
|
||||||
|
"""Returns the message's creation time in UTC."""
|
||||||
|
return utils.snowflake_time(self.id)
|
||||||
|
|
||||||
@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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user