Skip to content
Merged
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
1 change: 1 addition & 0 deletions .test.env
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ ROLE_VIP_PLUS=9583772910112769506

ROLE_CHALLENGE_CREATOR=8215461011276950716
ROLE_BOX_CREATOR=8215471011276950716
ROLE_SHERLOCK_CREATOR=1384037506349011044

ROLE_RANK_ONE=7419955631011276950
ROLE_RANK_TEN=7419955611011276950
Expand Down
3 changes: 3 additions & 0 deletions src/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class Roles(BaseSettings):
# Content Creation
CHALLENGE_CREATOR: int
BOX_CREATOR: int
SHERLOCK_CREATOR: int

# Positions
RANK_ONE: int
Expand Down Expand Up @@ -247,6 +248,7 @@ def get_post_or_rank(self, what: str) -> Optional[int]:
"dedivip": self.roles.VIP_PLUS,
"Challenge Creator": self.roles.CHALLENGE_CREATOR,
"Box Creator": self.roles.BOX_CREATOR,
"Sherlock Creator": self.roles.SHERLOCK_CREATOR,
}.get(what)

def get_season(self, what: str):
Expand Down Expand Up @@ -346,6 +348,7 @@ def load_settings(env_file: str | None = None):
"ALL_CREATORS": [
global_settings.roles.BOX_CREATOR,
global_settings.roles.CHALLENGE_CREATOR,
global_settings.roles.SHERLOCK_CREATOR,
],
"ALL_POSITIONS": [
global_settings.roles.RANK_ONE,
Expand Down
6 changes: 6 additions & 0 deletions src/helpers/verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,12 @@ def _process_creator_roles(htb_user_content: dict, guild: Guild) -> list[Role]:
if challenge_creator_role:
logger.debug("Adding challenge creator role to user.")
roles.append(challenge_creator_role)

if htb_user_content.get("sherlocks"):
sherlock_creator_role = guild.get_role(settings.roles.SHERLOCK_CREATOR)
if sherlock_creator_role:
logger.debug("Adding sherlock creator role to user.")
roles.append(sherlock_creator_role)
except Exception as e:
logger.error(f"Error processing creator roles: {e}")
return roles
Expand Down
46 changes: 14 additions & 32 deletions src/webhooks/handlers/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,8 @@ async def _handle_account_linked(self, body: WebhookBody, bot: Bot) -> dict:
"""
Handles the account linked event.
"""
discord_id = self.validate_discord_id(
self.get_property_or_trait(body, "discord_id")
)
account_id = self.validate_account_id(
self.get_property_or_trait(body, "account_id")
)
discord_id = self.validate_discord_id(self.get_property_or_trait(body, "discord_id"))
account_id = self.validate_account_id(self.get_property_or_trait(body, "account_id"))

member = await self.get_guild_member(discord_id, bot)
await process_account_identification(
Expand All @@ -53,9 +49,7 @@ async def _handle_account_linked(self, body: WebhookBody, bot: Bot) -> dict:
f"Account linked: {account_id} -> ({member.mention} ({member.id})",
)
else:
self.logger.warning(
f"Verify logs channel {settings.channels.VERIFY_LOGS} not found"
)
self.logger.warning(f"Verify logs channel {settings.channels.VERIFY_LOGS} not found")
except Exception as e:
self.logger.error(f"Failed to send verification log: {e}")
# Don't raise - this is not critical
Expand All @@ -71,17 +65,14 @@ async def _handle_account_unlinked(self, body: WebhookBody, bot: Bot) -> dict:
"""
Handles the account unlinked event.
"""
discord_id = self.validate_discord_id(
self.get_property_or_trait(body, "discord_id")
)
account_id = self.validate_account_id(
self.get_property_or_trait(body, "account_id")
)
discord_id = self.validate_discord_id(self.get_property_or_trait(body, "discord_id"))
account_id = self.validate_account_id(self.get_property_or_trait(body, "account_id"))

member = await self.get_guild_member(discord_id, bot)

await member.remove_roles(
bot.guilds[0].get_role(settings.roles.VERIFIED), atomic=True # type: ignore
bot.guilds[0].get_role(settings.roles.VERIFIED),
atomic=True, # type: ignore
) # type: ignore

return self.success()
Expand All @@ -102,15 +93,9 @@ async def _handle_account_banned(self, body: WebhookBody, bot: Bot) -> dict:
"""
Handles the account banned event.
"""
discord_id = self.validate_discord_id(
self.get_property_or_trait(body, "discord_id")
)
account_id = self.validate_account_id(
self.get_property_or_trait(body, "account_id")
)
expires_at = self.validate_property(
self.get_property_or_trait(body, "expires_at"), "expires_at"
)
discord_id = self.validate_discord_id(self.get_property_or_trait(body, "discord_id"))
account_id = self.validate_account_id(self.get_property_or_trait(body, "account_id"))
expires_at = self.validate_property(self.get_property_or_trait(body, "expires_at"), "expires_at")
reason = body.properties.get("reason")
notes = body.properties.get("notes")
created_by = body.properties.get("created_by")
Expand All @@ -120,9 +105,7 @@ async def _handle_account_banned(self, body: WebhookBody, bot: Bot) -> dict:

member = await self.get_guild_member(discord_id, bot)
if not member:
self.logger.warning(
f"Cannot ban user {discord_id}- not found in guild", extra=extra
)
self.logger.warning(f"Cannot ban user {discord_id}- not found in guild", extra=extra)
return self.fail()

# Use the generic ban helper to handle all the complex logic
Expand All @@ -140,9 +123,7 @@ async def _handle_account_banned(self, body: WebhookBody, bot: Bot) -> dict:
extra_log_data=extra,
)

