Browse Source

Tons more gateway/events stuff

pull/3/head
Andrei 9 years ago
parent
commit
3f696ffd85
  1. 0
      disco/bot/__init__.py
  2. 21
      disco/gateway/client.py
  3. 151
      disco/gateway/events.py
  4. 0
      disco/state.py
  5. 5
      disco/types/__init__.py
  6. 42
      disco/types/channel.py
  7. 53
      disco/types/guild.py
  8. 44
      disco/types/message.py
  9. 7
      disco/types/user.py
  10. 5
      disco/types/voice.py
  11. 18
      disco/util/types.py

0
disco/bot/__init__.py

21
disco/gateway/client.py

@ -7,10 +7,11 @@ from holster.emitter import Emitter
# from holster.util import SimpleObject # from holster.util import SimpleObject
from disco.gateway.packets import OPCode, HeartbeatPacket, ResumePacket, IdentifyPacket from disco.gateway.packets import OPCode, HeartbeatPacket, ResumePacket, IdentifyPacket
from disco.gateway.events import GatewayEvent from disco.gateway.events import GatewayEvent, Ready
from disco.util.logging import LoggingClass from disco.util.logging import LoggingClass
GATEWAY_VERSION = 6 GATEWAY_VERSION = 6
TEN_MEGABYTES = 10490000
def log_error(log, msg, w): def log_error(log, msg, w):
@ -29,12 +30,15 @@ class GatewayClient(LoggingClass):
self.client = client self.client = client
self.emitter = Emitter(gevent.spawn) self.emitter = Emitter(gevent.spawn)
self.emitter.on(Ready, self.on_ready)
# Websocket connection # Websocket connection
self.ws = None self.ws = None
# State # State
self.seq = 0 self.seq = 0
self.session_id = None self.session_id = None
self.reconnects = 0
# Cached gateway URL # Cached gateway URL
self._cached_gateway_url = None self._cached_gateway_url = None
@ -56,8 +60,9 @@ class GatewayClient(LoggingClass):
gevent.sleep(interval / 1000) gevent.sleep(interval / 1000)
def handle_dispatch(self, packet): def handle_dispatch(self, packet):
obj = GatewayEvent.from_dispatch(packet) cls, obj = GatewayEvent.from_dispatch(packet)
self.log.info('Got dispatch for %s', obj.user.id) self.log.info('Dispatching %s', cls)
self.emitter.emit(cls, obj)
def handle_heartbeat(self, packet): def handle_heartbeat(self, packet):
pass pass
@ -75,6 +80,11 @@ class GatewayClient(LoggingClass):
def handle_heartbeat_ack(self, packet): def handle_heartbeat_ack(self, packet):
pass pass
def on_ready(self, ready):
self.log.info('Recieved READY')
self.session_id = ready.session_id
self.reconnects = 0
def connect(self): def connect(self):
if not self._cached_gateway_url: if not self._cached_gateway_url:
self._cached_gateway_url = self.client.api.gateway(version=GATEWAY_VERSION, encoding='json') self._cached_gateway_url = self.client.api.gateway(version=GATEWAY_VERSION, encoding='json')
@ -89,10 +99,9 @@ class GatewayClient(LoggingClass):
) )
def on_message(self, ws, msg): def on_message(self, ws, msg):
# Check if we're JSON # Detect zlib and decompress
if msg[0] != '{': if msg[0] != '{':
print 'zlib' msg = zlib.decompress(msg, 15, TEN_MEGABYTES)
msg = zlib.decompress(msg)
try: try:
data = json.loads(msg) data = json.loads(msg)

151
disco/gateway/events.py

