diff --git a/disco/api/client.py b/disco/api/client.py index a6cea02..7a5a4e5 100644 --- a/disco/api/client.py +++ b/disco/api/client.py @@ -185,3 +185,11 @@ class APIClient(LoggingClass): def guilds_roles_delete(self, guild, role): self.http(Routes.GUILDS_ROLES_DELETE, dict(guild=guild, role=role)) + + def invites_get(self, invite): + r = self.http(Routes.INVITES_GET, dict(invite=invite)) + return Invite.create(self.client, r.json()) + + def invites_delete(self, invite): + r = self.http(Routes.INVITES_DELETE, dict(invite=invite)) + return Invite.create(self.client, r.json()) diff --git a/disco/api/http.py b/disco/api/http.py index 99ca763..88dbc50 100644 --- a/disco/api/http.py +++ b/disco/api/http.py @@ -91,6 +91,11 @@ class Routes(object): USERS_ME_CONNECTIONS_LIST = (HTTPMethod.GET, USERS + '/@me/connections') USERS_GET = (HTTPMethod.GET, USERS + '/{user}') + # Invites + INVITES = '/invites' + INVITES_GET = (HTTPMethod.GET, INVITES + '/{invite}') + INVITES_DELETE = (HTTPMethod.DELETE, INVITES + '/{invite}') + class APIException(Exception): """ diff --git a/disco/types/base.py b/disco/types/base.py index 9e59581..35600b4 100644 --- a/disco/types/base.py +++ b/disco/types/base.py @@ -1,4 +1,5 @@ import six +import gevent import inspect import functools @@ -184,7 +185,7 @@ class ModelMeta(type): fields = {} for parent in parents: - if issubclass(parent, Model) and parent != Model: + if Model and issubclass(parent, Model) and parent != Model: fields.update(parent._fields) for k, v in six.iteritems(dct): @@ -207,7 +208,13 @@ class ModelMeta(type): return super(ModelMeta, cls).__new__(cls, name, parents, dct) -class Model(six.with_metaclass(ModelMeta)): +class AsyncChainable(object): + def after(self, delay): + gevent.sleep(delay) + return self + + +class Model(six.with_metaclass(ModelMeta, AsyncChainable)): def __init__(self, *args, **kwargs): self.client = kwargs.pop('client', None) diff --git a/disco/types/channel.py b/disco/types/channel.py index d341783..faabdcf 100644 --- a/disco/types/channel.py +++ b/disco/types/channel.py @@ -35,7 +35,6 @@ class PermissionOverwrite(ChannelSubType): """ A PermissionOverwrite for a :class:`Channel` - Attributes ---------- id : snowflake @@ -52,11 +51,30 @@ class PermissionOverwrite(ChannelSubType): allow = Field(PermissionValue) deny = Field(PermissionValue) + @classmethod + def create(cls, channel, entity, allow=0, deny=0): + from disco.types.guild import Role + + type = PermissionOverwriteType.ROLE if isinstance(entity, Role) else PermissionOverwriteType.MEMBER + return cls( + client=channel.client, + id=entity.id, + type=type, + allow=allow, + deny=deny, + channel_id=channel.id + ).save() + def save(self): - return self.channel.update_overwrite(self) + self.client.api.channels_permissions_modify(self.channel_id, + self.id, + self.allow.value or 0, + self.deny.value or 0, + self.type.name) + return self def delete(self): - return self.channel.delete_overwrite(self) + self.client.api.channels_permissions_delete(self.channel_id, self.id) class Channel(SlottedModel, Permissible): @@ -152,13 +170,6 @@ class Channel(SlottedModel, Permissible): """ return self.messages_iter() - def messages_iter(self, **kwargs): - """ - Creates a new :class:`MessageIterator` for the channel with the given - keyword arguments - """ - return MessageIterator(self.client, self, **kwargs) - @cached_property def guild(self): """ @@ -166,6 +177,13 @@ class Channel(SlottedModel, Permissible): """ return self.client.state.guilds.get(self.guild_id) + def messages_iter(self, **kwargs): + """ + Creates a new :class:`MessageIterator` for the channel with the given + keyword arguments + """ + return MessageIterator(self.client, self, **kwargs) + def get_invites(self): """ Returns @@ -175,6 +193,10 @@ class Channel(SlottedModel, Permissible): """ return self.client.api.channels_invites_list(self.id) + def create_invite(self, *args, **kwargs): + from disco.types.invite import Invite + return Invite.create(self, *args, **kwargs) + def get_pins(self): """ Returns @@ -184,6 +206,12 @@ class Channel(SlottedModel, Permissible): """ return self.client.api.channels_pins_list(self.id) + def create_pin(self, message): + self.client.api.channels_pins_create(self.id, to_snowflake(message)) + + def delete_pin(self, message): + self.client.api.channels_pins_delete(self.id, to_snowflake(message)) + def send_message(self, content, nonce=None, tts=False): """ Send a message in this channel @@ -213,32 +241,8 @@ class Channel(SlottedModel, Permissible): vc.connect(*args, **kwargs) return vc - def create_overwrite(self, entity, allow=0, deny=0): - from disco.types.guild import Role - - type = PermissionOverwriteType.ROLE if isinstance(entity, Role) else PermissionOverwriteType.MEMBER - ow = PermissionOverwrite( - id=entity.id, - type=type, - allow=allow, - deny=deny - ) - - ow.channel_id = self.id - ow.channel = self - - return self.update_overwrite(ow) - - def update_overwrite(self, ow): - self.client.api.channels_permissions_modify(self.id, - ow.id, - ow.allow.value if ow.allow else 0, - ow.deny.value if ow.deny else 0, - ow.type.name) - return ow - - def delete_overwrite(self, ow): - self.client.api.channels_permissions_delete(self.id, ow.id) + def create_overwrite(self, *args, **kwargs): + return PermissionOverwrite.create(self, *args, **kwargs) def delete_message(self, message): """ diff --git a/disco/types/invite.py b/disco/types/invite.py index 34c5312..850002e 100644 --- a/disco/types/invite.py +++ b/disco/types/invite.py @@ -38,3 +38,15 @@ class Invite(SlottedModel): uses = Field(int) temporary = Field(bool) created_at = Field(lazy_datetime) + + @classmethod + def create(cls, channel, max_age=86400, max_uses=0, temporary=False, unique=False): + return channel.client.api.channels_invites_create( + channel.id, + max_age=max_age, + max_uses=max_uses, + temporary=temporary, + unique=unique) + + def delete(self): + self.client.api.invites_delete(self.code) diff --git a/disco/types/message.py b/disco/types/message.py index 112f662..55ba42b 100644 --- a/disco/types/message.py +++ b/disco/types/message.py @@ -156,6 +156,12 @@ class Message(SlottedModel): """ return self.client.state.channels.get(self.channel_id) + def pin(self): + return self.channel.create_pin(self) + + def unpin(self): + return self.channel.delete_pin(self) + def reply(self, *args, **kwargs): """ Reply to this message (proxys arguments to