Browse Source

Further progress on audit log

pull/35/head
Andrei 8 years ago
parent
commit
b69c941317
  1. 12
      disco/api/client.py
  2. 3
      disco/api/http.py
  3. 3
      disco/cli.py
  4. 4
      disco/types/base.py
  5. 47
      disco/types/guild.py
  6. 1
      disco/types/message.py
  7. 9
      disco/util/paginator.py
  8. 4
      examples/basic_plugin.py

12
disco/api/client.py

@ -384,15 +384,19 @@ class APIClient(LoggingClass):
dict(guild=guild, emoji=emoji), dict(guild=guild, emoji=emoji),
headers=_reason_header(reason)) headers=_reason_header(reason))
def guilds_auditlogs_list(self, guild, before, user_id=None, action_type=None, limit=50): def guilds_auditlogs_list(self, guild, before=None, user_id=None, action_type=None, limit=50):
r = self.http(Routes.GUILDS, dict(guild=guild), json=optional( r = self.http(Routes.GUILDS_AUDITLOGS_LIST, dict(guild=guild), params=optional(
before=before, before=before,
user_id=user_id, user_id=user_id,
action_type=action_type, action_type=int(action_type) if action_type else None,
limit=limit, limit=limit,
)) ))
return AuditLogEntry.create_map(self.client, r.json()['audit_log_entries']) data = r.json()
users = User.create_hash(self.client, 'id', data['users'])
webhooks = Webhook.create_hash(self.client, 'id', data['webhooks'])
return AuditLogEntry.create_map(self.client, r.json()['audit_log_entries'], users, webhooks, guild_id=guild)
def users_me_get(self): def users_me_get(self):
return User.create(self.client, self.http(Routes.USERS_ME_GET).json()) return User.create(self.client, self.http(Routes.USERS_ME_GET).json())

3
disco/api/http.py

@ -252,6 +252,8 @@ class HTTPClient(LoggingClass):
# Possibly wait if we're rate limited # Possibly wait if we're rate limited
self.limiter.check(bucket) self.limiter.check(bucket)
self.log.debug('KW: %s', kwargs)
# Make the actual request # Make the actual request
url = self.BASE_URL + route[1].format(**args) url = self.BASE_URL + route[1].format(**args)
self.log.info('%s %s (%s)', route[0].value, url, kwargs.get('params')) self.log.info('%s %s (%s)', route[0].value, url, kwargs.get('params'))
@ -264,6 +266,7 @@ class HTTPClient(LoggingClass):
if r.status_code < 400: if r.status_code < 400:
return r return r
elif r.status_code != 429 and 400 <= r.status_code < 500: elif r.status_code != 429 and 400 <= r.status_code < 500:
self.log.warning('Request failed with code %s: %s', r.status_code, r.content)
raise APIException(r) raise APIException(r)
else: else:
if r.status_code == 429: if r.status_code == 429:

3
disco/cli.py

@ -49,6 +49,9 @@ def disco_main(run=False):
else: else:
config = ClientConfig() config = ClientConfig()
config.manhole_enable = args.manhole
config.manhole_bind = args.manhole_bind.split(':', 1)
for k, v in six.iteritems(vars(args)): for k, v in six.iteritems(vars(args)):
if hasattr(config, k) and v is not None: if hasattr(config, k) and v is not None:
setattr(config, k, v) setattr(config, k, v)

4
disco/types/base.py

@ -349,8 +349,8 @@ class Model(six.with_metaclass(ModelMeta, Chainable)):
return inst return inst
@classmethod @classmethod
def create_map(cls, client, data, **kwargs): def create_map(cls, client, data, *args, **kwargs):
return list(map(functools.partial(cls.create, client, **kwargs), data)) return list(map(functools.partial(cls.create, client, *args, **kwargs), data))
@classmethod @classmethod
def create_hash(cls, client, key, data, **kwargs): def create_hash(cls, client, key, data, **kwargs):

47
disco/types/guild.py

