From 53604706c209815424b16bf79910fa7b0e8e6ae1 Mon Sep 17 00:00:00 2001 From: Nick Jungmann Date: Mon, 14 Nov 2022 22:29:43 +0100 Subject: [PATCH 1/4] Added technician module #44 --- kdb-bot/cpl-workspace.json | 3 +- kdb-bot/src/bot/config | 2 +- kdb-bot/src/bot/module_list.py | 2 + kdb-bot/src/bot/translation/de.json | 9 ++-- kdb-bot/src/bot_api/config | 2 +- kdb-bot/src/modules/base/base_module.py | 4 -- kdb-bot/src/modules/technician/__init__.py | 1 + .../modules/technician/command/__init__.py | 0 .../command/restart_command.py | 4 +- .../command/shutdown_command.py | 4 +- .../src/modules/technician/technician.json | 46 +++++++++++++++++++ .../modules/technician/technician_module.py | 27 +++++++++++ 12 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 kdb-bot/src/modules/technician/__init__.py create mode 100644 kdb-bot/src/modules/technician/command/__init__.py rename kdb-bot/src/modules/{base => technician}/command/restart_command.py (95%) rename kdb-bot/src/modules/{base => technician}/command/shutdown_command.py (95%) create mode 100644 kdb-bot/src/modules/technician/technician.json create mode 100644 kdb-bot/src/modules/technician/technician_module.py diff --git a/kdb-bot/cpl-workspace.json b/kdb-bot/cpl-workspace.json index 6587cbf6..ac1c4822 100644 --- a/kdb-bot/cpl-workspace.json +++ b/kdb-bot/cpl-workspace.json @@ -13,6 +13,7 @@ "level": "src/modules/level/level.json", "permission": "src/modules/permission/permission.json", "stats": "src/modules/stats/stats.json", + "technician": "src/modules/technician/technician.json", "get-version": "tools/get_version/get-version.json", "post-build": "tools/post_build/post-build.json", "set-version": "tools/set_version/set-version.json" @@ -20,10 +21,8 @@ "Scripts": { "sv": "cpl set-version", "set-version": "cpl run set-version $ARGS; echo '';", - "gv": "cpl get-version", "get-version": "export VERSION=$(cpl run get-version); echo $VERSION;", - "pre-build": "cpl set-version $ARGS", "post-build": "cpl run post-build", diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index bd8d3a5d..7eeac4a3 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit bd8d3a5dad13e0fdcad79b767c032997b716b1a4 +Subproject commit 7eeac4a343fcefb0aaff63a8fd28d35b46930f9a diff --git a/kdb-bot/src/bot/module_list.py b/kdb-bot/src/bot/module_list.py index 3eb60cd3..cde01cee 100644 --- a/kdb-bot/src/bot/module_list.py +++ b/kdb-bot/src/bot/module_list.py @@ -11,6 +11,7 @@ from modules.database.database_module import DatabaseModule from modules.level.level_module import LevelModule from modules.permission.permission_module import PermissionModule from modules.stats.stats_module import StatsModule +from modules.technician.technician_module import TechnicianModule class ModuleList: @@ -28,6 +29,7 @@ class ModuleList: PermissionModule, ApiModule, StatsModule, + TechnicianModule, # has to be last! BootLogModule, CoreExtensionModule, diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index 5b675289..986e5de0 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -72,11 +72,6 @@ } }, "modules": { - "admin": { - "restart_message": "Bin gleich wieder da :D", - "shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, Euer Freund. Lebt lange und in Frieden :)", - "deploy_message": "Der neue Stand wurde hochgeladen." - }, "auto_role": { "list": { "title": "Beobachtete Nachrichten:", @@ -249,6 +244,10 @@ "failed": "Statistik kann nicht gelöscht werden :(", "success": "Statistik wurde gelöscht :D" } + }, + "technician": { + "restart_message": "Bin gleich wieder da :D", + "shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, Euer Freund. Lebt lange und in Frieden :)" } }, "api": { diff --git a/kdb-bot/src/bot_api/config b/kdb-bot/src/bot_api/config index 98303ffd..43a44b31 160000 --- a/kdb-bot/src/bot_api/config +++ b/kdb-bot/src/bot_api/config @@ -1 +1 @@ -Subproject commit 98303ffd45445eecfad57f8b1be86729de3661d2 +Subproject commit 43a44b31f2efc644baadbf830b6414bab085fdea diff --git a/kdb-bot/src/modules/base/base_module.py b/kdb-bot/src/modules/base/base_module.py index 8da27656..cacde84b 100644 --- a/kdb-bot/src/modules/base/base_module.py +++ b/kdb-bot/src/modules/base/base_module.py @@ -12,8 +12,6 @@ from modules.base.command.help_command import HelpCommand from modules.base.command.info_command import InfoCommand from modules.base.command.ping_command import PingCommand from modules.base.command.purge_command import PurgeCommand -from modules.base.command.restart_command import RestartCommand -from modules.base.command.shutdown_command import ShutdownCommand from modules.base.command.user_group import UserGroup from modules.base.events.base_on_command_error_event import BaseOnCommandErrorEvent from modules.base.events.base_on_command_event import BaseOnCommandEvent @@ -41,8 +39,6 @@ class BaseModule(ModuleABC): self._dc.add_command(InfoCommand) self._dc.add_command(PingCommand) - self._dc.add_command(RestartCommand) - self._dc.add_command(ShutdownCommand) self._dc.add_command(PurgeCommand) self._dc.add_command(UserGroup) # events diff --git a/kdb-bot/src/modules/technician/__init__.py b/kdb-bot/src/modules/technician/__init__.py new file mode 100644 index 00000000..ad5eca30 --- /dev/null +++ b/kdb-bot/src/modules/technician/__init__.py @@ -0,0 +1 @@ +# imports: diff --git a/kdb-bot/src/modules/technician/command/__init__.py b/kdb-bot/src/modules/technician/command/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/kdb-bot/src/modules/base/command/restart_command.py b/kdb-bot/src/modules/technician/command/restart_command.py similarity index 95% rename from kdb-bot/src/modules/base/command/restart_command.py rename to kdb-bot/src/modules/technician/command/restart_command.py index c1fd3ae5..0a14e41b 100644 --- a/kdb-bot/src/modules/base/command/restart_command.py +++ b/kdb-bot/src/modules/technician/command/restart_command.py @@ -44,13 +44,13 @@ class RestartCommand(DiscordCommandABC): @commands.hybrid_command() @commands.guild_only() @CommandChecks.check_is_ready() - @CommandChecks.check_is_member_moderator() + @CommandChecks.check_is_member_technician() async def restart(self, ctx: Context): self._logger.debug(__name__, f'Received command restart {ctx}') self._config.add_configuration('IS_RESTART', 'true') await self._client_utils.presence_game('common.presence.restart') - await self._message_service.send_ctx_msg(ctx, self._t.transform('modules.admin.restart_message')) + await self._message_service.send_ctx_msg(ctx, self._t.transform('modules.technician.restart_message')) await asyncio.sleep(self._settings.wait_for_restart) await self._bot.stop_async() diff --git a/kdb-bot/src/modules/base/command/shutdown_command.py b/kdb-bot/src/modules/technician/command/shutdown_command.py similarity index 95% rename from kdb-bot/src/modules/base/command/shutdown_command.py rename to kdb-bot/src/modules/technician/command/shutdown_command.py index f8ebce5d..f81d127a 100644 --- a/kdb-bot/src/modules/base/command/shutdown_command.py +++ b/kdb-bot/src/modules/technician/command/shutdown_command.py @@ -45,12 +45,12 @@ class ShutdownCommand(DiscordCommandABC): @commands.hybrid_command() @commands.guild_only() @CommandChecks.check_is_ready() - @CommandChecks.check_is_member_moderator() + @CommandChecks.check_is_member_technician() async def shutdown(self, ctx: Context): self._logger.debug(__name__, f'Received command shutdown {ctx}') await self._client_utils.presence_game('common.presence.shutdown') - await self._message_service.send_ctx_msg(ctx, self._t.transform('modules.admin.shutdown_message')) + await self._message_service.send_ctx_msg(ctx, self._t.transform('modules.technician.shutdown_message')) await asyncio.sleep(self._settings.wait_for_shutdown) await self._bot.stop_async() diff --git a/kdb-bot/src/modules/technician/technician.json b/kdb-bot/src/modules/technician/technician.json new file mode 100644 index 00000000..a1a3340e --- /dev/null +++ b/kdb-bot/src/modules/technician/technician.json @@ -0,0 +1,46 @@ +{ + "ProjectSettings": { + "Name": "technician", + "Version": { + "Major": "0", + "Minor": "0", + "Micro": "0" + }, + "Author": "", + "AuthorEmail": "", + "Description": "", + "LongDescription": "", + "URL": "", + "CopyrightDate": "", + "CopyrightName": "", + "LicenseName": "", + "LicenseDescription": "", + "Dependencies": [ + "cpl-core>=2022.10.0.post7" + ], + "DevDependencies": [ + "cpl-cli>=2022.10.0" + ], + "PythonVersion": ">=3.10.6", + "PythonPath": { + "win32": "" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "technician.main", + "EntryPoint": "technician", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/kdb-bot/src/modules/technician/technician_module.py b/kdb-bot/src/modules/technician/technician_module.py new file mode 100644 index 00000000..089e36de --- /dev/null +++ b/kdb-bot/src/modules/technician/technician_module.py @@ -0,0 +1,27 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironmentABC +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.base.abc.base_helper_abc import BaseHelperABC +from modules.technician.command.restart_command import RestartCommand +from modules.technician.command.shutdown_command import ShutdownCommand +from modules.base.service.base_helper_service import BaseHelperService + + +class TechnicianModule(ModuleABC): + + def __init__(self, dc: DiscordCollectionABC): + ModuleABC.__init__(self, dc, FeatureFlagsEnum.base_module) + + def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + pass + + def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + services.add_transient(BaseHelperABC, BaseHelperService) + # commands + self._dc.add_command(RestartCommand) + self._dc.add_command(ShutdownCommand) + # events -- 2.45.2 From 2c7f4647af237903aaba3235b1985c21fd8c6903 Mon Sep 17 00:00:00 2001 From: Nick Jungmann Date: Wed, 16 Nov 2022 21:04:07 +0100 Subject: [PATCH 2/4] [WIP] Added log command #44 --- .../bot_core/abc/custom_file_logger_abc.py | 8 +- .../modules/technician/command/log_command.py | 95 +++++++++++++++++++ .../modules/technician/technician_module.py | 2 + 3 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 kdb-bot/src/modules/technician/command/log_command.py diff --git a/kdb-bot/src/bot_core/abc/custom_file_logger_abc.py b/kdb-bot/src/bot_core/abc/custom_file_logger_abc.py index c7354f65..d1cb8160 100644 --- a/kdb-bot/src/bot_core/abc/custom_file_logger_abc.py +++ b/kdb-bot/src/bot_core/abc/custom_file_logger_abc.py @@ -13,10 +13,14 @@ class CustomFileLoggerABC(Logger, ABC): @abstractmethod def __init__(self, key: str, config: ConfigurationABC, time_format: TimeFormatSettings, env: ApplicationEnvironmentABC): self._key = key - settings: LoggingSettings = config.get_configuration(f'{FileLoggingSettings.__name__}_{key}') - Logger.__init__(self, settings, time_format, env) + self._settings: LoggingSettings = config.get_configuration(f'{FileLoggingSettings.__name__}_{key}') + Logger.__init__(self, self._settings, time_format, env) self._begin_log() + @property + def settings(self) -> LoggingSettings: + return self._settings + def _begin_log(self): console_level = self._console.value self._console = LoggingLevelEnum.OFF diff --git a/kdb-bot/src/modules/technician/command/log_command.py b/kdb-bot/src/modules/technician/command/log_command.py new file mode 100644 index 00000000..d7395d46 --- /dev/null +++ b/kdb-bot/src/modules/technician/command/log_command.py @@ -0,0 +1,95 @@ +import os +from datetime import datetime + +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_core.logging import LoggingSettings +from cpl_discord.command import DiscordCommandABC +from cpl_query.extension import List +from cpl_translation import TranslatePipe +from discord.ext import commands +from discord.ext.commands import Context + +from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC +from bot_core.abc.custom_file_logger_abc import CustomFileLoggerABC +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_core.helper.command_checks import CommandChecks +from bot_core.logging.command_logger import CommandLogger +from modules.permission.abc.permission_service_abc import PermissionServiceABC + + +class LogCommand(DiscordCommandABC): + + def __init__( + self, + logger: CommandLogger, + logging_settings: LoggingSettings, + services: ServiceProviderABC, + message_service: MessageServiceABC, + client_utils: ClientUtilsServiceABC, + translate: TranslatePipe, + permissions: PermissionServiceABC, + ): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._logging_settings = logging_settings + self._services = services + self._message_service = message_service + self._client_utils = client_utils + self._t = translate + self._permissions = permissions + + self._logger.trace(__name__, f'Loaded command service: {type(self).__name__}') + + def _reduce_path(self, p: str) -> str: + if p.count('/') == 1 or p == '': + return p + + return self._reduce_path(os.path.dirname(p)) + + @commands.hybrid_command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_technician() + async def log(self, ctx: Context, date_from: datetime = datetime.now()): + self._logger.debug(__name__, f'Received command log {ctx}') + + possible_log_paths = List(str) + possible_log_paths.append(self._reduce_path(self._logging_settings.path)) + + file_extensions = List(str) + if '.' in self._logging_settings.filename: + split_filename = self._logging_settings.filename.split(".") + file_extensions.append(f'.{split_filename[len(split_filename) - 1]}') + + for subclass in CustomFileLoggerABC.__subclasses__(): + logger: CustomFileLoggerABC = self._services.get_service(subclass) + if logger is None: + continue + + path = self._reduce_path(logger.settings.path) + if '.' in logger.settings.filename: + split_filename = logger.settings.filename.split(".") + file_extension = f'.{split_filename[len(split_filename) - 1]}' + if file_extension not in file_extensions: + file_extensions.append(file_extension) + + if path in possible_log_paths: + continue + possible_log_paths.append(path) + + files = List(str) + now = datetime.now() + for possible_path in possible_log_paths: + for r, d, f in os.walk(possible_path): + for file in f: + if '.' not in file: + continue + + split_filename = file.split(".") + if f'.{split_filename[len(split_filename) - 1]}' not in file_extensions: + continue + + files.append(os.path.join(r, file)) + + self._logger.trace(__name__, f'Finished log command') diff --git a/kdb-bot/src/modules/technician/technician_module.py b/kdb-bot/src/modules/technician/technician_module.py index 089e36de..5c074ca8 100644 --- a/kdb-bot/src/modules/technician/technician_module.py +++ b/kdb-bot/src/modules/technician/technician_module.py @@ -6,6 +6,7 @@ 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.base.abc.base_helper_abc import BaseHelperABC +from modules.technician.command.log_command import LogCommand from modules.technician.command.restart_command import RestartCommand from modules.technician.command.shutdown_command import ShutdownCommand from modules.base.service.base_helper_service import BaseHelperService @@ -24,4 +25,5 @@ class TechnicianModule(ModuleABC): # commands self._dc.add_command(RestartCommand) self._dc.add_command(ShutdownCommand) + self._dc.add_command(LogCommand) # events -- 2.45.2 From 7b8dca64bf9f092b324648194a9d7a46db2c06c8 Mon Sep 17 00:00:00 2001 From: Nick Jungmann Date: Thu, 17 Nov 2022 22:45:10 +0100 Subject: [PATCH 3/4] Finished log command #44 --- kdb-bot/src/bot/translation/de.json | 3 ++- kdb-bot/src/bot_core/abc/message_service_abc.py | 2 +- kdb-bot/src/bot_core/service/message_service.py | 6 +++--- kdb-bot/src/modules/technician/command/log_command.py | 11 +++++++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index 986e5de0..9398972e 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -247,7 +247,8 @@ }, "technician": { "restart_message": "Bin gleich wieder da :D", - "shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, Euer Freund. Lebt lange und in Frieden :)" + "shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, Euer Freund. Lebt lange und in Frieden :)", + "log_message": "Hier sind deine Logdateien! :)" } }, "api": { diff --git a/kdb-bot/src/bot_core/abc/message_service_abc.py b/kdb-bot/src/bot_core/abc/message_service_abc.py index 614dd1df..3542e2b7 100644 --- a/kdb-bot/src/bot_core/abc/message_service_abc.py +++ b/kdb-bot/src/bot_core/abc/message_service_abc.py @@ -28,4 +28,4 @@ class MessageServiceABC(ABC): async def send_ctx_msg(self, ctx: Context, message: Union[str, discord.Embed], file: discord.File = None, is_persistent: bool = False, wait_before_delete: int = None, without_tracking=True): pass @abstractmethod - async def send_interaction_msg(self, interaction: Interaction, message: Union[str, discord.Embed], is_persistent: bool = False, wait_before_delete: int = None, without_tracking=True): pass + async def send_interaction_msg(self, interaction: Interaction, message: Union[str, discord.Embed], is_persistent: bool = False, wait_before_delete: int = None, without_tracking=True, **kwargs): pass diff --git a/kdb-bot/src/bot_core/service/message_service.py b/kdb-bot/src/bot_core/service/message_service.py index 04f33bfb..dcd329a2 100644 --- a/kdb-bot/src/bot_core/service/message_service.py +++ b/kdb-bot/src/bot_core/service/message_service.py @@ -119,7 +119,7 @@ class MessageService(MessageServiceABC): if ctx.guild is not None: await self.delete_message(msg, without_tracking) - async def send_interaction_msg(self, interaction: Interaction, message: Union[str, discord.Embed], is_persistent: bool = False, wait_before_delete: int = None, without_tracking=False): + async def send_interaction_msg(self, interaction: Interaction, message: Union[str, discord.Embed], is_persistent: bool = False, wait_before_delete: int = None, without_tracking=False, **kwargs): if interaction is None: self._logger.warn(__name__, 'Message context is empty') self._logger.debug(__name__, f'Message: {message}') @@ -128,9 +128,9 @@ class MessageService(MessageServiceABC): self._logger.debug(__name__, f'Try to send message\t\t{message}\n\tto: {interaction.channel}') try: if isinstance(message, discord.Embed): - await interaction.response.send_message(embed=message) + await interaction.response.send_message(embed=message, **kwargs) else: - await interaction.response.send_message(message) + await interaction.response.send_message(message, **kwargs) except Exception as e: self._logger.error(__name__, f'Send message to channel {interaction.channel.id} failed', e) else: diff --git a/kdb-bot/src/modules/technician/command/log_command.py b/kdb-bot/src/modules/technician/command/log_command.py index d7395d46..8d8c7832 100644 --- a/kdb-bot/src/modules/technician/command/log_command.py +++ b/kdb-bot/src/modules/technician/command/log_command.py @@ -1,6 +1,8 @@ import os from datetime import datetime +from zipfile import ZipFile +import discord from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.logging import LoggingSettings from cpl_discord.command import DiscordCommandABC @@ -51,7 +53,7 @@ class LogCommand(DiscordCommandABC): @commands.guild_only() @CommandChecks.check_is_ready() @CommandChecks.check_is_member_technician() - async def log(self, ctx: Context, date_from: datetime = datetime.now()): + async def log(self, ctx: Context): self._logger.debug(__name__, f'Received command log {ctx}') possible_log_paths = List(str) @@ -79,7 +81,6 @@ class LogCommand(DiscordCommandABC): possible_log_paths.append(path) files = List(str) - now = datetime.now() for possible_path in possible_log_paths: for r, d, f in os.walk(possible_path): for file in f: @@ -92,4 +93,10 @@ class LogCommand(DiscordCommandABC): files.append(os.path.join(r, file)) + zip_file = ZipFile('logs.zip', 'w') + files.for_each(lambda x: zip_file.write(x)) + zip_file.close() + await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform('modules.technician.log_message'), file=discord.File(zip_file.filename, 'logs.zip'), ephemeral=True) + os.remove(zip_file.filename) + self._logger.trace(__name__, f'Finished log command') -- 2.45.2 From e6fc41090aa4ece6ea5473c86ce3e1f39425ca31 Mon Sep 17 00:00:00 2001 From: Nick Jungmann Date: Thu, 17 Nov 2022 23:02:27 +0100 Subject: [PATCH 4/4] Refactored code #44 --- kdb-bot/cpl-workspace.json | 2 ++ kdb-bot/src/modules/technician/technician.json | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kdb-bot/cpl-workspace.json b/kdb-bot/cpl-workspace.json index ac1c4822..89d67f88 100644 --- a/kdb-bot/cpl-workspace.json +++ b/kdb-bot/cpl-workspace.json @@ -21,8 +21,10 @@ "Scripts": { "sv": "cpl set-version", "set-version": "cpl run set-version $ARGS; echo '';", + "gv": "cpl get-version", "get-version": "export VERSION=$(cpl run get-version); echo $VERSION;", + "pre-build": "cpl set-version $ARGS", "post-build": "cpl run post-build", diff --git a/kdb-bot/src/modules/technician/technician.json b/kdb-bot/src/modules/technician/technician.json index a1a3340e..9357fda8 100644 --- a/kdb-bot/src/modules/technician/technician.json +++ b/kdb-bot/src/modules/technician/technician.json @@ -22,9 +22,7 @@ "cpl-cli>=2022.10.0" ], "PythonVersion": ">=3.10.6", - "PythonPath": { - "win32": "" - }, + "PythonPath": {}, "Classifiers": [] }, "BuildSettings": { -- 2.45.2