mirror of https://gitlab.com/litecord/litecord.git
blueprints.channels: add implementations for some routes
more specifically edit/delete message, and all 3 pin-related routes. - snowflake: add snowflake_datetime
This commit is contained in:
parent
59127ad197
commit
0ca45c781e
|
|
@ -4,7 +4,7 @@ from quart import Blueprint, request, current_app as app, jsonify
|
||||||
from logbook import Logger
|
from logbook import Logger
|
||||||
|
|
||||||
from ..auth import token_check
|
from ..auth import token_check
|
||||||
from ..snowflake import get_snowflake
|
from ..snowflake import get_snowflake, snowflake_datetime
|
||||||
from ..enums import ChannelType, MessageType
|
from ..enums import ChannelType, MessageType
|
||||||
from ..errors import Forbidden, BadRequest, ChannelNotFound, MessageNotFound
|
from ..errors import Forbidden, BadRequest, ChannelNotFound, MessageNotFound
|
||||||
from ..schemas import validate, MESSAGE_CREATE
|
from ..schemas import validate, MESSAGE_CREATE
|
||||||
|
|
@ -73,7 +73,6 @@ async def get_messages(channel_id):
|
||||||
result.append(msg)
|
result.append(msg)
|
||||||
|
|
||||||
log.info('Fetched {} messages', len(result))
|
log.info('Fetched {} messages', len(result))
|
||||||
print(result)
|
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -119,6 +118,151 @@ async def create_message(channel_id):
|
||||||
return jsonify(payload)
|
return jsonify(payload)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/<int:channel_id>/messages/<int:message_id>', methods=['PATCH'])
|
||||||
|
async def edit_message(channel_id, message_id):
|
||||||
|
user_id = await token_check()
|
||||||
|
guild_id = await channel_check(user_id, channel_id)
|
||||||
|
|
||||||
|
author_id = await app.db.fetchval("""
|
||||||
|
SELECT author_id FROM messages
|
||||||
|
WHERE messages.id = $1
|
||||||
|
""", message_id)
|
||||||
|
|
||||||
|
if not author_id == user_id:
|
||||||
|
raise Forbidden('You can not edit this message')
|
||||||
|
|
||||||
|
j = await request.get_json()
|
||||||
|
updated = 'content' in j or 'embed' in j
|
||||||
|
|
||||||
|
if 'content' in j:
|
||||||
|
await app.db.execute("""
|
||||||
|
UPDATE messages
|
||||||
|
SET content=$1
|
||||||
|
WHERE messages.id = $2
|
||||||
|
""", j['content'], message_id)
|
||||||
|
|
||||||
|
# TODO: update embed
|
||||||
|
|
||||||
|
message = await app.storage.get_message(message_id)
|
||||||
|
|
||||||
|
# only dispatch MESSAGE_CREATE if we actually had any update to start with
|
||||||
|
if updated:
|
||||||
|
await app.dispatcher.dispatch_guild(guild_id,
|
||||||
|
'MESSAGE_UPDATE', message)
|
||||||
|
|
||||||
|
return jsonify(message)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/<int:channel_id>/messages/<int:message_id>', methods=['DELETE'])
|
||||||
|
async def delete_message(channel_id, message_id):
|
||||||
|
user_id = await token_check()
|
||||||
|
guild_id = await channel_check(user_id, channel_id)
|
||||||
|
|
||||||
|
author_id = await app.db.fetchval("""
|
||||||
|
SELECT author_id FROM messages
|
||||||
|
WHERE messages.id = $1
|
||||||
|
""", message_id)
|
||||||
|
|
||||||
|
# TODO: MANAGE_MESSAGES permission check
|
||||||
|
if not author_id == user_id:
|
||||||
|
raise Forbidden('You can not delete this message')
|
||||||
|
|
||||||
|
await app.db.execute("""
|
||||||
|
DELETE FROM messages
|
||||||
|
WHERE messages.id = $1
|
||||||
|
""", message_id)
|
||||||
|
|
||||||
|
await app.dispatcher.dispatch_guild(guild_id, 'MESSAGE_DELETE', {
|
||||||
|
'id': str(message_id),
|
||||||
|
'channel_id': str(channel_id)
|
||||||
|
})
|
||||||
|
|
||||||
|
return '', 204
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/<int:channel_id>/pins', methods=['GET'])
|
||||||
|
async def get_pins(channel_id):
|
||||||
|
user_id = await token_check()
|
||||||
|
await channel_check(user_id, channel_id)
|
||||||
|
|
||||||
|
ids = await app.db.fetch("""
|
||||||
|
SELECT message_id
|
||||||
|
FROM channel_pins
|
||||||
|
WHERE channel_id = $1
|
||||||
|
ORDER BY message_id ASC
|
||||||
|
""", channel_id)
|
||||||
|
|
||||||
|
ids = [r['message_id'] for r in ids]
|
||||||
|
res = []
|
||||||
|
|
||||||
|
for message_id in ids:
|
||||||
|
message = await app.storage.get_message(message_id)
|
||||||
|
if message is not None:
|
||||||
|
res.append(message)
|
||||||
|
|
||||||
|
return jsonify(message)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/<int:channel_id>/pins/<int:message_id>', methods=['PUT'])
|
||||||
|
async def add_pin(channel_id, message_id):
|
||||||
|
user_id = await token_check()
|
||||||
|
guild_id = await channel_check(user_id, channel_id)
|
||||||
|
|
||||||
|
# TODO: check MANAGE_MESSAGES permission
|
||||||
|
|
||||||
|
await app.db.execute("""
|
||||||
|
INSERT INTO channel_pins (channel_id, message_id)
|
||||||
|
VALUES ($1, $2)
|
||||||
|
""", channel_id, message_id)
|
||||||
|
|
||||||
|
row = await app.db.fetchrow("""
|
||||||
|
SELECT message_id
|
||||||
|
FROM channel_pins
|
||||||
|
WHERE channel_id = $1
|
||||||
|
ORDER BY message_id ASC
|
||||||
|
LIMIT 1
|
||||||
|
""", channel_id)
|
||||||
|
|
||||||
|
timestamp = snowflake_datetime(row['message_id'])
|
||||||
|
|
||||||
|
await app.dispatcher.dispatch_guild(guild_id, 'CHANNEL_PINS_UPDATE', {
|
||||||
|
'channel_id': str(channel_id),
|
||||||
|
'last_pin_timestamp': timestamp.isoformat()
|
||||||
|
})
|
||||||
|
|
||||||
|
return '', 204
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/<int:channel_id>/pins/<int:message_id>', methods=['DELETE'])
|
||||||
|
async def delete_pin(channel_id, message_id):
|
||||||
|
user_id = await token_check()
|
||||||
|
guild_id = await channel_check(user_id, channel_id)
|
||||||
|
|
||||||
|
# TODO: check MANAGE_MESSAGES permission
|
||||||
|
|
||||||
|
await app.db.execute("""
|
||||||
|
DELETE FROM channel_pins
|
||||||
|
WHERE channel_id = $1 AND message_id = $2
|
||||||
|
""", channel_id, message_id)
|
||||||
|
|
||||||
|
row = await app.db.fetchrow("""
|
||||||
|
SELECT message_id
|
||||||
|
FROM channel_pins
|
||||||
|
WHERE channel_id = $1
|
||||||
|
ORDER BY message_id ASC
|
||||||
|
LIMIT 1
|
||||||
|
""", channel_id)
|
||||||
|
|
||||||
|
timestamp = snowflake_datetime(row['message_id'])
|
||||||
|
|
||||||
|
await app.dispatcher.dispatch_guild(guild_id, 'CHANNEL_PINS_UPDATE', {
|
||||||
|
'channel_id': str(channel_id),
|
||||||
|
'last_pin_timestamp': timestamp.isoformat()
|
||||||
|
})
|
||||||
|
|
||||||
|
return '', 204
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/<int:channel_id>/typing', methods=['POST'])
|
@bp.route('/<int:channel_id>/typing', methods=['POST'])
|
||||||
async def trigger_typing(channel_id):
|
async def trigger_typing(channel_id):
|
||||||
user_id = await token_check()
|
user_id = await token_check()
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,11 @@ snowflake.py - snowflake helper functions
|
||||||
File brought in from
|
File brought in from
|
||||||
litecord-reference(https://github.com/lnmds/litecord-reference)
|
litecord-reference(https://github.com/lnmds/litecord-reference)
|
||||||
"""
|
"""
|
||||||
import time
|
|
||||||
import hashlib
|
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
import base64
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import datetime
|
||||||
|
|
||||||
# encoded in ms
|
# encoded in ms
|
||||||
EPOCH = 1420070400000
|
EPOCH = 1420070400000
|
||||||
|
|
@ -90,6 +91,12 @@ def snowflake_time(snowflake: Snowflake) -> float:
|
||||||
return timestamp / 1000
|
return timestamp / 1000
|
||||||
|
|
||||||
|
|
||||||
|
def snowflake_datetime(snowflake: Snowflake) -> datetime.datetime:
|
||||||
|
"""Return a datetime object representing the snowflake."""
|
||||||
|
unix_ts = snowflake_time(snowflake)
|
||||||
|
return datetime.datetime.fromtimestamp(unix_ts)
|
||||||
|
|
||||||
|
|
||||||
def get_snowflake():
|
def get_snowflake():
|
||||||
"""Generate a snowflake"""
|
"""Generate a snowflake"""
|
||||||
return _snowflake(int(time.time() * 1000))
|
return _snowflake(int(time.time() * 1000))
|
||||||
|
|
|
||||||
2
run.py
2
run.py
|
|
@ -64,7 +64,7 @@ async def app_before_serving():
|
||||||
# We wrap the main websocket_handler
|
# We wrap the main websocket_handler
|
||||||
# so we can pass quart's app object.
|
# so we can pass quart's app object.
|
||||||
await websocket_handler((app.db, app.state_manager, app.storage,
|
await websocket_handler((app.db, app.state_manager, app.storage,
|
||||||
app.loop, app.dispatcher), ws, url)
|
app.loop, app.dispatcher), ws, url)
|
||||||
|
|
||||||
ws_future = websockets.serve(_wrapper, host, port)
|
ws_future = websockets.serve(_wrapper, host, port)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -372,6 +372,6 @@ CREATE TABLE IF NOT EXISTS message_reactions (
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS channel_pins (
|
CREATE TABLE IF NOT EXISTS channel_pins (
|
||||||
channel_id bigint REFERENCES channels (id) UNIQUE,
|
channel_id bigint REFERENCES channels (id) UNIQUE,
|
||||||
message_id bigint REFERENCEs messages (id),
|
message_id bigint REFERENCES messages (id),
|
||||||
PRIMARY KEY (channel_id, message_id)
|
PRIMARY KEY (channel_id, message_id)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue