From 2c8f73f63cd7b6d958732f630ae6c1cb8aad1d61 Mon Sep 17 00:00:00 2001 From: Andrei Date: Fri, 7 Oct 2016 05:43:57 -0500 Subject: [PATCH] APIClient fixes, emitter priority support, etc fixes --- disco/api/client.py | 8 ++++---- disco/bot/plugin.py | 15 +++++++++++---- disco/gateway/client.py | 3 ++- disco/gateway/events.py | 13 ++++++------- disco/state.py | 6 +++--- disco/types/base.py | 16 +++++++++++----- disco/types/guild.py | 19 +++++++++++++++++++ requirements.txt | 2 +- 8 files changed, 57 insertions(+), 25 deletions(-) diff --git a/disco/api/client.py b/disco/api/client.py index bd01a76..761344a 100644 --- a/disco/api/client.py +++ b/disco/api/client.py @@ -144,17 +144,17 @@ class APIClient(LoggingClass): return GuildMember.create_map(self.client, r.json()) def guilds_members_get(self, guild, member): - r = self.http(Routes.GUILD_MEMBERS_GET, dict(guild=guild, member=member)) + r = self.http(Routes.GUILDS_MEMBERS_GET, dict(guild=guild, member=member)) return GuildMember.create(self.client, r.json()) def guilds_members_modify(self, guild, member, **kwargs): - self.http(Routes.GUILD_MEMBERS_MODIFY, dict(guild=guild, member=member), json=kwargs) + self.http(Routes.GUILDS_MEMBERS_MODIFY, dict(guild=guild, member=member), json=kwargs) def guilds_members_kick(self, guild, member): - self.http(Routes.GUILD_MEMBERS_KICK, dict(guild=guild, member=member)) + self.http(Routes.GUILDS_MEMBERS_KICK, dict(guild=guild, member=member)) def guilds_bans_list(self, guild): - r = self.http(Routes.GUILD_BANS_LIST, dict(guild=guild)) + r = self.http(Routes.GUILDS_BANS_LIST, dict(guild=guild)) return User.create_map(self.client, r.json()) def guilds_bans_create(self, guild, user, delete_message_days): diff --git a/disco/bot/plugin.py b/disco/bot/plugin.py index 7890931..3139c87 100644 --- a/disco/bot/plugin.py +++ b/disco/bot/plugin.py @@ -1,6 +1,8 @@ import inspect import functools +from holster.emitter import Priority + from disco.util.logging import LoggingClass from disco.bot.command import Command, CommandError @@ -10,6 +12,8 @@ class PluginDeco(object): A utility mixin which provides various function decorators that a plugin author can use to create bound event/command handlers. """ + Prio = Priority + @staticmethod def add_meta_deco(meta): def deco(f): @@ -22,13 +26,14 @@ class PluginDeco(object): return deco @classmethod - def listen(cls, event_name): + def listen(cls, event_name, priority=None): """ Binds the function to listen for a given event name """ return cls.add_meta_deco({ 'type': 'listener', 'event_name': event_name, + 'priority': priority }) @classmethod @@ -118,7 +123,7 @@ class Plugin(LoggingClass, PluginDeco): if hasattr(member, 'meta'): for meta in member.meta: if meta['type'] == 'listener': - self.register_listener(member, meta['event_name']) + self.register_listener(member, meta['event_name'], meta['priority']) elif meta['type'] == 'command': self.register_command(member, *meta['args'], **meta['kwargs']) elif meta['type'].startswith('pre_') or meta['type'].startswith('post_'): @@ -155,7 +160,7 @@ class Plugin(LoggingClass, PluginDeco): return True - def register_listener(self, func, name): + def register_listener(self, func, name, priority): """ Registers a listener @@ -165,9 +170,11 @@ class Plugin(LoggingClass, PluginDeco): The function to be registered. name : string Name of event to listen for. + priority : Priority + The priority of this listener. """ func = functools.partial(self._dispatch, 'listener', func) - self.listeners.append(self.bot.client.events.on(name, func)) + self.listeners.append(self.bot.client.events.on(name, func, priority=priority or Priority.NONE)) def register_command(self, func, *args, **kwargs): """ diff --git a/disco/gateway/client.py b/disco/gateway/client.py index 3b764c6..87194c4 100644 --- a/disco/gateway/client.py +++ b/disco/gateway/client.py @@ -1,6 +1,7 @@ import gevent import zlib import six +import ssl from disco.gateway.packets import OPCode from disco.gateway.events import GatewayEvent @@ -99,7 +100,7 @@ class GatewayClient(LoggingClass): self.ws.emitter.on('on_close', self.on_close) self.ws.emitter.on('on_message', self.on_message) - self.ws.run_forever() + self.ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE}) def on_message(self, msg): # Detect zlib and decompress diff --git a/disco/gateway/events.py b/disco/gateway/events.py index 367c9af..6d809de 100644 --- a/disco/gateway/events.py +++ b/disco/gateway/events.py @@ -2,7 +2,7 @@ import inflection import six from disco.types import Guild, Channel, User, GuildMember, Role, Message, VoiceState -from disco.types.base import Model, snowflake, alias, listof +from disco.types.base import Model, snowflake, alias, listof, text # TODO: clean this... use BaseType, etc @@ -121,10 +121,9 @@ class GuildMemberRemove(GatewayEvent): user = User +@wraps_model(GuildMember, alias='member') class GuildMemberUpdate(GatewayEvent): - guild_id = snowflake - user = User - roles = listof(snowflake) + pass class GuildRoleCreate(GatewayEvent): @@ -166,14 +165,14 @@ class PresenceUpdate(GatewayEvent): class Game(Model): # TODO enum type = int - name = str - url = str + name = text + url = text user = User guild_id = snowflake roles = listof(snowflake) game = Game - status = str + status = text class TypingStart(GatewayEvent): diff --git a/disco/state.py b/disco/state.py index 90d2b22..1f7d998 100644 --- a/disco/state.py +++ b/disco/state.py @@ -219,11 +219,11 @@ class State(object): self.guilds[event.member.guild_id].members[event.member.id] = event.member def on_guild_member_update(self, event): - if event.guild_id not in self.guilds: + if event.member.guild_id not in self.guilds: return - self.guilds[event.guild_id].members[event.user.id].roles = event.roles - self.guilds[event.guild_id].members[event.user.id].user.update(event.user) + event.member.guild = self.guilds[event.member.guild_id] + self.guilds[event.member.guild_id].members[event.member.id].update(event.member) def on_guild_member_remove(self, event): if event.guild_id not in self.guilds: diff --git a/disco/types/base.py b/disco/types/base.py index 1802e01..26e8438 100644 --- a/disco/types/base.py +++ b/disco/types/base.py @@ -15,6 +15,10 @@ def _make(typ, data, client): args, _, _, _ = inspect.getargspec(typ) if 'client' in args: return typ(data, client) + elif issubclass(typ, Model): + if not client: + raise Exception() + return typ(data, client) return typ(data) @@ -125,15 +129,14 @@ class Model(six.with_metaclass(ModelMeta)): v = typ(obj[name], client) else: v = typ(obj[name]) + elif inspect.isclass(typ) and issubclass(typ, Model): + v = typ(obj[name], client) else: v = typ(obj[name]) except Exception: - print('Failed during parsing of field {} => {} (`{}`)'.format(name, typ, obj[name])) + print('Failed during parsing of field {} => {}'.format(name, typ)) raise - if client and isinstance(v, Model): - v.client = client - setattr(self, dest_name, v) def update(self, other): @@ -145,7 +148,10 @@ class Model(six.with_metaclass(ModelMeta)): # Clear cached properties for name in dir(type(self)): if isinstance(getattr(type(self), name), property): - delattr(self, name) + try: + delattr(self, name) + except: + pass @classmethod def create(cls, client, data): diff --git a/disco/types/guild.py b/disco/types/guild.py index 81e7a85..02d3c0d 100644 --- a/disco/types/guild.py +++ b/disco/types/guild.py @@ -2,6 +2,7 @@ from holster.enum import Enum from disco.api.http import APIException from disco.util import to_snowflake +from disco.util.functional import cached_property from disco.types.base import Model, snowflake, listof, dictof, datetime, text, binary, enum from disco.types.user import User from disco.types.voice import VoiceState @@ -82,6 +83,8 @@ class GuildMember(Model): The user object of this member. guild_id : snowflake The guild this member is part of. + nick : str + The nickname of the member. mute : bool Whether this member is server voice-muted. deaf : bool @@ -93,6 +96,7 @@ class GuildMember(Model): """ user = User guild_id = snowflake + nick = text mute = bool deaf = bool joined_at = datetime @@ -125,6 +129,21 @@ class GuildMember(Model): """ self.client.api.guilds_bans_create(self.guild.id, self.user.id, delete_message_days) + def set_nickname(self, nickname=None): + """ + Sets the members nickname (or clears it if None). + + Args + ---- + nickname : Optional[str] + The nickname (or none to reset) to set. + """ + self.client.api.guilds_members_modify(self.guild.id, self.user.id, nick=nickname or '') + + @cached_property + def guild(self): + return self.client.state.guilds.get(self.guild_id) + @property def id(self): """ diff --git a/requirements.txt b/requirements.txt index d0a50b9..b67520a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ gevent==1.1.2 -holster==1.0.1 +holster==1.0.3 inflection==0.3.1 requests==2.11.1 six==1.10.0