@ -1,8 +1,7 @@
import inflection import inflection
import skema import skema
from disco.types.user import User from disco.types import Guild, Channel, User, GuildMember, Role, Message, VoiceState
from disco.types.guild import Guild
class GatewayEvent(skema.Model): class GatewayEvent(skema.Model):
@ -12,7 +11,25 @@ class GatewayEvent(skema.Model):
if not cls: if not cls:
raise Exception('Could not find cls for {}'.format(obj['t'])) raise Exception('Could not find cls for {}'.format(obj['t']))
return cls(obj['d']) return cls, cls.create(obj['d'])
@classmethod
def create(cls, obj):
self = cls(obj)
self.validate()
return self
def Sub(field):
class _T(GatewayEvent):
@classmethod
def create(cls, obj):
obj[field] = obj
self = cls(obj)
self.validate()
return self
return _T
class Ready(GatewayEvent): class Ready(GatewayEvent):
@ -20,3 +37,131 @@ class Ready(GatewayEvent):
session_id = skema.StringType() session_id = skema.StringType()
user = skema.ModelType(User) user = skema.ModelType(User)
guilds = skema.ListType(skema.ModelType(Guild)) guilds = skema.ListType(skema.ModelType(Guild))
class Resumed(GatewayEvent):
pass
class GuildCreate(Sub('guild')):
guild = skema.ModelType(Guild)
unavailable = skema.BooleanType(default=None)
class GuildUpdate(Sub('guild')):
guild = skema.ModelType(Guild)
class GuildDelete(GatewayEvent):
id = skema.SnowflakeType()
unavailable = skema.BooleanType(default=None)
class ChannelCreate(Sub('channel')):
channel = skema.ModelType(Channel)
class ChannelUpdate(Sub('channel')):
channel = skema.ModelType(Channel)
class ChannelDelete(Sub('channel')):
channel = skema.ModelType(Channel)
class ChannelPinsUpdate(GatewayEvent):
channel_id = skema.SnowflakeType()
last_pin_timestamp = skema.IntType()
class GuildBanAdd(Sub('user')):
user = skema.ModelType(User)
class GuildBanRemove(Sub('user')):
user = skema.ModelType(User)
class GuildEmojisUpdate(GatewayEvent):
pass
class GuildIntegrationsUpdate(GatewayEvent):
pass
class GuildMembersChunk(GatewayEvent):
guild_id = skema.SnowflakeType()
members = skema.ListType(skema.ModelType(GuildMember))
class GuildMemberAdd(Sub('member')):
member = skema.ModelType(GuildMember)
class GuildMemberRemove(GatewayEvent):
guild_id = skema.SnowflakeType()
user = skema.ModelType(User)
class GuildMemberUpdate(GatewayEvent):
guild_id = skema.SnowflakeType()
user = skema.ModelType(User)
roles = skema.ListType(skema.SnowflakeType())
class GuildRoleCreate(GatewayEvent):
guild_id = skema.SnowflakeType()
role = skema.ModelType(Role)
class GuildRoleUpdate(GatewayEvent):
guild_id = skema.SnowflakeType()
role = skema.ModelType(Role)
class GuildRoleDelete(GatewayEvent):
guild_id = skema.SnowflakeType()
role = skema.ModelType(Role)
class MessageCreate(Sub('message')):
message = skema.ModelType(Message)
class MessageUpdate(Sub('message')):
message = skema.ModelType(Message)
class MessageDelete(GatewayEvent):
id = skema.SnowflakeType()
channel_id = skema.SnowflakeType()
class MessageDeleteBulk(GatewayEvent):
channel_id = skema.SnowflakeType()
ids = skema.ListType(skema.SnowflakeType())
class PresenceUpdate(GatewayEvent):
user = skema.ModelType(User)
guild_id = skema.SnowflakeType()
roles = skema.ListType(skema.SnowflakeType())
game = skema.StringType()
status = skema.StringType()
class TypingStart(GatewayEvent):
channel_id = skema.SnowflakeType()
user_id = skema.SnowflakeType()
timestamp = skema.IntType()
class VoiceStateUpdate(Sub('state')):
state = skema.ModelType(VoiceState)
class VoiceServerUpdate(GatewayEvent):
token = skema.StringType()
endpoint = skema.StringType()
guild_id = skema.SnowflakeType()

0
disco/state.py

5
disco/types/__init__.py

@ -0,0 +1,5 @@
from disco.types.channel import Channel
from disco.types.guild import Guild, GuildMember, Role
from disco.types.user import User
from disco.types.message import Message
from disco.types.voice import VoiceState

42
disco/types/channel.py

@ -0,0 +1,42 @@
import skema
from holster.enum import Enum
# from disco.types.guild import Guild
from disco.types.user import User
ChannelType = Enum(
GUILD_TEXT=0,
DM=1,
GUILD_VOICE=2,
GROUP_DM=3,
)
PermissionOverwriteType = Enum(
ROLE='role',
MEMBER='member'
)
class PermissionOverwrite(skema.Model):
id = skema.SnowflakeType()
type = skema.StringType(choices=PermissionOverwriteType.ALL_VALUES)
allow = skema.IntType()
deny = skema.IntType()
class Channel(skema.Model):
id = skema.SnowflakeType()
name = skema.StringType()
topic = skema.StringType()
last_message_id = skema.SnowflakeType()
position = skema.IntType()
bitrate = skema.IntType(required=False)
recipient = skema.ModelType(User, required=False)
type = skema.IntType(choices=ChannelType.ALL_VALUES)
permission_overwrites = skema.ListType(skema.ModelType(PermissionOverwrite))

