From 53c49711cc7b1144f35d92b8e105b37c950e8dc6 Mon Sep 17 00:00:00 2001 From: Evie Viau Date: Sun, 5 Sep 2021 03:23:00 +0000 Subject: [PATCH] Implement inline replies --- .gitignore | 1 + litecord/blueprints/channel/messages.py | 17 +++++++++++------ litecord/blueprints/channel/pins.py | 3 ++- litecord/blueprints/users.py | 3 ++- litecord/common/messages.py | 7 +++++++ litecord/gateway/state.py | 6 ++++++ litecord/schemas.py | 19 +++++++++++++++++++ litecord/storage.py | 3 +-- litecord/utils.py | 4 +++- .../migration/scripts/12_inline_replies.sql | 3 +++ 10 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 manage/cmd/migration/scripts/12_inline_replies.sql diff --git a/.gitignore b/.gitignore index 2ba771e..c64e057 100644 --- a/.gitignore +++ b/.gitignore @@ -109,3 +109,4 @@ attachments/* .DS_Store .vscode +.idea \ No newline at end of file diff --git a/litecord/blueprints/channel/messages.py b/litecord/blueprints/channel/messages.py index fcce097..98f7e3b 100644 --- a/litecord/blueprints/channel/messages.py +++ b/litecord/blueprints/channel/messages.py @@ -41,6 +41,7 @@ from litecord.common.messages import ( msg_create_check_content, msg_add_attachment, msg_guild_text_mentions, + message_view, ) from litecord.pubsub.user import dispatch_user @@ -129,7 +130,7 @@ async def get_messages(channel_id): if msg is None: continue - result.append(msg) + result.append(message_view(msg)) log.info("Fetched {} messages", len(result)) return jsonify(result) @@ -146,7 +147,7 @@ async def get_single_message(channel_id, message_id): if not message: raise MessageNotFound() - return jsonify(message) + return jsonify(message_view(message)) async def _dm_pre_dispatch(channel_id, peer_id): @@ -196,8 +197,8 @@ async def create_message( """ INSERT INTO messages (id, channel_id, guild_id, author_id, content, tts, mention_everyone, nonce, message_type, - embeds) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) + embeds, message_reference, allowed_mentions) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) """, message_id, channel_id, @@ -209,6 +210,8 @@ async def create_message( data["nonce"], MessageType.DEFAULT.value, data.get("embeds") or [], + data.get("message_reference") or None, + data.get("allowed_mentions") or None, ) return message_id @@ -266,6 +269,8 @@ async def _create_message(channel_id): "embeds": ( [await fill_embed(j["embed"])] if j.get("embed") is not None else [] ), + "message_reference": j.get("message_reference"), + "allowed_mentions": j.get("allowed_mentions"), }, ) @@ -304,7 +309,7 @@ async def _create_message(channel_id): payload, guild_id, mentions_everyone, mentions_here ) - return jsonify(payload) + return jsonify(message_view(payload)) @bp.route("//messages/", methods=["PATCH"]) @@ -390,7 +395,7 @@ async def edit_message(channel_id, message_id): if updated: await app.dispatcher.channel.dispatch(channel_id, ("MESSAGE_UPDATE", message)) - return jsonify(message) + return jsonify(message_view(message)) async def _del_msg_fkeys(message_id: int): diff --git a/litecord/blueprints/channel/pins.py b/litecord/blueprints/channel/pins.py index 6e683d8..3e5e9d2 100644 --- a/litecord/blueprints/channel/pins.py +++ b/litecord/blueprints/channel/pins.py @@ -26,6 +26,7 @@ from litecord.types import timestamp_ from litecord.system_messages import send_sys_message from litecord.enums import MessageType, SYS_MESSAGES from litecord.errors import BadRequest +from litecord.common.messages import message_view bp = Blueprint("channel_pins", __name__) @@ -58,7 +59,7 @@ async def get_pins(channel_id): for message_id in ids: message = await app.storage.get_message(message_id) if message is not None: - res.append(message) + res.append(message_view(message)) return jsonify(res) diff --git a/litecord/blueprints/users.py b/litecord/blueprints/users.py index dc1869e..7757c8e 100644 --- a/litecord/blueprints/users.py +++ b/litecord/blueprints/users.py @@ -36,6 +36,7 @@ from litecord.permissions import base_permissions from litecord.blueprints.auth import check_password from litecord.utils import to_update +from litecord.common.messages import message_view from litecord.common.users import ( mass_user_update, delete_user, @@ -470,7 +471,7 @@ async def _get_mentions(): if gid not in guild_ids: continue - res.append(message) + res.append(message_view(message)) return jsonify(res) diff --git a/litecord/common/messages.py b/litecord/common/messages.py index 0768487..f2308db 100644 --- a/litecord/common/messages.py +++ b/litecord/common/messages.py @@ -192,3 +192,10 @@ async def msg_guild_text_mentions( user_id, channel_id, ) + + +def message_view(message_data: dict) -> dict: + # Change message type to 19 if this is a reply to another message + if message_data["message_reference"] and request.discord_api_version > 7: + return {**message_data, **{"type": 19}} + return message_data diff --git a/litecord/gateway/state.py b/litecord/gateway/state.py index 774763a..125ff73 100644 --- a/litecord/gateway/state.py +++ b/litecord/gateway/state.py @@ -128,6 +128,12 @@ class GatewayState: try: if self.ws: + if ( + event_type.startswith("MESSAGE_") + and payload["d"]["message_reference"] is not None + and self.ws.ws_properties.version > 7 + ): + payload["d"]["type"] = 19 await self.ws.send(payload) except websockets.exceptions.ConnectionClosed as exc: log.warning( diff --git a/litecord/schemas.py b/litecord/schemas.py index a9388db..2d4fca1 100644 --- a/litecord/schemas.py +++ b/litecord/schemas.py @@ -435,6 +435,25 @@ MESSAGE_CREATE = { "required": False, "nullable": True, }, + "message_reference": { + "type": "dict", + "required": False, + "nullable": True, + "schema": { + "guild_id": {"type": "string", "required": False}, + "channel_id": {"type": "string", "required": True}, + "message_id": {"type": "string", "required": True}, + }, + }, + "allowed_mentions": { + "type": "dict", + "required": False, + "nullable": True, + "schema": { + "parse": {"type": "list", "required": True}, + "replied_user": {"type": "boolean", "required": True}, + }, + }, } diff --git a/litecord/storage.py b/litecord/storage.py index fe826ad..d3131d6 100644 --- a/litecord/storage.py +++ b/litecord/storage.py @@ -35,7 +35,6 @@ from litecord.blueprints.user.billing import PLAN_ID_TO_TYPE from litecord.types import timestamp_ from litecord.utils import pg_set_json - log = Logger(__name__) @@ -1019,7 +1018,7 @@ class Storage: """ SELECT id::text, channel_id::text, author_id, content, created_at AS timestamp, edited_at AS edited_timestamp, - tts, mention_everyone, nonce, message_type, embeds, flags + tts, mention_everyone, nonce, message_type, embeds, flags, message_reference FROM messages WHERE id = $1 """, diff --git a/litecord/utils.py b/litecord/utils.py index 86be8c2..338a5b6 100644 --- a/litecord/utils.py +++ b/litecord/utils.py @@ -28,6 +28,8 @@ from logbook import Logger from quart.json import JSONEncoder from quart import current_app as app +from litecord.common.messages import message_view + from .errors import BadRequest log = Logger(__name__) @@ -226,7 +228,7 @@ async def search_result_from_list(rows: List) -> Dict[str, Any]: msg = await app.storage.get_message(row["current_id"]) msg["hit"] = True - res.append(before + [msg] + after) + res.append(before + [message_view(msg)] + after) return {"total_results": results, "messages": res, "analytics_id": ""} diff --git a/manage/cmd/migration/scripts/12_inline_replies.sql b/manage/cmd/migration/scripts/12_inline_replies.sql new file mode 100644 index 0000000..5bc1691 --- /dev/null +++ b/manage/cmd/migration/scripts/12_inline_replies.sql @@ -0,0 +1,3 @@ +ALTER TABLE messages + ADD COLUMN message_reference jsonb DEFAULT null, + ADD COLUMN allowed_mentions jsonb DEFAULT null;