From eeeca2579fc5e1bb1fc6d0f55055cff3e69514da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=C3=A1n=20Maureira-Fredes?= Date: Fri, 7 Feb 2025 00:31:12 +0100 Subject: [PATCH 1/6] Add close command for threads/posts The command will close the thread (if on a text channel), and archive the post (if on a forum channel). When in a forum channel, the command will look for a tag from that specific forum called 'done' (each tag will have different IDs depending on the forum) and apply to the post if found. The bot will send a message notifying who closed it. --- intbot/core/bot/main.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/intbot/core/bot/main.py b/intbot/core/bot/main.py index 4cbc55c..478bc93 100644 --- a/intbot/core/bot/main.py +++ b/intbot/core/bot/main.py @@ -38,6 +38,40 @@ async def wiki(ctx): suppress_embeds=True, ) +@bot.command() +async def close(ctx): + channel = ctx.channel + parent = channel.parent + author = ctx.message.author + + # Check if it's a public or private post (thread) + if channel.type in (discord.ChannelType.public_thread, discord.ChannelType.private_thread): + + # Check if the post (thread) was sent in a forum, + # so we can add a tag + if parent.type == discord.ChannelType.forum: + + # Get tag from forum + tag = None + for _tag in parent.available_tags: + if _tag.name.lower() == "done": + tag = _tag + break + + if tag is not None: + await channel.add_tags(tag) + + # Remove command message + await ctx.message.delete() + + # We need to archive after adding tags in case it was a forum. + # Otherwise we only archive the thread + await channel.edit(archived=True) + + # Send notification to the thread + await channel.send(f"# This was marked as done by {author.mention}") + + @bot.command() async def version(ctx): From 7e5c49152626d60fcd79f9ab8e680541d25ab919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=C3=A1n=20Maureira-Fredes?= Date: Fri, 7 Feb 2025 00:45:34 +0100 Subject: [PATCH 2/6] Update intbot/core/bot/main.py --- intbot/core/bot/main.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/intbot/core/bot/main.py b/intbot/core/bot/main.py index 478bc93..fbb5c2b 100644 --- a/intbot/core/bot/main.py +++ b/intbot/core/bot/main.py @@ -64,12 +64,11 @@ async def close(ctx): # Remove command message await ctx.message.delete() - # We need to archive after adding tags in case it was a forum. - # Otherwise we only archive the thread - await channel.edit(archived=True) - # Send notification to the thread await channel.send(f"# This was marked as done by {author.mention}") + + # We need to archive after adding tags in case it was a forum. + await channel.edit(archived=True) From 331f205107a9b2d0267ed0350d93ea25902de94d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=C3=A1n=20Maureira-Fredes?= Date: Sat, 8 Feb 2025 10:51:56 +0100 Subject: [PATCH 3/6] Add Test Cases --- intbot/core/bot/main.py | 2 +- intbot/tests/test_bot/test_main.py | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/intbot/core/bot/main.py b/intbot/core/bot/main.py index fbb5c2b..ae7cce3 100644 --- a/intbot/core/bot/main.py +++ b/intbot/core/bot/main.py @@ -66,7 +66,7 @@ async def close(ctx): # Send notification to the thread await channel.send(f"# This was marked as done by {author.mention}") - + # We need to archive after adding tags in case it was a forum. await channel.edit(archived=True) diff --git a/intbot/tests/test_bot/test_main.py b/intbot/tests/test_bot/test_main.py index 108edeb..3941d4a 100644 --- a/intbot/tests/test_bot/test_main.py +++ b/intbot/tests/test_bot/test_main.py @@ -6,7 +6,7 @@ import pytest from asgiref.sync import sync_to_async -from core.bot.main import ping, poll_database, qlen, source, version, wiki +from core.bot.main import ping, poll_database, qlen, source, version, wiki, close from core.models import DiscordMessage from django.utils import timezone @@ -100,6 +100,24 @@ async def test_wiki_command(): suppress_embeds=True, ) +@pytest.mark.asyncio +async def test_close_command(): + # Mock context + ctx = AsyncMock() + ctx.channel = discord.Thread() + ctx.channel.parent = discord.ForumChannel() + ctx.author = discord.Member() + ctx.author.mention = "TestUser" + + # Call the command + await close(ctx) + + # Assert that the command sent the expected message + ctx.send.assert_called_once_with( + "# This was marked as done by {ctx.author.mention}", + suppress_embeds=True, + ) + @pytest.mark.asyncio async def test_version_command(): From 5da8db82eca956d75c5032b468551f920c39f0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=C3=A1n=20Maureira-Fredes?= Date: Sat, 8 Feb 2025 11:08:39 +0100 Subject: [PATCH 4/6] Add missing import --- intbot/tests/test_bot/test_main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/intbot/tests/test_bot/test_main.py b/intbot/tests/test_bot/test_main.py index 3941d4a..f4ad5fd 100644 --- a/intbot/tests/test_bot/test_main.py +++ b/intbot/tests/test_bot/test_main.py @@ -1,6 +1,7 @@ from unittest import mock from unittest.mock import AsyncMock, patch import contextlib +import discord from django.db import connections From 6e0e8b72c2c54e6351f12c65c0775dbd03bd527e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=C3=A1n=20Maureira-Fredes?= Date: Sat, 8 Feb 2025 12:13:26 +0100 Subject: [PATCH 5/6] Fix test case --- intbot/core/bot/main.py | 2 +- intbot/tests/test_bot/test_main.py | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/intbot/core/bot/main.py b/intbot/core/bot/main.py index ae7cce3..93e7a98 100644 --- a/intbot/core/bot/main.py +++ b/intbot/core/bot/main.py @@ -65,7 +65,7 @@ async def close(ctx): await ctx.message.delete() # Send notification to the thread - await channel.send(f"# This was marked as done by {author.mention}") + await channel.send(f"# This was marked as done by {author.mention}", suppress_embeds=True) # We need to archive after adding tags in case it was a forum. await channel.edit(archived=True) diff --git a/intbot/tests/test_bot/test_main.py b/intbot/tests/test_bot/test_main.py index f4ad5fd..4782313 100644 --- a/intbot/tests/test_bot/test_main.py +++ b/intbot/tests/test_bot/test_main.py @@ -105,17 +105,16 @@ async def test_wiki_command(): async def test_close_command(): # Mock context ctx = AsyncMock() - ctx.channel = discord.Thread() - ctx.channel.parent = discord.ForumChannel() - ctx.author = discord.Member() - ctx.author.mention = "TestUser" + ctx.channel = AsyncMock() + ctx.message.author = AsyncMock() + ctx.channel.type = discord.ChannelType.public_thread # Call the command await close(ctx) # Assert that the command sent the expected message - ctx.send.assert_called_once_with( - "# This was marked as done by {ctx.author.mention}", + ctx.channel.send.assert_called_once_with( + f"# This was marked as done by {ctx.message.author.mention}", suppress_embeds=True, ) From 9628b9f646791da1b7109e01dc5130e87f99863f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=C3=A1n=20Maureira-Fredes?= Date: Sat, 8 Feb 2025 12:30:28 +0100 Subject: [PATCH 6/6] Add test case when the command doesn't work --- intbot/core/bot/main.py | 7 +++++++ intbot/tests/test_bot/test_main.py | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/intbot/core/bot/main.py b/intbot/core/bot/main.py index 93e7a98..4dd0c6f 100644 --- a/intbot/core/bot/main.py +++ b/intbot/core/bot/main.py @@ -69,6 +69,13 @@ async def close(ctx): # We need to archive after adding tags in case it was a forum. await channel.edit(archived=True) + else: + # Remove command message + await ctx.message.delete() + + await channel.send("The !close command is intended to be used inside a thread/post", + suppress_embeds=True, + delete_after=5) diff --git a/intbot/tests/test_bot/test_main.py b/intbot/tests/test_bot/test_main.py index 4782313..393bc37 100644 --- a/intbot/tests/test_bot/test_main.py +++ b/intbot/tests/test_bot/test_main.py @@ -102,7 +102,7 @@ async def test_wiki_command(): ) @pytest.mark.asyncio -async def test_close_command(): +async def test_close_command_working(): # Mock context ctx = AsyncMock() ctx.channel = AsyncMock() @@ -118,6 +118,23 @@ async def test_close_command(): suppress_embeds=True, ) +@pytest.mark.asyncio +async def test_close_command_notworking(): + # Mock context + ctx = AsyncMock() + ctx.channel = AsyncMock() + ctx.message.author = AsyncMock() + + # Call the command + await close(ctx) + + # Assert that the command sent the expected message + ctx.channel.send.assert_called_once_with( + "The !close command is intended to be used inside a thread/post", + suppress_embeds=True, + delete_after=5 + ) + @pytest.mark.asyncio async def test_version_command():