Browse Source

Add permissions support, etc fixes/tweaks

pull/3/head
Andrei 9 years ago
parent
commit
4c41010fc1
  1. 9
      disco/api/http.py
  2. 2
      disco/bot/bot.py
  3. 34
      disco/bot/parser.py
  4. 5
      disco/types/channel.py
  5. 3
      disco/types/guild.py
  6. 5
      disco/types/message.py
  7. 71
      disco/types/permissions.py
  8. 6
      disco/types/user.py
  9. 1
      disco/util/websocket.py

9
disco/api/http.py

@ -88,9 +88,14 @@ class Routes(object):
class APIException(Exception):
def __init__(self, msg, status_code=0, content=None):
super(APIException, self).__init__(msg)
self.status_code = status_code
self.content = content
self.msg = msg
if self.status_code:
self.msg += ' code: {}'.format(status_code)
super(APIException, self).__init__(self.msg)
class HTTPClient(LoggingClass):
@ -132,6 +137,8 @@ class HTTPClient(LoggingClass):
# If we got a success status code, just return the data
if r.status_code < 400:
return r
elif 400 < r.status_code < 500:
raise APIException('Request failed', r.status_code, r.content)
else:
if r.status_code == 429:
self.log.warning('Request responded w/ 429, retrying (but this should not happen, check your clock sync')

2
disco/bot/bot.py

@ -126,7 +126,7 @@ class Bot(object):
if cls.__name__ in self.plugins:
raise Exception('Cannot add already added plugin: {}'.format(cls.__name__))
config = self.config.plugin_config_provider(cls.__name__) if self.config.plugin_config_provider else {}
config = self.config.plugin_config_provider(cls.__name__) if self.config.plugin_config_provider else None
self.plugins[cls.__name__] = cls(self, config)
self.plugins[cls.__name__].load()

34
disco/bot/parser.py