53
disco/types/guild.py

@ -1,7 +1,58 @@
import skema import skema
from disco.util.oop import TypedClass from disco.util.types import PreHookType
from disco.types.user import User
from disco.types.voice import VoiceState
from disco.types.channel import Channel
class Emoji(skema.Model):
id = skema.SnowflakeType()
name = skema.StringType()
require_colons = skema.BooleanType()
managed = skema.BooleanType()
roles = skema.ListType(skema.SnowflakeType())
class Role(skema.Model):
id = skema.SnowflakeType()
name = skema.StringType()
hoist = skema.BooleanType()
managed = skema.BooleanType()
color = skema.IntType()
permissions = skema.IntType()
position = skema.IntType()
class GuildMember(skema.Model):
user = skema.ModelType(User)
mute = skema.BooleanType()
deaf = skema.BooleanType()
joined_at = PreHookType(lambda k: k[:-6], skema.DateTimeType())
roles = skema.ListType(skema.SnowflakeType())
class Guild(skema.Model): class Guild(skema.Model):
id = skema.SnowflakeType() id = skema.SnowflakeType()
owner_id = skema.SnowflakeType()
afk_channel_id = skema.SnowflakeType()
embed_channel_id = skema.SnowflakeType()
name = skema.StringType()
icon = skema.BinaryType(None)
splash = skema.BinaryType(None)
region = skema.StringType()
afk_timeout = skema.IntType()
embed_enabled = skema.BooleanType()
verification_level = skema.IntType()
mfa_level = skema.IntType()
features = skema.ListType(skema.StringType())
members = skema.ListType(skema.ModelType(GuildMember))
voice_states = skema.ListType(skema.ModelType(VoiceState))
channels = skema.ListType(skema.ModelType(Channel))
roles = skema.ListType(skema.ModelType(Role))
emojis = skema.ListType(skema.ModelType(Emoji))

44
disco/types/message.py

@ -0,0 +1,44 @@
import skema
from disco.util.types import PreHookType
from disco.types.user import User
class MessageEmbed(skema.Model):
title = skema.StringType()
type = skema.StringType()
description = skema.StringType()
url = skema.StringType()
class MessageAttachment(skema.Model):
id = skema.SnowflakeType()
filename = skema.StringType()
url = skema.StringType()
proxy_url = skema.StringType()
size = skema.IntType()
height = skema.IntType()
width = skema.IntType()
class Message(skema.Model):
id = skema.SnowflakeType()
channel_id = skema.SnowflakeType()
author = skema.ModelType(User)
content = skema.StringType()
nonce = skema.StringType()
timestamp = PreHookType(lambda k: k[:-6], skema.DateTimeType())
edited_timestamp = PreHookType(lambda k: k[:-6], skema.DateTimeType())
tts = skema.BooleanType()
mention_everyone = skema.BooleanType()
pinned = skema.BooleanType(required=False)
mentions = skema.ListType(skema.ModelType(User))
mention_roles = skema.ListType(skema.SnowflakeType())
embeds = skema.ListType(skema.ModelType(MessageEmbed))
attachment = skema.ListType(skema.ModelType(MessageAttachment))

7
disco/types/user.py

@ -3,3 +3,10 @@ import skema
class User(skema.Model): class User(skema.Model):
id = skema.SnowflakeType() id = skema.SnowflakeType()
username = skema.StringType()
discriminator = skema.StringType()
avatar = skema.BinaryType(None)
verified = skema.BooleanType(required=False)
email = skema.EmailType(required=False)

5
disco/types/voice.py

@ -0,0 +1,5 @@
import skema
class VoiceState(skema.Model):
id = skema.SnowflakeType()

18
disco/util/types.py

@ -0,0 +1,18 @@
from skema import BaseType
class PreHookType(BaseType):
_hashable = False
def __init__(self, func, field, **kwargs):
self.func = func
self.field = field
super(PreHookType, self).__init__(**kwargs)
def to_python(self, value):
value = self.func(value)
return self.field.to_python(value)
def to_storage(self, *args, **kwargs):
return self.field.to_storage(*args, **kwargs)
Loading…
Cancel
Save