From 0f7618875cdb17e2ada6080ee12508f4d95fbd46 Mon Sep 17 00:00:00 2001 From: "Nyeki.py" <84998222+Nekidev@users.noreply.github.com> Date: Sun, 20 Oct 2024 23:00:58 -0300 Subject: [PATCH] feat(bot): :bug: Delete message replies on original message delete. --- payphone/cogs/calls/cog.py | 120 ++++++++++++++++++++++++++++++++----- payphone/core/constants.py | 31 ++++++++-- 2 files changed, 131 insertions(+), 20 deletions(-) diff --git a/payphone/cogs/calls/cog.py b/payphone/cogs/calls/cog.py index 4639462..4f01f43 100644 --- a/payphone/cogs/calls/cog.py +++ b/payphone/cogs/calls/cog.py @@ -133,6 +133,7 @@ class Calls(base.Cog): constants.CALL_MESSAGE_CONTENTS_TEMPLATE % call_id, constants.CALL_MESSAGE_FROM_PROPAGATION_TEMPLATE % call_id, constants.CALL_MESSAGES_TEMPLATE % call_id, + constants.CALL_MESSAGE_REPLIES_TEMPLATE % call_id, ) await pipe.execute() @@ -870,6 +871,25 @@ class Calls(base.Cog): message.id, ) + if replying_to_id is not None: + other_replies = await redis.hget( + constants.CALL_MESSAGE_REPLIES_TEMPLATE % call.id, replying_to_id + ) + + if other_replies is None: + pipe.hset( + constants.CALL_MESSAGE_REPLIES_TEMPLATE % call.id, + replying_to_id, + message.id, + ) + + else: + pipe.hset( + constants.CALL_MESSAGE_REPLIES_TEMPLATE % call.id, + replying_to_id, + other_replies.decode() + f",{message.id}", + ) + await pipe.execute() @commands.Cog.listener() @@ -899,7 +919,17 @@ class Calls(base.Cog): if message_json is None: return - message = models.Message(**orjson.loads(message_json)) + message_dict = orjson.loads(message_json) + + message = models.Message(**message_dict) + + message_dict["was_deleted"] = True + + await redis.hset( + constants.CALL_MESSAGES_TEMPLATE % channel.call_id, + message.id, + orjson.dumps(message_dict), + ) other_channel = await models.Channel.get(id=message.propagation_channel_id) @@ -916,6 +946,21 @@ class Calls(base.Cog): # This message was already deleted. pass + message_replies = await redis.hget( + constants.CALL_MESSAGE_REPLIES_TEMPLATE % channel.call_id, + message.id + ) + + if message_replies is None: + return + + for message_id in message_replies.split(","): + try: + await webhook.edit_message(message_id, embed=None) + + except errors.DiscordException: + pass + @commands.Cog.listener() @commands.guild_only() @transactions.atomic() @@ -939,33 +984,80 @@ class Calls(base.Cog): channel_id = payload.channel_id content = payload.data["content"] - if censorship.moderate(content) is not None: + channel = await models.Channel.get(id=channel_id) + + if channel.call_id is None: return - is_on_call = await redis.sismember( - constants.CHANNELS_ONCALL_SET, str(channel_id) + message_json = await redis.hget( + constants.CALL_MESSAGES_TEMPLATE % channel.call_id, message_id ) - if not is_on_call: + if message_json is None: return - message = await models.Message.get_or_none(id=message_id).select_related( - "propagation_channel" - ) + message = models.Message(**orjson.loads(message_json)) - if message is None: - return - - other_channel = message.propagation_channel + other_channel = await models.Channel.get(id=message.propagation_channel_id) if other_channel.call_id != message.call_id: return + original_message = await self.bot.get_partial_messageable( + channel_id + ).fetch_message(message.id) + + if original_message is None: + return + + call_rss = await models.CallUserChannelRelationship.filter( + call_id=channel.call_id + ) + + cleaned_content = formatting.clean(original_message, call_rss) + + blocked_word = censorship.moderate(content) + + iteration = int( + await redis.hget( + constants.CALL_MESSAGE_CONTENT_ITERATIONS_TEMPLATE % channel.call_id, + message.id, + ) + ) + + pipe = redis.pipeline() + + pipe.hincrby( + constants.CALL_MESSAGE_CONTENT_ITERATIONS_TEMPLATE % channel.call_id, + message.id, + ) + pipe.hset( + constants.CALL_MESSAGE_CONTENTS_TEMPLATE % channel.call_id, + constants.CALL_MESSAGE_CONTENTS_HASH_TEMPLATE % (message.id, iteration + 1), + orjson.dumps( + { + "message_id": message.id, + "content": cleaned_content, + "was_propagated": not bool(blocked_word), + "created_at": datetime.now(timezone.utc), + } + ), + ) + + await pipe.execute() + async with aiohttp.ClientSession() as session: webhook = other_channel.webhook(session) try: - await webhook.edit_message(message.propagation_id, content=content) + await webhook.edit_message( + message.propagation_id, + content=( + cleaned_content + if blocked_word is None + else "*This message was edited and censored.*" + ), + ) except errors.DiscordException: # This message was deleted. @@ -973,8 +1065,6 @@ class Calls(base.Cog): # TODO: Edit replies. - await models.MessageContent.create(message=message, content=content) - def setup(b: bot.Payphone) -> None: """Load the cog into the bot. diff --git a/payphone/core/constants.py b/payphone/core/constants.py index 90b24cb..c216068 100644 --- a/payphone/core/constants.py +++ b/payphone/core/constants.py @@ -175,19 +175,40 @@ MESSAGE_CONTENTS_QUEUE = "message-contents" MESSAGES_PROPAGATION_MAP = "messages-propagation" CALL_MESSAGES_TEMPLATE = "m:%s" -"""`%s`: Call ID. The key template for call messages hash.""" +"""`%s`: Call ID. + +The key template for call messages hash. +""" CALL_MESSAGE_CONTENTS_TEMPLATE = "mc:%s" -"""`%s`: Call ID. The key template for call message contents hash.""" +"""`%s`: Call ID. + +The key template for call message contents hash. +""" CALL_MESSAGE_CONTENTS_HASH_TEMPLATE = "%s-%s" -"""`%s-%s`: Call ID - Iteration. The key template for call message contents hash keys.""" +"""`%s-%s`: Call ID - Iteration. + +The key template for call message contents hash keys. +""" CALL_MESSAGE_FROM_PROPAGATION_TEMPLATE = "mfp:%s" -"""`%s`: Call ID. A map from propagation IDs to message IDs.""" +"""`%s`: Call ID. + +A map from propagation IDs to message IDs. +""" CALL_MESSAGE_CONTENT_ITERATIONS_TEMPLATE = "mci:%s" -"""`%s`: Call ID. A map of messages to amount of iterations of their message contents.""" +"""`%s`: Call ID. + +A map of messages to amount of iterations of their message contents. +""" + +CALL_MESSAGE_REPLIES_TEMPLATE = "mr:%s" +"""`%s`: Call ID. + +A map of message IDs to a `,`-delimited list of message IDs that reply to the message. +""" CALL_IDS_TO_FLUSH = "call-ids-to-flush" """A set of IDs of calls to flush to the DB."""