@ -4,6 +4,7 @@ from holster.enum import Enum
from disco.gateway.packets import OPCode from disco.gateway.packets import OPCode
from disco.api.http import APIException from disco.api.http import APIException
from disco.util.paginator import Paginator
from disco.util.snowflake import to_snowflake from disco.util.snowflake import to_snowflake
from disco.util.functional import cached_property from disco.util.functional import cached_property
from disco.types.base import ( from disco.types.base import (
@ -471,6 +472,18 @@ class Guild(SlottedModel, Permissible):
def splash_url(self): def splash_url(self):
return self.get_splash_url() return self.get_splash_url()
@property
def audit_log(self):
return Paginator(
self.client.api.guilds_auditlogs_list,
'before',
self.id,
)
def get_audit_log_entries(self, *args, **kwargs):
return self.client.api.guilds_auditlogs_list(self.id, *args, **kwargs)
AuditLogActionTypes = Enum( AuditLogActionTypes = Enum(
GUILD_UPDATE=1, GUILD_UPDATE=1,
CHANNEL_CREATE=10, CHANNEL_CREATE=10,
@ -560,7 +573,7 @@ class AuditLogObjectChange(SlottedModel):
class AuditLogEntry(SlottedModel): class AuditLogEntry(SlottedModel):
id = Field(snowflake) id = Field(snowflake)
guild = Field(None) guild_id = Field(snowflake)
user_id = Field(snowflake) user_id = Field(snowflake)
target_id = Field(snowflake) target_id = Field(snowflake)
action_type = Field(enum(AuditLogActionTypes)) action_type = Field(enum(AuditLogActionTypes))
@ -568,6 +581,38 @@ class AuditLogEntry(SlottedModel):
options = DictField(text, text) options = DictField(text, text)
reason = Field(text) reason = Field(text)
_cached_target = Field(None)
@classmethod
def create(cls, client, users, webhooks, data, **kwargs):
self = super(SlottedModel, cls).create(client, data, **kwargs)
if self.action_type in MEMBER_ACTIONS:
self._cached_target = users[self.target_id]
elif self.action_type in WEBHOOK_ACTIONS:
self._cached_target = webhooks[self.target_id]
return self
@cached_property
def guild(self):
return self.client.state.guilds.get(self.guild_id)
@cached_property @cached_property
def user(self): def user(self):
return self.client.state.users.get(self.user_id) return self.client.state.users.get(self.user_id)
@cached_property
def target(self):
if self.action_type in GUILD_ACTIONS:
return self.guild
elif self.action_type in CHANNEL_ACTIONS:
return self.guild.channels.get(self.target_id)
elif self.action_type in MEMBER_ACTIONS:
return self._cached_target or self.state.users.get(self.target_id)
elif self.action_type in ROLE_ACTIONS:
return self.guild.roles.get(self.target_id)
elif self.action_type in WEBHOOK_ACTIONS:
return self._cached_target
elif self.action_type in EMOJI_ACTIONS:
return self.guild.emojis.get(self.target_id)

1
disco/types/message.py

@ -315,6 +315,7 @@ class Message(SlottedModel):
return Paginator( return Paginator(
self.client.api.channels_messages_reactions_get, self.client.api.channels_messages_reactions_get,
'after',
self.channel_id, self.channel_id,
self.id, self.id,
emoji, emoji,

9
disco/util/paginator.py

@ -5,25 +5,26 @@ class Paginator(object):
""" """
Implements a class which provides paginated iteration over an endpoint. Implements a class which provides paginated iteration over an endpoint.
""" """
def __init__(self, func, *args, **kwargs): def __init__(self, func, sort_key, *args, **kwargs):
self.func = func self.func = func
self.sort_key = sort_key
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
self._key = kwargs.pop('key', operator.attrgetter('id')) self._key = kwargs.pop('key', operator.attrgetter('id'))
self._bulk = kwargs.pop('bulk', False) self._bulk = kwargs.pop('bulk', False)
self._after = kwargs.pop('after', None) self._sort_key_value = kwargs.pop(self.sort_key, 0)
self._buffer = [] self._buffer = []
def fill(self): def fill(self):
self.kwargs['after'] = self._after self.kwargs[self.sort_key] = self._sort_key_value
result = self.func(*self.args, **self.kwargs) result = self.func(*self.args, **self.kwargs)
if not len(result): if not len(result):
return return
self._buffer.extend(result) self._buffer.extend(result)
self._after = self._key(result[-1]) self._sort_key_value = self._key(result[-1])
def next(self): def next(self):
return self.__next__() return self.__next__()

4
examples/basic_plugin.py

@ -19,10 +19,6 @@ class BasicPlugin(Plugin):
self.log.info('Message created: {}: {}'.format(msg.author, msg.content)) self.log.info('Message created: {}: {}'.format(msg.author, msg.content))
@Plugin.command('test') @Plugin.command('test')
def on_test(self, event):
c = event.guild.create_channel('WOWSOCOOL', 'text', reason='TEST REASONS')
c.delete(reason='TEST REASONS2')
@Plugin.command('echo', '<content:str...>') @Plugin.command('echo', '<content:str...>')
def on_echo_command(self, event, content): def on_echo_command(self, event, content):
event.msg.reply(content) event.msg.reply(content)

Loading…
Cancel
Save