aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/exts/events/code_jams/_channels.py113
-rw-r--r--bot/exts/events/code_jams/_cog.py113
-rw-r--r--bot/exts/filters/antimalware.py2
-rw-r--r--bot/exts/filters/antispam.py2
-rw-r--r--bot/exts/filters/filtering.py2
-rw-r--r--tests/bot/exts/events/test_code_jams.py64
6 files changed, 150 insertions, 146 deletions
diff --git a/bot/exts/events/code_jams/_channels.py b/bot/exts/events/code_jams/_channels.py
new file mode 100644
index 000000000..8b199a3c2
--- /dev/null
+++ b/bot/exts/events/code_jams/_channels.py
@@ -0,0 +1,113 @@
+import logging
+import typing as t
+
+import discord
+
+from bot.constants import Categories, Channels, Roles
+
+log = logging.getLogger(__name__)
+
+MAX_CHANNELS = 50
+CATEGORY_NAME = "Code Jam"
+
+
+async def _get_category(guild: discord.Guild) -> discord.CategoryChannel:
+ """
+ Return a code jam category.
+
+ If all categories are full or none exist, create a new category.
+ """
+ for category in guild.categories:
+ if category.name == CATEGORY_NAME and len(category.channels) < MAX_CHANNELS:
+ return category
+
+ return await _create_category(guild)
+
+
+async def _create_category(guild: discord.Guild) -> discord.CategoryChannel:
+ """Create a new code jam category and return it."""
+ log.info("Creating a new code jam category.")
+
+ category_overwrites = {
+ guild.default_role: discord.PermissionOverwrite(read_messages=False),
+ guild.me: discord.PermissionOverwrite(read_messages=True)
+ }
+
+ category = await guild.create_category_channel(
+ CATEGORY_NAME,
+ overwrites=category_overwrites,
+ reason="It's code jam time!"
+ )
+
+ await _send_status_update(
+ guild, f"Created a new category with the ID {category.id} for this Code Jam's team channels."
+ )
+
+ return category
+
+
+def _get_overwrites(
+ members: list[tuple[discord.Member, bool]],
+ guild: discord.Guild,
+) -> dict[t.Union[discord.Member, discord.Role], discord.PermissionOverwrite]:
+ """Get code jam team channels permission overwrites."""
+ team_channel_overwrites = {
+ guild.default_role: discord.PermissionOverwrite(read_messages=False),
+ guild.get_role(Roles.code_jam_event_team): discord.PermissionOverwrite(read_messages=True)
+ }
+
+ for member, _ in members:
+ team_channel_overwrites[member] = discord.PermissionOverwrite(
+ read_messages=True
+ )
+
+ return team_channel_overwrites
+
+
+async def create_team_channel(
+ guild: discord.Guild,
+ team_name: str,
+ members: list[tuple[discord.Member, bool]],
+ team_leaders: discord.Role
+) -> None:
+ """Create the team's text channel."""
+ await _add_team_leader_roles(members, team_leaders)
+
+ # Get permission overwrites and category
+ team_channel_overwrites = _get_overwrites(members, guild)
+ code_jam_category = await _get_category(guild)
+
+ # Create a text channel for the team
+ await code_jam_category.create_text_channel(
+ team_name,
+ overwrites=team_channel_overwrites,
+ )
+
+
+async def create_team_leader_channel(guild: discord.Guild, team_leaders: discord.Role) -> None:
+ """Create the Team Leader Chat channel for the Code Jam team leaders."""
+ category: discord.CategoryChannel = guild.get_channel(Categories.summer_code_jam)
+
+ team_leaders_chat = await category.create_text_channel(
+ name="team-leaders-chat",
+ overwrites={
+ guild.default_role: discord.PermissionOverwrite(read_messages=False),
+ team_leaders: discord.PermissionOverwrite(read_messages=True)
+ }
+ )
+
+ await _send_status_update(guild, f"Created {team_leaders_chat.mention} in the {category} category.")
+
+
+async def _send_status_update(guild: discord.Guild, message: str) -> None:
+ """Inform the events lead with a status update when the command is ran."""
+ channel: discord.TextChannel = guild.get_channel(Channels.code_jam_planning)
+
+ await channel.send(f"<@&{Roles.events_lead}>\n\n{message}")
+
+
+async def _add_team_leader_roles(members: list[tuple[discord.Member, bool]], team_leaders: discord.Role) -> None:
+ """Assign team leader role, the jammer role and their team role."""
+ for member, is_leader in members:
+ if is_leader:
+ await member.add_roles(team_leaders)
diff --git a/bot/exts/events/code_jams/_cog.py b/bot/exts/events/code_jams/_cog.py
index 87ae847f6..2d0873de7 100644
--- a/bot/exts/events/code_jams/_cog.py
+++ b/bot/exts/events/code_jams/_cog.py
@@ -3,16 +3,14 @@ import logging
import typing as t
from collections import defaultdict
-import discord
from discord.ext import commands
from bot.bot import Bot
-from bot.constants import Categories, Channels, Emojis, Roles
+from bot.constants import Emojis, Roles
+from bot.exts.events.code_jams import _channels
log = logging.getLogger(__name__)
-MAX_CHANNELS = 50
-CATEGORY_NAME = "Code Jam"
TEAM_LEADERS_COLOUR = 0x11806a
@@ -67,110 +65,7 @@ class CodeJams(commands.Cog):
team_leaders = await ctx.guild.create_role(name="Code Jam Team Leaders", colour=TEAM_LEADERS_COLOUR)
for team_name, members in teams.items():
- await self.create_team_channel(ctx.guild, team_name, members, team_leaders)
+ await _channels.create_team_channel(ctx.guild, team_name, members, team_leaders)
- await self.create_team_leader_channel(ctx.guild, team_leaders)
+ await _channels.create_team_leader_channel(ctx.guild, team_leaders)
await ctx.send(f"{Emojis.check_mark} Created Code Jam with {len(teams)} teams.")
-
- async def get_category(self, guild: discord.Guild) -> discord.CategoryChannel:
- """
- Return a code jam category.
-
- If all categories are full or none exist, create a new category.
- """
- for category in guild.categories:
- if category.name == CATEGORY_NAME and len(category.channels) < MAX_CHANNELS:
- return category
-
- return await self.create_category(guild)
-
- async def create_category(self, guild: discord.Guild) -> discord.CategoryChannel:
- """Create a new code jam category and return it."""
- log.info("Creating a new code jam category.")
-
- category_overwrites = {
- guild.default_role: discord.PermissionOverwrite(read_messages=False),
- guild.me: discord.PermissionOverwrite(read_messages=True)
- }
-
- category = await guild.create_category_channel(
- CATEGORY_NAME,
- overwrites=category_overwrites,
- reason="It's code jam time!"
- )
-
- await self.send_status_update(
- guild, f"Created a new category with the ID {category.id} for this Code Jam's team channels."
- )
-
- return category
-
- @staticmethod
- def get_overwrites(
- members: list[tuple[discord.Member, bool]],
- guild: discord.Guild,
- ) -> dict[t.Union[discord.Member, discord.Role], discord.PermissionOverwrite]:
- """Get code jam team channels permission overwrites."""
- team_channel_overwrites = {
- guild.default_role: discord.PermissionOverwrite(read_messages=False),
- guild.get_role(Roles.code_jam_event_team): discord.PermissionOverwrite(read_messages=True)
- }
-
- for member, _ in members:
- team_channel_overwrites[member] = discord.PermissionOverwrite(
- read_messages=True
- )
-
- return team_channel_overwrites
-
- async def create_team_channel(
- self,
- guild: discord.Guild,
- team_name: str,
- members: list[tuple[discord.Member, bool]],
- team_leaders: discord.Role
- ) -> None:
- """Create the team's text channel."""
- await self.add_team_leader_roles(members, team_leaders)
-
- # Get permission overwrites and category
- team_channel_overwrites = self.get_overwrites(members, guild)
- code_jam_category = await self.get_category(guild)
-
- # Create a text channel for the team
- await code_jam_category.create_text_channel(
- team_name,
- overwrites=team_channel_overwrites,
- )
-
- async def create_team_leader_channel(self, guild: discord.Guild, team_leaders: discord.Role) -> None:
- """Create the Team Leader Chat channel for the Code Jam team leaders."""
- category: discord.CategoryChannel = guild.get_channel(Categories.summer_code_jam)
-
- team_leaders_chat = await category.create_text_channel(
- name="team-leaders-chat",
- overwrites={
- guild.default_role: discord.PermissionOverwrite(read_messages=False),
- team_leaders: discord.PermissionOverwrite(read_messages=True)
- }
- )
-
- await self.send_status_update(guild, f"Created {team_leaders_chat.mention} in the {category} category.")
-
- async def send_status_update(self, guild: discord.Guild, message: str) -> None:
- """Inform the events lead with a status update when the command is ran."""
- channel: discord.TextChannel = guild.get_channel(Channels.code_jam_planning)
-
- await channel.send(f"<@&{Roles.events_lead}>\n\n{message}")
-
- @staticmethod
- async def add_team_leader_roles(members: list[tuple[discord.Member, bool]], team_leaders: discord.Role) -> None:
- """Assign team leader role, the jammer role and their team role."""
- for member, is_leader in members:
- if is_leader:
- await member.add_roles(team_leaders)
-
-
-def setup(bot: Bot) -> None:
- """Load the CodeJams cog."""
- bot.add_cog(CodeJams(bot))
diff --git a/bot/exts/filters/antimalware.py b/bot/exts/filters/antimalware.py
index 3f6213db3..0eedeb0fb 100644
--- a/bot/exts/filters/antimalware.py
+++ b/bot/exts/filters/antimalware.py
@@ -7,7 +7,7 @@ from discord.ext.commands import Cog
from bot.bot import Bot
from bot.constants import Channels, Filter, URLs
-from bot.exts.events.code_jams._cog import CATEGORY_NAME as JAM_CATEGORY_NAME
+from bot.exts.events.code_jams._channels import CATEGORY_NAME as JAM_CATEGORY_NAME
log = logging.getLogger(__name__)
diff --git a/bot/exts/filters/antispam.py b/bot/exts/filters/antispam.py
index 124905cb4..1830e23b8 100644
--- a/bot/exts/filters/antispam.py
+++ b/bot/exts/filters/antispam.py
@@ -17,7 +17,7 @@ from bot.constants import (
Guild as GuildConfig, Icons,
)
from bot.converters import Duration
-from bot.exts.events.code_jams._cog import CATEGORY_NAME as JAM_CATEGORY_NAME
+from bot.exts.events.code_jams._channels import CATEGORY_NAME as JAM_CATEGORY_NAME
from bot.exts.moderation.modlog import ModLog
from bot.utils import lock, scheduling
from bot.utils.messages import format_user, send_attachments
diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py
index 0810425e2..10cc7885d 100644
--- a/bot/exts/filters/filtering.py
+++ b/bot/exts/filters/filtering.py
@@ -19,7 +19,7 @@ from bot.constants import (
Channels, Colours, Filter,
Guild, Icons, URLs
)
-from bot.exts.events.code_jams._cog import CATEGORY_NAME as JAM_CATEGORY_NAME
+from bot.exts.events.code_jams._channels import CATEGORY_NAME as JAM_CATEGORY_NAME
from bot.exts.moderation.modlog import ModLog
from bot.utils.messages import format_user
from bot.utils.regex import INVITE_RE
diff --git a/tests/bot/exts/events/test_code_jams.py b/tests/bot/exts/events/test_code_jams.py
index d7b8aa4d2..b9ee1e363 100644
--- a/tests/bot/exts/events/test_code_jams.py
+++ b/tests/bot/exts/events/test_code_jams.py
@@ -1,14 +1,15 @@
import unittest
-from unittest.mock import AsyncMock, MagicMock, create_autospec
+from unittest.mock import AsyncMock, MagicMock, create_autospec, patch
from discord import CategoryChannel
from discord.ext.commands import BadArgument
from bot.constants import Roles
-from bot.exts.events.code_jams import _cog
+from bot.exts.events import code_jams
+from bot.exts.events.code_jams import _channels, _cog
from tests.helpers import (
MockAttachment, MockBot, MockCategoryChannel, MockContext,
- MockGuild, MockMember, MockRole, MockTextChannel
+ MockGuild, MockMember, MockRole, MockTextChannel, autospec
)
TEST_CSV = b"""\
@@ -49,7 +50,9 @@ class JamCodejamCreateTests(unittest.IsolatedAsyncioTestCase):
with self.assertRaises(BadArgument):
await self.cog.create(self.cog, self.ctx, None)
- async def test_result_sending(self):
+ @patch.object(_channels, "create_team_channel")
+ @patch.object(_channels, "create_team_leader_channel")
+ async def test_result_sending(self, create_leader_channel, create_team_channel):
"""Should call `ctx.send` when everything goes right."""
self.ctx.message.attachments = [MockAttachment()]
self.ctx.message.attachments[0].read = AsyncMock()
@@ -61,14 +64,12 @@ class JamCodejamCreateTests(unittest.IsolatedAsyncioTestCase):
self.ctx.guild.create_role = AsyncMock()
self.ctx.guild.create_role.return_value = team_leaders
- self.cog.create_team_channel = AsyncMock()
- self.cog.create_team_leader_channel = AsyncMock()
self.cog.add_roles = AsyncMock()
await self.cog.create(self.cog, self.ctx, None)
- self.cog.create_team_channel.assert_awaited()
- self.cog.create_team_leader_channel.assert_awaited_once_with(
+ create_team_channel.assert_awaited()
+ create_leader_channel.assert_awaited_once_with(
self.ctx.guild, team_leaders
)
self.ctx.send.assert_awaited_once()
@@ -81,25 +82,24 @@ class JamCodejamCreateTests(unittest.IsolatedAsyncioTestCase):
self.ctx.send.assert_awaited_once()
- async def test_category_doesnt_exist(self):
+ @patch.object(_channels, "_send_status_update")
+ async def test_category_doesnt_exist(self, update):
"""Should create a new code jam category."""
subtests = (
[],
- [get_mock_category(_cog.MAX_CHANNELS, _cog.CATEGORY_NAME)],
- [get_mock_category(_cog.MAX_CHANNELS - 2, "other")],
+ [get_mock_category(_channels.MAX_CHANNELS, _channels.CATEGORY_NAME)],
+ [get_mock_category(_channels.MAX_CHANNELS - 2, "other")],
)
- self.cog.send_status_update = AsyncMock()
-
for categories in subtests:
- self.cog.send_status_update.reset_mock()
+ update.reset_mock()
self.guild.reset_mock()
self.guild.categories = categories
with self.subTest(categories=categories):
- actual_category = await self.cog.get_category(self.guild)
+ actual_category = await _channels._get_category(self.guild)
- self.cog.send_status_update.assert_called_once()
+ update.assert_called_once()
self.guild.create_category_channel.assert_awaited_once()
category_overwrites = self.guild.create_category_channel.call_args[1]["overwrites"]
@@ -109,45 +109,41 @@ class JamCodejamCreateTests(unittest.IsolatedAsyncioTestCase):
async def test_category_channel_exist(self):
"""Should not try to create category channel."""
- expected_category = get_mock_category(_cog.MAX_CHANNELS - 2, _cog.CATEGORY_NAME)
+ expected_category = get_mock_category(_channels.MAX_CHANNELS - 2, _channels.CATEGORY_NAME)
self.guild.categories = [
- get_mock_category(_cog.MAX_CHANNELS - 2, "other"),
+ get_mock_category(_channels.MAX_CHANNELS - 2, "other"),
expected_category,
- get_mock_category(0, _cog.CATEGORY_NAME),
+ get_mock_category(0, _channels.CATEGORY_NAME),
]
- actual_category = await self.cog.get_category(self.guild)
+ actual_category = await _channels._get_category(self.guild)
self.assertEqual(expected_category, actual_category)
async def test_channel_overwrites(self):
"""Should have correct permission overwrites for users and roles."""
leader = (MockMember(), True)
members = [leader] + [(MockMember(), False) for _ in range(4)]
- overwrites = self.cog.get_overwrites(members, self.guild)
+ overwrites = _channels._get_overwrites(members, self.guild)
for member, _ in members:
self.assertTrue(overwrites[member].read_messages)
- async def test_team_channels_creation(self):
+ @patch.object(_channels, "_get_overwrites")
+ @patch.object(_channels, "_get_category")
+ @autospec(_channels, "_add_team_leader_roles", pass_mocks=False)
+ async def test_team_channels_creation(self, get_category, get_overwrites):
"""Should create a text channel for a team."""
team_leaders = MockRole()
members = [(MockMember(), True)] + [(MockMember(), False) for _ in range(5)]
category = MockCategoryChannel()
category.create_text_channel = AsyncMock()
- self.cog.get_overwrites = MagicMock()
- self.cog.get_category = AsyncMock()
- self.cog.get_category.return_value = category
- self.cog.add_team_leader_roles = AsyncMock()
-
- await self.cog.create_team_channel(self.guild, "my-team", members, team_leaders)
- self.cog.add_team_leader_roles.assert_awaited_once_with(members, team_leaders)
- self.cog.get_overwrites.assert_called_once_with(members, self.guild)
- self.cog.get_category.assert_awaited_once_with(self.guild)
+ get_category.return_value = category
+ await _channels.create_team_channel(self.guild, "my-team", members, team_leaders)
category.create_text_channel.assert_awaited_once_with(
"my-team",
- overwrites=self.cog.get_overwrites.return_value
+ overwrites=get_overwrites.return_value
)
async def test_jam_roles_adding(self):
@@ -156,7 +152,7 @@ class JamCodejamCreateTests(unittest.IsolatedAsyncioTestCase):
leader = MockMember()
members = [(leader, True)] + [(MockMember(), False) for _ in range(4)]
- await self.cog.add_team_leader_roles(members, leader_role)
+ await _channels._add_team_leader_roles(members, leader_role)
leader.add_roles.assert_awaited_once_with(leader_role)
for member, is_leader in members:
@@ -170,5 +166,5 @@ class CodeJamSetup(unittest.TestCase):
def test_setup(self):
"""Should call `bot.add_cog`."""
bot = MockBot()
- _cog.setup(bot)
+ code_jams.setup(bot)
bot.add_cog.assert_called_once()