From 6e74e9b190ed91de6a95f09932851dacfcf3775c Mon Sep 17 00:00:00 2001 From: edraft Date: Tue, 7 Jan 2025 17:56:56 +0100 Subject: [PATCH] Handle category updates #481 --- bot/src/modules/realms/events/__init__.py | 0 .../realms/events/realm_on_channel_update.py | 75 +++++++++++++++++++ bot/src/modules/realms/realm_utils.py | 21 +++++- bot/src/modules/realms/reams_module.py | 6 ++ 4 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 bot/src/modules/realms/events/__init__.py create mode 100644 bot/src/modules/realms/events/realm_on_channel_update.py diff --git a/bot/src/modules/realms/events/__init__.py b/bot/src/modules/realms/events/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bot/src/modules/realms/events/realm_on_channel_update.py b/bot/src/modules/realms/events/realm_on_channel_update.py new file mode 100644 index 00000000..e636a7be --- /dev/null +++ b/bot/src/modules/realms/events/realm_on_channel_update.py @@ -0,0 +1,75 @@ +import discord +from cpl_core.configuration import ConfigurationABC +from cpl_discord.events import OnGuildChannelUpdateABC +from discord import CategoryChannel + +from bot_core.logging.message_logger import MessageLogger +from bot_data.abc.realm_repository_abc import RealmRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.realm_moderator import RealmModerator +from modules.realms.realm_utils import RealmUtils + + +class RealmOnChannelUpdateEvent(OnGuildChannelUpdateABC): + def __init__( + self, + config: ConfigurationABC, + logger: MessageLogger, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + realms: RealmRepositoryABC, + realm_utils: RealmUtils, + ): + OnGuildChannelUpdateABC.__init__(self) + + self._config = config + self._logger = logger + self._servers = servers + self._users = users + self._realms = realms + self._realm_utils = realm_utils + + async def on_guild_channel_update(self, before: discord.abc.GuildChannel, after: discord.abc.GuildChannel): + self._logger.debug(__name__, f"Module {type(self)} started") + + realm = self._realms.find_realm_by_name(before.name) + if realm is None: + return + + if before.name != after.name: + realm.name = after.name + self._realms.update_realm(realm) + role = self._realm_utils.find_role_by_name(after.guild, before.name) + if role is not None: + await role.edit(name=after.name) + + if before.overwrites != after.overwrites: + role = self._realm_utils.get_role_by_name(after.guild, after.name) + if role not in after.overwrites: + await after.set_permissions( + role, + view_channel=True, + connect=True, + manage_channels=True, + manage_permissions=True, + create_instant_invite=True, + ) + + mods = self._realms.get_realm_moderators_by_realm_id(realm.id) + mod_users = mods.select(lambda x: x.user) + for mod in mods: + if mod.user not in after.overwrites: + self._realms.delete_realm_moderator(mod) + + server = self._servers.get_server_by_discord_id(after.guild.id) + for mod in after.overwrites: + if isinstance(mod, discord.Role): + continue + + if mod not in mod_users: + user = self._users.find_user_by_discord_id_and_server_id(mod.id, server.id) + self._realms.add_realm_moderator(RealmModerator(realm, user)) + await self._realm_utils.assign_moderator(after, mod) + + self._logger.debug(__name__, f"Module {type(self)} stopped") diff --git a/bot/src/modules/realms/realm_utils.py b/bot/src/modules/realms/realm_utils.py index 0df683ed..c20fb7c1 100644 --- a/bot/src/modules/realms/realm_utils.py +++ b/bot/src/modules/realms/realm_utils.py @@ -1,8 +1,9 @@ -from typing import Optional +from typing import Optional, Union import discord from cpl_discord.container import Role, CategoryChannel from discord import Guild, Member +from discord.abc import GuildChannel from bot_data.abc.realm_repository_abc import RealmRepositoryABC @@ -18,6 +19,13 @@ class RealmUtils: return Role(role) return None + @staticmethod + def get_role_by_name(guild: Guild, name: str) -> Optional[Role]: + for role in guild.roles: + if role.name == name: + return Role(role) + raise ValueError(f"Role {name} not found") + @staticmethod def find_category_by_name(guild: Guild, name: str) -> Optional[CategoryChannel]: for category in guild.categories: @@ -25,6 +33,13 @@ class RealmUtils: return CategoryChannel(category) return None + @staticmethod + def get_category_by_name(guild: Guild, name: str) -> Optional[CategoryChannel]: + for category in guild.categories: + if category.name == name: + return CategoryChannel(category) + raise ValueError(f"Category {name} not found") + @staticmethod def check_realm_role(guild: Guild, role: Role) -> bool: return role in guild.roles @@ -50,7 +65,7 @@ class RealmUtils: return await guild.create_category(name, overwrites=overwrites) @staticmethod - async def assign_moderator(category: CategoryChannel, member: Member): + async def assign_moderator(category: Union[CategoryChannel, GuildChannel], member: Member): await category.set_permissions( member, view_channel=True, @@ -61,7 +76,7 @@ class RealmUtils: ) @staticmethod - async def remove_moderator(category: CategoryChannel, member: Member): + async def remove_moderator(category: Union[CategoryChannel, GuildChannel], member: Member): await category.set_permissions( member, view_channel=True, diff --git a/bot/src/modules/realms/reams_module.py b/bot/src/modules/realms/reams_module.py index f338ef60..0d5901c9 100644 --- a/bot/src/modules/realms/reams_module.py +++ b/bot/src/modules/realms/reams_module.py @@ -1,11 +1,13 @@ from cpl_core.configuration import ConfigurationABC from cpl_core.dependency_injection import ServiceCollectionABC from cpl_core.environment import ApplicationEnvironmentABC +from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum from cpl_discord.service.discord_collection_abc import DiscordCollectionABC from bot_core.abc.module_abc import ModuleABC from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from modules.realms.command.realm_group import RealmGroup +from modules.realms.events.realm_on_channel_update import RealmOnChannelUpdateEvent from modules.realms.realm_utils import RealmUtils @@ -19,3 +21,7 @@ class RealmsModule(ModuleABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): services.add_transient(RealmGroup) services.add_transient(RealmUtils) + services.add_transient( + DiscordEventTypesEnum.on_guild_channel_update.value, + RealmOnChannelUpdateEvent, + )