diff --git a/disco/gateway/events.py b/disco/gateway/events.py index d8451ef..367c9af 100644 --- a/disco/gateway/events.py +++ b/disco/gateway/events.py @@ -73,10 +73,12 @@ class ChannelCreate(GatewayEvent): return self.channel.guild +@wraps_model(Channel) class ChannelUpdate(ChannelCreate): pass +@wraps_model(Channel) class ChannelDelete(ChannelCreate): pass @@ -91,6 +93,7 @@ class GuildBanAdd(GatewayEvent): pass +@wraps_model(User) class GuildBanRemove(GuildBanAdd): pass @@ -144,6 +147,7 @@ class MessageCreate(GatewayEvent): return self.message.channel +@wraps_model(Message) class MessageUpdate(MessageCreate): pass diff --git a/disco/types/base.py b/disco/types/base.py index 0279beb..6ffab85 100644 --- a/disco/types/base.py +++ b/disco/types/base.py @@ -4,6 +4,11 @@ import functools from datetime import datetime as real_datetime +DATETIME_FORMATS = [ + '%Y-%m-%dT%H:%M:%S.%f', + '%Y-%m-%dT%H:%M:%S' +] + def _make(typ, data, client): args, _, _, _ = inspect.getargspec(typ) @@ -50,7 +55,16 @@ def alias(typ, name): def datetime(data): - return real_datetime.strptime(data.rsplit('+', 1)[0], '%Y-%m-%dT%H:%M:%S.%f') if data else None + if not data: + return None + + for fmt in DATETIME_FORMATS: + try: + return real_datetime.strptime(data.rsplit('+', 1)[0], fmt) + except (ValueError, TypeError): + continue + + raise ValueError('Failed to conver `{}` to datetime'.format(data)) def text(obj): @@ -112,9 +126,9 @@ class Model(six.with_metaclass(ModelMeta)): v = typ(obj[name]) else: v = typ(obj[name]) - except TypeError as e: + except Exception: print('Failed during parsing of field {} => {} (`{}`)'.format(name, typ, obj[name])) - raise e + raise if client and isinstance(v, Model): v.client = client @@ -122,15 +136,21 @@ class Model(six.with_metaclass(ModelMeta)): setattr(self, dest_name, v) def update(self, other): - for name in six.iterkeys(self.__class__.fields): + for name in six.iterkeys(self.__class__._fields): value = getattr(other, name) if value: setattr(self, name, value) + # Clear cached properties + for name in dir(type(self)): + if isinstance(getattr(type(self), name), property): + delattr(self, name) + + @classmethod def create(cls, client, data): return cls(data, client) @classmethod def create_map(cls, client, data): - return map(functools.partial(cls.create, client), data) + return list(map(functools.partial(cls.create, client), data)) diff --git a/disco/types/channel.py b/disco/types/channel.py index 030dbf9..e1beea4 100644 --- a/disco/types/channel.py +++ b/disco/types/channel.py @@ -240,7 +240,7 @@ class MessageIterator(object): self.last = None self._buffer = [] - if len(filter(bool, (before, after))) > 1: + if not before and not after: raise Exception('Must specify at most one of before or after') if not any((before, after)) and self.direction == self.Direction.DOWN: @@ -268,10 +268,13 @@ class MessageIterator(object): self._buffer.reverse() self.after == self._buffer[-1].id + def next(self): + return self.__next__() + def __iter__(self): return self - def next(self): + def __next__(self): if not len(self._buffer): self.fill() diff --git a/disco/types/message.py b/disco/types/message.py index 87d62c3..d3aa2e6 100644 --- a/disco/types/message.py +++ b/disco/types/message.py @@ -1,12 +1,24 @@ import re -from disco.types.base import Model, snowflake, text, datetime, dictof, listof +from holster.enum import Enum +from disco.types.base import Model, snowflake, text, datetime, dictof, listof, enum from disco.util import to_snowflake from disco.util.functional import cached_property from disco.types.user import User +MessageType = Enum( + DEFAULT=0, + RECIPIENT_ADD=1, + RECIPIENT_REMOVE=2, + CALL=3, + CHANNEL_NAME_CHANGE=4, + CHANNEL_ICON_CHANGE=5, + PINS_ADD=6 +) + + class MessageEmbed(Model): """ Message embed object @@ -68,6 +80,8 @@ class Message(Model): The ID of this message. channel_id : snowflake The channel ID this message was sent in. + type : ``MessageType`` + Type of the message. author : :class:`disco.types.user.User` The author of this message. content : str @@ -95,6 +109,7 @@ class Message(Model): """ id = snowflake channel_id = snowflake + type = enum(MessageType) author = User content = text nonce = snowflake