blueprints: add guilds blueprint

- gateway.websocket: merge get_guild and get_guild_extra
 - gateway.websocket: only apply too many shards close when
     guilds > 2500
 - storage: detach state usage
 - storage: fix large calc on get_guild_extra
This commit is contained in:
Luna Mendes 2018-06-21 03:16:13 -03:00
parent f5ea44c8d7
commit 183013f8f9
7 changed files with 87 additions and 16 deletions

View File

@ -1,3 +1,4 @@
from .gateway import bp as gateway from .gateway import bp as gateway
from .auth import bp as auth from .auth import bp as auth
from .users import bp as users from .users import bp as users
from .guilds import bp as guilds

View File

@ -0,0 +1,60 @@
from quart import Blueprint, request, current_app as app, jsonify
from ..auth import token_check
from ..snowflake import get_snowflake
from ..enums import ChannelType
bp = Blueprint('guilds', __name__)
@bp.route('', methods=['POST'])
async def create_guild():
user_id = await token_check()
j = await request.get_json()
guild_id = get_snowflake()
await app.db.execute(
"""
INSERT INTO guilds (id, name, region, icon, owner_id,
verification_level, default_message_notifications,
explicit_content_filter)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
""", guild_id, j['name'], j['region'], j['icon'], user_id,
j.get('verification_level', 0),
j.get('default_message_notifications', 0),
j.get('explicit_content_filter', 0))
await app.db.execute("""
INSERT INTO members (user_id, guild_id)
VALUES ($1, $2)
""", user_id, guild_id)
everyone_role_id = get_snowflake()
await app.db.execute("""
INSERT INTO roles (id, guild_id, name, position, permissions)
VALUES ($1, $2, $3, $4, $5)
""", everyone_role_id, guild_id, '@everyone', 0, 104324161)
general_id = get_snowflake()
await app.db.execute("""
INSERT INTO channels (id, channel_type)
VALUES ($1, $2)
""", general_id, ChannelType.GUILD_TEXT)
await app.db.execute("""
INSERT INTO guild_channels (id, guild_id, name, position)
VALUES ($1, $2, $3, $4)
""", general_id, guild_id, 'general', 0)
await app.db.execute("""
INSERT INTO guild_text_channels (id)
VALUES ($1)
""", general_id)
guild_json = await app.storage.get_guild(guild_id, user_id)
guild_extra = await app.storage.get_guild_extra(guild_id, user_id, 250)
return jsonify({**guild_json, **guild_extra})

View File

@ -96,7 +96,7 @@ async def leave_guild(guild_id):
return '', 204 return '', 204
@bp.route('/@me/connections', methods=['GET']) # @bp.route('/@me/connections', methods=['GET'])
async def get_connections(): async def get_connections():
pass pass

4
litecord/dispatcher.py Normal file
View File

@ -0,0 +1,4 @@
class EventDispatcher:
"""Pub/Sub routines for litecord."""
pass

View File

@ -109,7 +109,11 @@ class GatewayWebsocket:
} for row in guild_ids] } for row in guild_ids]
return [ return [
await self.storage.get_guild(row[0], self.state) {
**await self.storage.get_guild(row[0], user_id),
**await self.storage.get_guild_extra(row[0], user_id,
self.state.large)
}
for row in guild_ids for row in guild_ids
] ]
@ -122,7 +126,7 @@ class GatewayWebsocket:
for guild_obj in unavailable_guilds: for guild_obj in unavailable_guilds:
guild = await self.storage.get_guild(guild_obj['id'], guild = await self.storage.get_guild(guild_obj['id'],
self.state) self.state.user_id)
if not guild: if not guild:
continue continue
@ -162,8 +166,9 @@ class GatewayWebsocket:
raise ShardingRequired('Too many guilds for shard ' raise ShardingRequired('Too many guilds for shard '
f'{current_shard}') f'{current_shard}')
if guilds / shard_count > 0.8: if guilds > 2500 and guilds / shard_count > 0.8:
raise ShardingRequired('Too many shards.') raise ShardingRequired('Too many shards. '
f'(g={guilds} sc={shard_count})')
if current_shard > shard_count: if current_shard > shard_count:
raise InvalidShard('Shard count > Total shards') raise InvalidShard('Shard count > Total shards')

View File