@ -1,4 +1,6 @@
import re
import copy
PARTS_RE = re.compile('(\<|\[)((?:\w+|\:|\||\.\.\.| (?:[0-9]+))+)(?:\>|\])')
@ -26,15 +28,6 @@ class Argument(object):
def true_count(self):
return self.count or 1
def convert(self, obj):
for typ in self.types:
typ = TYPE_MAP.get(typ)
try:
return typ(obj)
except Exception as e:
continue
raise e
def parse(self, raw):
prefix, part = raw
@ -58,8 +51,23 @@ class Argument(object):
class ArgumentSet(object):
def __init__(self, args=None):
def __init__(self, args=None, custom_types=None):
self.args = args or []
self.types = copy.copy(TYPE_MAP)
self.types.update(custom_types)
def convert(self, types, value):
for typ_name in types:
typ = self.types.get(typ_name)
if not typ:
raise Exception('Unknown type {}'.format(typ_name))
try:
return typ(value)
except Exception as e:
continue
raise e
def append(self, arg):
if self.args and not self.args[-1].required and arg.required:
@ -85,7 +93,7 @@ class ArgumentSet(object):
if arg.types:
for idx, r in enumerate(raw):
try:
raw[idx] = arg.convert(r)
raw[idx] = self.convert(arg.types, r)
except:
raise ArgumentError('cannot convert `{}` to `{}`'.format(
r, ', '.join(arg.types)
@ -110,8 +118,8 @@ class ArgumentSet(object):
return sum([i.true_count for i in self.args if i.required])
def parse_arguments(line):
args = ArgumentSet()
def parse_arguments(line, custom_types=None):
args = ArgumentSet(custom_types=custom_types)
data = PARTS_RE.findall(line)
if len(data):

5
disco/types/channel.py

@ -6,6 +6,7 @@ from disco.util.cache import cached_property
from disco.util.types import ListToDictType
from disco.types.base import BaseType
from disco.types.user import User
from disco.types.permissions import *
from disco.voice.client import VoiceClient
@ -26,8 +27,8 @@ class PermissionOverwrite(BaseType):
id = skema.SnowflakeType()
type = skema.StringType(choices=PermissionOverwriteType.ALL_VALUES)
allow = skema.IntType()
deny = skema.IntType()
allow = PermissionType()
deny = PermissionType()
class Channel(BaseType):

3
disco/types/guild.py

@ -7,6 +7,7 @@ from disco.types.base import BaseType
from disco.util.types import PreHookType, ListToDictType
from disco.types.user import User
from disco.types.voice import VoiceState
from disco.types.permissions import PermissionType
from disco.types.channel import Channel
@ -24,7 +25,7 @@ class Role(BaseType):
hoist = skema.BooleanType()
managed = skema.BooleanType()
color = skema.IntType()
permissions = skema.IntType()
permissions = PermissionType()
position = skema.IntType()

5
disco/types/message.py

@ -47,6 +47,9 @@ class Message(BaseType):
embeds = skema.ListType(skema.ModelType(MessageEmbed))
attachments = ListToDictType('id', skema.ModelType(MessageAttachment))
def __str__(self):
return '<Message {} ({})>'.format(self.id, self.channel_id)
@cached_property
def guild(self):
return self.channel.guild
@ -61,7 +64,7 @@ class Message(BaseType):
def edit(self, content):
return self.client.api.channels_messages_modify(self.channel_id, self.id, content)
def delete(self, content):
def delete(self):
return self.client.api.channels_messages_delete(self.channel_id, self.id)
def is_mentioned(self, entity):

71
disco/types/permissions.py

@ -0,0 +1,71 @@
from skema import NumberType
from holster.enum import Enum
Permissions = Enum(
NONE=0,
CREATE_INSTANT_INVITE=1 << 0,
KICK_MEMBERS=1 << 1,
BAN_MEMBERS=1 << 2,
ADMINISTRATOR=1 << 3,
MANAGE_CHANNELS=1 << 4,
MANAGE_GUILD=1 << 5,
READ_MESSAGES=1 << 10,
SEND_MESSAGES=1 << 11,
SEND_TSS_MESSAGES=1 << 12,
MANAGE_MESSAGES=1 << 13,
EMBED_LINKS=1 << 14,
ATTACH_FILES=1 << 15,
READ_MESSAGE_HISTORY=1 << 16,
MENTION_EVERYONE=1 << 17,
USE_EXTERNAL_EMOJIS=1 << 18,
CONNECT=1 << 20,
SPEAK=1 << 21,
MUTE_MEMBERS=1 << 22,
DEAFEN_MEMBERS=1 << 23,
MOVE_MEMBERS=1 << 24,
USE_VAD=1 << 25,
CHANGE_NICKNAME=1 << 26,
MANAGE_NICKNAMES=1 << 27,
MANAGE_ROLES=1 << 28,
MANAGE_WEBHOOKS=1 << 29,
MANAGE_EMOJIS=1 << 30,
)
class PermissionValue(object):
def __init__(self, value):
self.value = value
def __getattribute__(self, name):
if name in Permissions.attrs:
return (self.value & Permissions[name].value) == Permissions[name].value
else:
return object.__getattribute__(self, name)
def __setattr__(self, name, value):
if name not in Permissions.attrs:
return super(PermissionValue, self).__setattr__(name, value)
if value:
self.value |= Permissions[name].value
else:
self.value &= ~Permissions[name].value
def to_dict(self):
return {
k: getattr(self, k) for k in Permissions.attrs
}
@classmethod
def text(cls):
return cls(523264)
@classmethod
def voice(cls):
return cls(66060288)
class PermissionType(NumberType):
def __init__(self, *args, **kwargs):
super(PermissionType, self).__init__(number_class=PermissionValue, number_type='PermissionValue', *args, **kwargs)

6
disco/types/user.py

@ -13,5 +13,11 @@ class User(BaseType):
verified = skema.BooleanType(required=False)
email = skema.EmailType(required=False)
def to_string(self):
return '{}#{}'.format(self.username, self.discriminator)
def __str__(self):
return '<User {} ({})>'.format(self.id, self.to_string())
def on_create(self):
self.client.state.users[self.id] = self

1
disco/util/websocket.py

@ -66,7 +66,6 @@ class WebsocketProcessProxy(object):
self.emitter = Emitter(gevent.spawn)
gevent.signal(signal.SIGINT, self.handle_signal)
gevent.signal(signal.SIGQUIT, self.handle_signal)
gevent.signal(signal.SIGTERM, self.handle_signal)
def handle_signal(self, *args):

Loading…
Cancel
Save