Files
GuardDen/tests/test_automod.py
latte 4e16777f25 Implement GuardDen Discord moderation bot
Features:
- Core moderation: warn, kick, ban, timeout, strike system
- Automod: banned words filter, scam detection, anti-spam, link filtering
- AI moderation: Claude/OpenAI integration, NSFW detection, phishing analysis
- Verification system: button, captcha, math, emoji challenges
- Rate limiting system with configurable scopes
- Event logging: joins, leaves, message edits/deletes, voice activity
- Per-guild configuration with caching
- Docker deployment support

Bug fixes applied:
- Fixed await on session.delete() in guild_config.py
- Fixed memory leak in AI moderation message tracking (use deque)
- Added error handling to bot shutdown
- Added error handling to timeout command
- Removed unused Literal import
- Added prefix validation
- Added image analysis limit (3 per message)
- Fixed test mock for SQLAlchemy model
2026-01-16 19:27:48 +01:00

154 lines
5.5 KiB
Python

"""Tests for the automod service."""
import pytest
from guardden.models import BannedWord
from guardden.services.automod import AutomodService
@pytest.fixture
def automod() -> AutomodService:
"""Create an automod service instance."""
return AutomodService()
class TestBannedWords:
"""Tests for banned word filtering."""
def test_simple_match(self, automod: AutomodService) -> None:
"""Test simple text matching."""
banned = [_make_banned_word("badword")]
result = automod.check_banned_words("This contains badword in it", banned)
assert result is not None
assert result.should_delete
def test_case_insensitive(self, automod: AutomodService) -> None:
"""Test case insensitive matching."""
banned = [_make_banned_word("BadWord")]
result = automod.check_banned_words("this contains BADWORD here", banned)
assert result is not None
def test_no_match(self, automod: AutomodService) -> None:
"""Test no match returns None."""
banned = [_make_banned_word("badword")]
result = automod.check_banned_words("This is a clean message", banned)
assert result is None
def test_regex_pattern(self, automod: AutomodService) -> None:
"""Test regex pattern matching."""
banned = [_make_banned_word(r"bad\w+", is_regex=True)]
result = automod.check_banned_words("This is badword and badstuff", banned)
assert result is not None
def test_action_warn(self, automod: AutomodService) -> None:
"""Test warn action is set."""
banned = [_make_banned_word("badword", action="warn")]
result = automod.check_banned_words("badword", banned)
assert result is not None
assert result.should_warn
def test_action_strike(self, automod: AutomodService) -> None:
"""Test strike action is set."""
banned = [_make_banned_word("badword", action="strike")]
result = automod.check_banned_words("badword", banned)
assert result is not None
assert result.should_strike
class TestScamDetection:
"""Tests for scam/phishing detection."""
def test_discord_nitro_scam(self, automod: AutomodService) -> None:
"""Test detection of fake Discord Nitro links."""
result = automod.check_scam_links("Free nitro at discord-nitro.gift")
assert result is not None
assert result.should_delete
def test_steam_scam(self, automod: AutomodService) -> None:
"""Test detection of Steam scam patterns."""
result = automod.check_scam_links("Check out this steam-community-giveaway.xyz")
assert result is not None
def test_legitimate_discord_link(self, automod: AutomodService) -> None:
"""Test that legitimate Discord links pass."""
result = automod.check_scam_links("Join us at discord.gg/example")
assert result is None
def test_suspicious_tld_with_keyword(self, automod: AutomodService) -> None:
"""Test suspicious TLD with impersonation keyword."""
result = automod.check_scam_links("Visit discord-verify.xyz to claim")
assert result is not None
def test_normal_url(self, automod: AutomodService) -> None:
"""Test normal URLs pass."""
result = automod.check_scam_links("Check out https://github.com/example")
assert result is None
class TestInviteLinks:
"""Tests for Discord invite link detection."""
def test_discord_gg_invite(self, automod: AutomodService) -> None:
"""Test discord.gg invite detection."""
result = automod.check_invite_links("Join discord.gg/example", allow_invites=False)
assert result is not None
assert result.should_delete
def test_discordapp_invite(self, automod: AutomodService) -> None:
"""Test discordapp.com invite detection."""
result = automod.check_invite_links(
"Join https://discordapp.com/invite/abc123", allow_invites=False
)
assert result is not None
def test_allowed_invites(self, automod: AutomodService) -> None:
"""Test invites pass when allowed."""
result = automod.check_invite_links("Join discord.gg/example", allow_invites=True)
assert result is None
class TestCapsDetection:
"""Tests for excessive caps detection."""
def test_excessive_caps(self, automod: AutomodService) -> None:
"""Test detection of all caps message."""
result = automod.check_all_caps("THIS IS ALL CAPS MESSAGE HERE")
assert result is not None
def test_normal_caps(self, automod: AutomodService) -> None:
"""Test normal message passes."""
result = automod.check_all_caps("This is a Normal Message with Some Caps")
assert result is None
def test_short_message_ignored(self, automod: AutomodService) -> None:
"""Test short messages are ignored."""
result = automod.check_all_caps("HI THERE")
assert result is None
class MockBannedWord:
"""Mock BannedWord for testing without database."""
def __init__(
self,
pattern: str,
is_regex: bool = False,
action: str = "delete",
) -> None:
self.id = 1
self.guild_id = 123
self.pattern = pattern
self.is_regex = is_regex
self.action = action
self.reason = None
self.added_by = 456
def _make_banned_word(
pattern: str,
is_regex: bool = False,
action: str = "delete",
) -> MockBannedWord:
"""Create a mock BannedWord object for testing."""
return MockBannedWord(pattern, is_regex, action)