Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/cmds/automation/auto_verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def __init__(self, bot: Bot):

async def process_reverification(self, member: Member | User) -> None:
"""Re-verifation process for a member.

TODO: Reimplement once it's possible to fetch link state from the HTB Account.
"""
raise VerificationError("Not implemented")
Expand All @@ -28,11 +28,18 @@ async def on_message(self, ctx: Message) -> None:
# Return if the message was sent by the bot to avoid recursion.
if ctx.author.bot:
return

# When a user types in un-verified-bot-commands, hold their hand in finding the how-to-talk channel so they can verify.
if ctx.channel.id == 1430556712313688225:
await ctx.reply(
"Hello! Welcome to the Hack The Box Discord! In order to access the full server, please verify your account by following the instructions in <#1432333413980835840>.",
mention_author=True,
)
try:
await self.process_reverification(ctx.author)
except VerificationError as exc:
logger.debug(f"HTB Discord link for user {ctx.author.name} with ID {ctx.author.id} not found", exc_info=exc)
logger.debug(
f"HTB Discord link for user {ctx.author.name} with ID {ctx.author.id} not found", exc_info=exc
)

@commands.Cog.listener()
@commands.cooldown(1, 3600, commands.BucketType.user)
Expand Down
Empty file.
61 changes: 61 additions & 0 deletions tests/src/cmds/automation/test_auto_verify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from unittest import mock

import pytest

from src.cmds.automation import auto_verify
from tests import helpers


class TestMessageHandler:
"""Test the `MessageHandler` cog."""

@pytest.mark.asyncio
async def test_on_message_in_unverified_channel_sends_welcome(self, bot):
"""Test that a welcome message is sent when user posts in unverified channel."""
cog = auto_verify.MessageHandler(bot)

# Create a mock message in the specific unverified channel
channel = helpers.MockTextChannel(id=1430556712313688225)
author = helpers.MockMember(bot=False)
message = helpers.MockMessage(channel=channel, author=author)
message.reply = mock.AsyncMock()

await cog.on_message(message)

# Verify reply was called with welcome message
message.reply.assert_called_once()
call_args = message.reply.call_args
assert "Welcome to the Hack The Box Discord" in call_args[0][0]
assert call_args[1]["mention_author"] is True

@pytest.mark.asyncio
async def test_on_message_in_other_channel_no_welcome(self, bot):
"""Test that no welcome is sent in other channels."""
cog = auto_verify.MessageHandler(bot)

# Create a mock message in a different channel
channel = helpers.MockTextChannel(id=999999999999999999)
author = helpers.MockMember(bot=False)
message = helpers.MockMessage(channel=channel, author=author)
message.reply = mock.AsyncMock()

await cog.on_message(message)

# Verify reply was NOT called
message.reply.assert_not_called()

@pytest.mark.asyncio
async def test_on_message_from_bot_returns_early(self, bot):
"""Test that bot messages are ignored."""
cog = auto_verify.MessageHandler(bot)

# Create a message from a bot in the unverified channel
channel = helpers.MockTextChannel(id=1430556712313688225)
author = helpers.MockMember(bot=True)
message = helpers.MockMessage(channel=channel, author=author)
message.reply = mock.AsyncMock()

await cog.on_message(message)

# Reply should not be called for bot messages
message.reply.assert_not_called()
24 changes: 11 additions & 13 deletions tests/src/helpers/test_ban.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@

import pytest
from discord import Forbidden, HTTPException
from datetime import datetime, timezone

from src.helpers.ban import _check_member, _dm_banned_member, ban_member
from src.helpers.responses import SimpleResponse
from tests import helpers


class TestBanHelpers:

