Skip to content

Commit

Permalink
Refactor code in 'showcas_pre' extension
Browse files Browse the repository at this point in the history
  • Loading branch information
Mega-JC committed Jun 27, 2024
1 parent 1ead906 commit 7a571e4
Showing 1 changed file with 51 additions and 92 deletions.
143 changes: 51 additions & 92 deletions pcbot/exts/showcase_pre.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,30 +27,27 @@ def __init__(
self.entry_post_deletion_dict: dict[int, tuple[asyncio.Task[None], int]] = {}

@staticmethod
async def delete_bad_entry_and_warning(
entry_msg: discord.Message, warn_msg: discord.Message, delay: float = 0.0
):
"""A function to pardon a bad entry post with a grace period. If this coroutine is not cancelled during the
grace period specified in `delay` in seconds, it will delete both `entry_msg` and `warn_msg`, if possible.
async def delete_bad_thread(thread: discord.Thread, delay: float = 0.0):
"""A function to pardon a bad thread with a grace period. If this coroutine is not cancelled during the
grace period specified in `delay` in seconds, it will delete `thread`, if possible.
"""
try:
await asyncio.sleep(delay) # allow cancelling during delay
except asyncio.CancelledError:
return

else:
for msg in (entry_msg, warn_msg):
# don't error here if messages were already deleted
try:
await msg.delete()
except discord.NotFound:
pass
try:
await thread.delete()
except discord.NotFound:
# don't error here if post was already deleted
pass

@staticmethod
def entry_message_validity_check(
def starter_message_validity_check(
message: discord.Message, min_chars=32, max_chars=float("inf")
):
"""Checks if a post's starter message posted in a showcase channel has the right format.
"""Checks if a thread's starter message has the right format.
Returns
-------
Expand Down Expand Up @@ -87,76 +84,22 @@ async def on_thread_create(self, thread: discord.Thread):
else:
await message.pin()

if not self.entry_message_validity_check(message):
if not self.starter_message_validity_check(message):
deletion_datetime = datetime.datetime.now(
datetime.timezone.utc
) + datetime.timedelta(minutes=2)
) + datetime.timedelta(minutes=5)
warn_msg = await message.reply(
"Your post must contain an attachment or text and safe links to be valid.\n\n"
"- Attachment-only entries must be replies to a previous entry of yours.\n"
"- Text-only entries must contain at least 32 characters (including links, but not links alone).\n\n"
"- Attachment-only entries must be in reference to a previous post of yours.\n"
"- Text-only posts must contain at least 32 characters (including links, but not links alone).\n\n"
" If no changes are made, your post will be"
f" deleted {snakecore.utils.create_markdown_timestamp(deletion_datetime, 'R')}."
)
self.entry_post_deletion_dict[thread.id] = (
asyncio.create_task(
self.delete_bad_entry_and_warning(message, warn_msg, delay=120)
),
asyncio.create_task(self.delete_bad_thread(thread, delay=300)),
warn_msg.id,
)

async def on_thread_delete(self, thread: discord.Thread):
if thread.parent_id != self.showcase_channel_id:
return

if not any(tag.name.lower() == "invalid" for tag in thread.applied_tags):
alert_msg = await thread.send(
embed=discord.Embed.from_dict(
dict(
title="Post scheduled for deletion",
description=(
"This post is scheduled for deletion after the OP "
"deleted their starter message.\n\nIt will be deleted "
f"**<t:{int(time.time()+300)}:R>**." # 5 min. delay
),
color=0x551111,
footer=dict(text="React with ❌ to cancel the deletion."),
)
)
)
await alert_msg.add_reaction("❌")

try:
await self.bot.wait_for(
"raw_reaction_add",
check=lambda event: event.message_id == alert_msg.id
and (
event.user_id == thread.owner_id
or (
event.member
and not event.member.bot
and (
(
perms := thread.permissions_for(event.member)
).administrator
or perms.manage_messages
)
)
)
and snakecore.utils.is_emoji_equal(event.emoji, "❌"),
timeout=300,
)
except asyncio.TimeoutError:
try:
await thread.delete()
except discord.NotFound:
pass
else:
try:
await alert_msg.delete()
except discord.NotFound:
pass

@commands.Cog.listener()
async def on_message_edit(self, old: discord.Message, new: discord.Message):
if not (
Expand All @@ -167,7 +110,7 @@ async def on_message_edit(self, old: discord.Message, new: discord.Message):

thread = new.channel

if not self.entry_message_validity_check(new):
if not self.starter_message_validity_check(new):
if thread.id in self.entry_post_deletion_dict:
deletion_data_tuple = self.entry_post_deletion_dict[thread.id]
deletion_task = deletion_data_tuple[0]
Expand All @@ -179,21 +122,23 @@ async def on_message_edit(self, old: discord.Message, new: discord.Message):
warn_msg = await thread.fetch_message(deletion_data_tuple[1])
deletion_datetime = datetime.datetime.now(
datetime.timezone.utc
) + datetime.timedelta(minutes=2)
) + datetime.timedelta(minutes=5)
await warn_msg.edit(
content=(
"I noticed your edit, but: Your post must contain an attachment or a (Discord recognized) link to be valid."
" If it doesn't contain any characters but an attachment, it must be a reply to another entry you created."
f" If no attachments are present, it must contain at least 32 characters (including any links, but not links alone)."
"I noticed your edit. However:\n\n"
"Your post must contain an attachment or text and safe "
"links to be valid.\n\n"
"- Attachment-only entries must be in reference to a "
"previous post of yours.\n"
"- Text-only posts must contain at least 32 "
"characters (including links, but not links alone).\n\n"
" If no changes are made, your post will be"
f" deleted {snakecore.utils.create_markdown_timestamp(deletion_datetime, 'R')}."
)
)
self.entry_post_deletion_dict[thread.id] = (
asyncio.create_task(
self.delete_bad_entry_and_warning(
new, warn_msg, delay=120
)
self.delete_bad_thread(thread, delay=300)
),
warn_msg.id,
)
Expand All @@ -206,48 +151,47 @@ async def on_message_edit(self, old: discord.Message, new: discord.Message):
else: # an edit led to an invalid post from a valid one
deletion_datetime = datetime.datetime.now(
datetime.timezone.utc
) + datetime.timedelta(minutes=2)
) + datetime.timedelta(minutes=5)
warn_msg = await new.reply(
"Your post must contain an attachment or text and a (Discord recognized) link to be valid."
" If it doesn't contain any characters but an attachment, it must be a reply to another entry you created."
f" If no attachments are present, it must contain at least 32 characters (including any links, but not links alone)."
"Your post must contain an attachment or text and safe links to be valid.\n\n"
"- Attachment-only entries must be in reference to a previous post of yours.\n"
"- Text-only posts must contain at least 32 characters (including links, but not links alone).\n\n"
" If no changes are made, your post will be"
f" deleted {snakecore.utils.create_markdown_timestamp(deletion_datetime, 'R')}."
)

self.entry_post_deletion_dict[thread.id] = (
asyncio.create_task(
self.delete_bad_entry_and_warning(new, warn_msg, delay=120)
),
asyncio.create_task(self.delete_bad_thread(thread, delay=300)),
warn_msg.id,
)
return

elif (
self.entry_message_validity_check(new)
self.starter_message_validity_check(new)
and thread.id in self.entry_post_deletion_dict
): # an invalid entry was corrected
deletion_data_tuple = self.entry_post_deletion_dict[thread.id]
deletion_task = deletion_data_tuple[0]
if not deletion_task.done(): # too late to do anything
try:
deletion_task.cancel() # try to cancel deletion after noticing valid edit by sender
warn_msg = await thread.fetch_message(deletion_data_tuple[1])
await warn_msg.delete()
await discord.PartialMessage(
channel=thread, id=deletion_data_tuple[1]
).delete()
except (
discord.NotFound
): # cancelling didn't work, warning and post were already deleted
): # cancelling didn't work, warning was already deleted
pass

if thread.id in self.entry_post_deletion_dict:
del self.entry_post_deletion_dict[thread.id]

@commands.Cog.listener()
async def on_message_delete(self, message: discord.Message):

if not (
isinstance(message.channel, discord.Thread)
and message.channel.parent_id == self.showcase_channel_id
and message.channel.id == message.id # is starter message
):
return

Expand All @@ -271,6 +215,21 @@ async def on_message_delete(self, message: discord.Message):
if thread.id in self.entry_post_deletion_dict:
del self.entry_post_deletion_dict[thread.id]

@commands.Cog.listener()
async def on_raw_thread_delete(self, payload: discord.RawThreadDeleteEvent):
if (
payload.parent_id != self.showcase_channel_id
or payload.thread_id not in self.entry_post_deletion_dict
):
return

deletion_data_tuple = self.entry_post_deletion_dict[payload.thread_id]
deletion_task = deletion_data_tuple[0]
if not deletion_task.done():
deletion_task.cancel()

del self.entry_post_deletion_dict[payload.thread_id]


@snakecore.commands.decorators.with_config_kwargs
async def setup(
Expand Down

0 comments on commit 7a571e4

Please sign in to comment.