litecord: add embed namespace

- embed: add embed.schemas
 - channel.messages: split some functions for readability
This commit is contained in:
Luna 2018-12-04 18:10:58 -03:00
parent d87ff940f6
commit 8b97195404
2 changed files with 198 additions and 67 deletions

View File

@ -139,34 +139,10 @@ async def _dm_pre_dispatch(channel_id, peer_id):
await try_dm_state(peer_id, channel_id) await try_dm_state(peer_id, channel_id)
@bp.route('/<int:channel_id>/messages', methods=['POST']) async def create_message(channel_id: int, actual_guild_id: int,
async def create_message(channel_id): author_id: int, data: dict) -> int:
user_id = await token_check()
ctype, guild_id = await channel_check(user_id, channel_id)
actual_guild_id = None
if ctype in GUILD_CHANS:
await channel_perm_check(user_id, channel_id, 'send_messages')
actual_guild_id = guild_id
j = validate(await request.get_json(), MESSAGE_CREATE)
message_id = get_snowflake() message_id = get_snowflake()
# TODO: check connection to the gateway
can_everyone = await channel_perm_check(
user_id, channel_id, 'mention_everyone', False
)
mentions_everyone = ('@everyone' in j['content']) and can_everyone
mentions_here = ('@here' in j['content']) and can_everyone
is_tts = (j.get('tts', False) and
await channel_perm_check(
user_id, channel_id, 'send_tts_messages', False
))
await app.db.execute( await app.db.execute(
""" """
INSERT INTO messages (id, channel_id, guild_id, author_id, INSERT INTO messages (id, channel_id, guild_id, author_id,
@ -176,33 +152,22 @@ async def create_message(channel_id):
message_id, message_id,
channel_id, channel_id,
actual_guild_id, actual_guild_id,
user_id, author_id,
j['content'], data['content'],
is_tts, data['tts'],
mentions_everyone or mentions_here, data['everyone_mention'],
int(j.get('nonce', 0)), data['nonce'],
MessageType.DEFAULT.value MessageType.DEFAULT.value
) )
payload = await app.storage.get_message(message_id, user_id) return message_id
if ctype == ChannelType.DM: async def _guild_text_mentions(payload: dict, guild_id: int,
# guild id here is the peer's ID. mentions_everyone: bool, mentions_here: bool):
await _dm_pre_dispatch(channel_id, user_id) channel_id = int(payload['channel_id'])
await _dm_pre_dispatch(channel_id, guild_id)
await app.dispatcher.dispatch('channel', channel_id,
'MESSAGE_CREATE', payload)
await app.db.execute("""
UPDATE user_read_state
SET last_message_id = $1
WHERE channel_id = $2 AND user_id = $3
""", message_id, channel_id, user_id)
if ctype == ChannelType.GUILD_TEXT:
# calculate the user ids we'll bump the mention count for # calculate the user ids we'll bump the mention count for
uids = set() uids = set()
@ -252,6 +217,64 @@ async def create_message(channel_id):
AND channel_id = $2 AND channel_id = $2
""", user_id, channel_id) """, user_id, channel_id)
@bp.route('/<int:channel_id>/messages', methods=['POST'])
async def _create_message(channel_id):
"""Create a message."""
user_id = await token_check()
ctype, guild_id = await channel_check(user_id, channel_id)
actual_guild_id = None
if ctype in GUILD_CHANS:
await channel_perm_check(user_id, channel_id, 'send_messages')
actual_guild_id = guild_id
j = validate(await request.get_json(), MESSAGE_CREATE)
message_id = get_snowflake()
# TODO: check connection to the gateway
can_everyone = await channel_perm_check(
user_id, channel_id, 'mention_everyone', False
)
mentions_everyone = ('@everyone' in j['content']) and can_everyone
mentions_here = ('@here' in j['content']) and can_everyone
is_tts = (j.get('tts', False) and
await channel_perm_check(
user_id, channel_id, 'send_tts_messages', False
))
await create_message(channel_id, actual_guild_id, user_id, {
'content': j['content'],
'tts': is_tts,
'nonce': int(j.get('nonce', 0)),
'everyone_mention': mentions_everyone or mentions_here,
})
payload = await app.storage.get_message(message_id, user_id)
if ctype == ChannelType.DM:
# guild id here is the peer's ID.
await _dm_pre_dispatch(channel_id, user_id)
await _dm_pre_dispatch(channel_id, guild_id)
await app.dispatcher.dispatch('channel', channel_id,
'MESSAGE_CREATE', payload)
# update read state for the author
await app.db.execute("""
UPDATE user_read_state
SET last_message_id = $1
WHERE channel_id = $2 AND user_id = $3
""", message_id, channel_id, user_id)
if ctype == ChannelType.GUILD_TEXT:
await _guild_text_mentions(payload, guild_id,
mentions_everyone, mentions_here)
return jsonify(payload) return jsonify(payload)

108
litecord/embed/schemas.py Normal file
View File

@ -0,0 +1,108 @@
"""
litecord.embed.schemas - embed input validators.
"""
import urllib.parse
from litecord.types import Color
class EmbedURL:
def __init__(self, url: str):
parsed = urllib.parse.urlparse(url)
if parsed.scheme not in ('http', 'https', 'attachment'):
raise ValueError('Invalid URL scheme')
self.raw_url = url
self.parsed = parsed
@property
def url(self):
"""Return the URL."""
return urllib.parse.urlunparse(self.parsed)
EMBED_FOOTER = {
'text': {
'type': 'string', 'minlength': 1, 'maxlength': 128, 'required': True},
'icon_url': {
'coerce': EmbedURL, 'required': False,
},
# NOTE: proxy_icon_url set by us
}
EMBED_IMAGE = {
'url': {'coerce': EmbedURL, 'required': True},
# NOTE: proxy_url, width, height set by us
}
EMBED_THUMBNAIL = EMBED_IMAGE
EMBED_AUTHOR = {
'name': {
'type': 'string', 'minlength': 1, 'maxlength': 128, 'required': False
},
'url': {
'type': EmbedURL, 'required': False,
},
'icon_url': {
'coerce': EmbedURL, 'required': False,
}
}
EMBED_OBJECT = {
'title': {
'type': 'string', 'minlength': 1, 'maxlength': 128, 'required': False},
'type': {
'type': 'string', 'allowed': ['rich'], 'required': False,
'default': 'rich'
},
'description': {
'type': 'string', 'minlength': 1, 'maxlength': 1024, 'required': False,
},
'url': {
'coerce': EmbedURL, 'required': False,
},
'timestamp': {
# TODO: an ISO 8601 type
# TODO: maybe replace the default in here with now().isoformat?
'type': 'string', 'required': False
},
'color': {
'coerce': Color, 'required': False
},
'footer': {
'type': 'dict',
'schema': EMBED_FOOTER,
'required': False,
},
'image': {
'type': 'dict',
'schema': EMBED_IMAGE,
'required': False,
},
'thumbnail': {
'type': 'dict',
'schema': EMBED_THUMBNAIL,
'required': False,
},
# NOTE: 'video' set by us
# NOTE: 'provider' set by us
'author': {
'type': 'dict',
'schema': EMBED_AUTHOR,
'required': False,
},
'fields': {
'type': 'list',
'schema': EMBED_AUTHOR,
'required': False,
},
}