@pytest.mark.asyncio
async def test__check_member_staff_member(self, bot, guild, member):
author = helpers.MockMember(name="Author User")
member_is_staff = mock.Mock(return_value=True)
with mock.patch('src.helpers.ban.member_is_staff', member_is_staff):
with mock.patch("src.helpers.ban.member_is_staff", member_is_staff):
response = await _check_member(bot, guild, member, author)
assert isinstance(response, SimpleResponse)
assert response.message == "You cannot ban another staff member."
Expand All @@ -27,7 +25,7 @@ async def test__check_member_staff_member(self, bot, guild, member):
async def test__check_member_regular_member(self, bot, guild, member):
author = helpers.MockMember(name="Author User")
member_is_staff = mock.Mock(return_value=False)
with mock.patch('src.helpers.ban.member_is_staff', member_is_staff):
with mock.patch("src.helpers.ban.member_is_staff", member_is_staff):
response = await _check_member(bot, guild, member, author)
assert response is None

Expand All @@ -37,7 +35,7 @@ async def test__check_member_user(self, bot, guild, user):
bot.get_member_or_user = AsyncMock()
bot.get_member_or_user.return_value = user
response = await _check_member(bot, guild, user, author)
assert await bot.get_member_or_user.called_once_with(guild, user.id)
bot.get_member_or_user.assert_called_once_with(guild, user.id)
assert response is None

@pytest.mark.asyncio
Expand Down Expand Up @@ -110,7 +108,6 @@ def __init__(self, status, reason):


class TestBanMember:

@pytest.mark.asyncio
async def test_ban_member_valid_duration(self, bot, guild, member, author):
duration = "1d"
Expand All @@ -134,8 +131,9 @@ async def test_ban_member_valid_duration(self, bot, guild, member, author):

result = await ban_member(bot, guild, member, duration, reason, evidence)
assert isinstance(result, SimpleResponse)
assert result.message == f"{member.display_name} ({member.id}) has been banned until {expected_date} " \
f"(UTC)."
assert (
result.message == f"{member.display_name} ({member.id}) has been banned until {expected_date} (UTC)."
)

@pytest.mark.asyncio
async def test_ban_member_invalid_duration(self, bot, guild, member, author):
Expand Down Expand Up @@ -196,7 +194,7 @@ async def test_ban_member_no_reason_success(self, bot, guild, member, author):

@pytest.mark.asyncio
async def test_ban_member_no_author_success(self, bot, guild, member):
duration = '500w'
duration = "500w"
reason = ""
evidence = "Some evidence"
member.display_name = "Banned Member"
Expand All @@ -216,7 +214,7 @@ async def test_ban_member_no_author_success(self, bot, guild, member):

@pytest.mark.asyncio
async def test_ban_already_exists(self, bot, guild, member, author):
duration = '500w'
duration = "500w"
reason = ""
evidence = "Some evidence"
member.display_name = "Banned Member"
Expand All @@ -238,7 +236,7 @@ async def test_ban_already_exists(self, bot, guild, member, author):
async def test_ban_member_staff(self, ctx, bot, guild):
ctx.user = helpers.MockMember(id=1, name="Test User")
user = helpers.MockMember(id=2, name="Banned User")
with patch('src.helpers.ban.member_is_staff', return_value=True):
with patch("src.helpers.ban.member_is_staff", return_value=True):
response = await ban_member(
bot, guild, user, "1d", "spamming", "some evidence", author=ctx.user, needs_approval=True
)
Expand All @@ -250,7 +248,7 @@ async def test_ban_member_staff(self, ctx, bot, guild):
async def test_ban_member_bot(self, ctx, bot, guild):
ctx.user = helpers.MockMember(id=1, name="Test User")
member = helpers.MockMember(id=2, name="Bot Member", bot=True)
with patch('src.helpers.ban.member_is_staff', return_value=False):
with patch("src.helpers.ban.member_is_staff", return_value=False):
response = await ban_member(
bot, guild, member, "1d", "spamming", "some evidence", author=ctx.user, needs_approval=True
)
Expand All @@ -261,7 +259,7 @@ async def test_ban_member_bot(self, ctx, bot, guild):
@pytest.mark.asyncio
async def test_ban_self(self, ctx, bot, guild):
ctx.user = helpers.MockMember(id=1, name="Test User")
with patch('src.helpers.ban.member_is_staff', return_value=False):
with patch("src.helpers.ban.member_is_staff", return_value=False):
response = await ban_member(
bot, guild, ctx.user, "1d", "spamming", "some evidence", author=ctx.user, needs_approval=True
)
Expand Down