self.logger.debug(
f"Platform ban handling result: {result['action']}", extra=extra
)
self.logger.debug(f"Platform ban handling result: {result['action']}", extra=extra)

return self.success()

Expand All @@ -162,7 +143,8 @@ async def _handle_account_deleted(self, body: WebhookBody, bot: Bot) -> dict:
return self.fail()

await member.remove_roles(
bot.guilds[0].get_role(settings.roles.VERIFIED), atomic=True # type: ignore
bot.guilds[0].get_role(settings.roles.VERIFIED),
atomic=True, # type: ignore
) # type: ignore

return self.success()
40 changes: 40 additions & 0 deletions tests/src/core/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import unittest

from src.core import settings


class TestConfig(unittest.TestCase):
def test_sherlock_creator_role_in_all_creators(self):
"""Test that SHERLOCK_CREATOR role is included in ALL_CREATORS group."""
all_creators = settings.role_groups.get("ALL_CREATORS", [])
self.assertIn(settings.roles.SHERLOCK_CREATOR, all_creators)
self.assertIn(settings.roles.CHALLENGE_CREATOR, all_creators)
self.assertIn(settings.roles.BOX_CREATOR, all_creators)

def test_get_post_or_rank_sherlock_creator(self):
"""Test that get_post_or_rank returns correct role for Sherlock Creator."""
result = settings.get_post_or_rank("Sherlock Creator")
self.assertEqual(result, settings.roles.SHERLOCK_CREATOR)

def test_get_post_or_rank_other_creators(self):
"""Test that get_post_or_rank works for all creator types."""
test_cases = [
("Challenge Creator", settings.roles.CHALLENGE_CREATOR),
("Box Creator", settings.roles.BOX_CREATOR),
("Sherlock Creator", settings.roles.SHERLOCK_CREATOR),
]

for role_name, expected_role in test_cases:
with self.subTest(role_name=role_name):
result = settings.get_post_or_rank(role_name)
self.assertEqual(result, expected_role)

def test_get_post_or_rank_invalid_role(self):
"""Test that get_post_or_rank returns None for invalid role."""
result = settings.get_post_or_rank("Invalid Role")
self.assertIsNone(result)

def test_sherlock_creator_role_configured(self):
"""Test that SHERLOCK_CREATOR role is properly configured."""
self.assertIsNotNone(settings.roles.SHERLOCK_CREATOR)
self.assertIsInstance(settings.roles.SHERLOCK_CREATOR, int)
Loading