@ -28,11 +28,10 @@ class Storage:
duser.pop('email') duser.pop('email')
duser.pop('mfa_enabled') duser.pop('mfa_enabled')
duser.pop('verified') duser.pop('verified')
duser.pop('mfa_enabled')
return duser return duser
async def get_guild(self, guild_id: int, state=None) -> Dict: async def get_guild(self, guild_id: int, user_id=None) -> Dict:
"""Get gulid payload.""" """Get gulid payload."""
row = await self.db.fetchrow(""" row = await self.db.fetchrow("""
SELECT * SELECT *
@ -45,8 +44,8 @@ class Storage:
drow = dict(row) drow = dict(row)
if state: if user_id:
drow['owner'] = drow['owner_id'] == state.user_id drow['owner'] = drow['owner_id'] == user_id
# TODO: Probably a really bad idea to repeat str() calls # TODO: Probably a really bad idea to repeat str() calls
# Any ideas to make this simpler? # Any ideas to make this simpler?
@ -76,7 +75,7 @@ class Storage:
async def get_member_data(self, guild_id) -> List[Dict[str, Any]]: async def get_member_data(self, guild_id) -> List[Dict[str, Any]]:
"""Get member information on a guild.""" """Get member information on a guild."""
members_basic = await self.db.fetch(""" members_basic = await self.db.fetch("""
SELECT user_id, nickname, joined_at SELECT user_id, nickname, joined_at, deafened, muted
FROM members FROM members
WHERE guild_id = $1 WHERE guild_id = $1
""", guild_id) """, guild_id)
@ -145,7 +144,7 @@ class Storage:
# type is a SQL keyword, so we can't do # type is a SQL keyword, so we can't do
# 'overwrite_type AS type' # 'overwrite_type AS type'
overwrite_rows = await self.db.fetch(""" overwrite_rows = await self.db.fetch("""
SELECT user_id::text AS id, overwrite_type, allow, deny SELECT target_id::text AS id, overwrite_type, allow, deny
FROM channel_overwrites FROM channel_overwrites
WHERE channel_id = $1 WHERE channel_id = $1
""", row['id']) """, row['id'])
@ -165,7 +164,8 @@ class Storage:
return channels return channels
async def get_guild_extra(self, guild_id: int, state=None) -> Dict: async def get_guild_extra(self, guild_id: int,
user_id=None, large=None) -> Dict:
"""Get extra information about a guild.""" """Get extra information about a guild."""
res = {} res = {}
@ -175,14 +175,14 @@ class Storage:
WHERE guild_id = $1 WHERE guild_id = $1
""", guild_id) """, guild_id)
if state: if user_id and large:
joined_at = await self.db.fetchval(""" joined_at = await self.db.fetchval("""
SELECT joined_at SELECT joined_at
FROM members FROM members
WHERE guild_id = $1 AND user_id = $2 WHERE guild_id = $1 AND user_id = $2
""", guild_id, state.user_id) """, guild_id, user_id)
res['large'] = state.large > member_count res['large'] = member_count > large
res['joined_at'] = joined_at.isoformat() res['joined_at'] = joined_at.isoformat()
members = await self.get_member_data(guild_id) members = await self.get_member_data(guild_id)

3
run.py
View File

@ -8,7 +8,7 @@ from quart import Quart, g, jsonify
from logbook import StreamHandler, Logger from logbook import StreamHandler, Logger
import config import config
from litecord.blueprints import gateway, auth, users from litecord.blueprints import gateway, auth, users, guilds
from litecord.gateway import websocket_handler from litecord.gateway import websocket_handler
from litecord.errors import LitecordError from litecord.errors import LitecordError
from litecord.gateway.state_manager import StateManager from litecord.gateway.state_manager import StateManager
@ -36,6 +36,7 @@ app = make_app()
app.register_blueprint(gateway, url_prefix='/api/v6') app.register_blueprint(gateway, url_prefix='/api/v6')
app.register_blueprint(auth, url_prefix='/api/v6') app.register_blueprint(auth, url_prefix='/api/v6')
app.register_blueprint(users, url_prefix='/api/v6/users') app.register_blueprint(users, url_prefix='/api/v6/users')
app.register_blueprint(guilds, url_prefix='/api/v6/guilds')
@app.before_serving @app.before_serving