diff --git a/.gitignore b/.gitignore index f8b73e7..6a660d8 100644 --- a/.gitignore +++ b/.gitignore @@ -138,3 +138,6 @@ dmypy.json # Cython debug symbols cython_debug/ +# custom vs code +PythonImportHelper-v2-Completion.json + diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..dc382e7 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,31 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Aktuelle Datei", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + }, + { + "name": "Gismo", + "type": "python", + "request": "launch", + "cwd": "${workspaceFolder}/src/gismo", + "program": "main.py", + "console": "integratedTerminal", + "args": [ + "--customer=sh-edraft.de" + ], + "env": { + "CPL_NAME": "Gismo", + "GISMO_ENVIRONMENT": "development", + "PYTHONPATH": "${workspaceFolder}/src/:$PYTHONPATH" + } + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4e78d7c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,24 @@ +{ + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#93e6fc", + "activityBar.activeBorder": "#fa45d4", + "activityBar.background": "#93e6fc", + "activityBar.foreground": "#15202b", + "activityBar.inactiveForeground": "#15202b99", + "activityBarBadge.background": "#fa45d4", + "activityBarBadge.foreground": "#15202b", + "sash.hoverBorder": "#93e6fc", + "statusBar.background": "#61dafb", + "statusBar.foreground": "#15202b", + "statusBarItem.hoverBackground": "#2fcefa", + "statusBarItem.remoteBackground": "#61dafb", + "statusBarItem.remoteForeground": "#15202b", + "titleBar.activeBackground": "#61dafb", + "titleBar.activeForeground": "#15202b", + "titleBar.inactiveBackground": "#61dafb99", + "titleBar.inactiveForeground": "#15202b99" + }, + "peacock.color": "#61dafb", + "python.pythonPath": "${workspaceRoot}/venv/bin/python", + "python.defaultInterpreterPath": "${workspaceRoot}/venv/bin/python", +} \ No newline at end of file diff --git a/LICENSE b/LICENSE index 204b93d..a23c753 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -MIT License Copyright (c) +MIT License Copyright (c) 2021-2022 sh-edraft.de Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/cpl-workspace.json b/cpl-workspace.json new file mode 100644 index 0000000..85ccd65 --- /dev/null +++ b/cpl-workspace.json @@ -0,0 +1,25 @@ +{ + "WorkspaceSettings": { + "DefaultProject": "gismo", + "Projects": { + "gismo": "src/gismo/gismo.json", + "gismo-cli": "src/gismo_cli/gismo-cli.json", + "gismo-core": "src/gismo_core/gismo-core.json", + "gismo-db": "src/gismo_db/gismo_db.json", + "database": "src/database/database.json", + "modules-core": "src/modules_core/modules-core.json", + "boot-log": "src/modules/boot_log/boot-log.json", + "level-generator": "tools/level_generator/level-generator.json", + "ontime-calculator": "tools/ontime_calculator/ontime-calculator.json" + }, + "Scripts": { + "pre-start": "echo '!WARNING! You should start with the right environment!\nRun cpl start-ENV\nSee workspace for more details.'; sleep 2", + "pre-dev-start": "echo 'development:'; ", + "dev-start": "export GISMO_ENVIRONMENT=development; export GISMO_NAME=Gismo-dev; cpl start", + "pre-stage-start": "echo 'staging:'; ", + "stage-start": "export GISMO_ENVIRONMENT=staging; export GISMO_NAME=Gismo-test; cpl start", + "pre-prod-start": "echo 'production:'; ", + "prod-start": "export GISMO_ENVIRONMENT=production; export GISMO_NAME=Gismo-prod; cpl start" + } + } +} \ No newline at end of file diff --git a/src/database/__init__.py b/src/database/__init__.py new file mode 100644 index 0000000..099bca2 --- /dev/null +++ b/src/database/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +database sh-edraft Gismo - database core +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - database implementation of cpl.database + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'database' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/database/appsettings.json b/src/database/appsettings.json new file mode 100644 index 0000000..629e6eb --- /dev/null +++ b/src/database/appsettings.json @@ -0,0 +1,15 @@ +{ + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "ERROR", + "FileLogLevel": "WARN" + } +} diff --git a/src/database/database.json b/src/database/database.json new file mode 100644 index 0000000..c743e12 --- /dev/null +++ b/src/database/database.json @@ -0,0 +1,44 @@ +{ + "ProjectSettings": { + "Name": "database", + "Version": { + "Major": "0", + "Minor": "1", + "Micro": "0" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "sh-edraft Gismo - database core", + "LongDescription": "sh-edraft Dicord bot Gismo - database implementation of cpl.database", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2021 - 2022", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "sh_cpl-core>=2021.10.2", + "sh_cpl-query>=2021.10.2" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "../../venv/bin/python" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "database.main", + "EntryPoint": "database", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/gismo/__init__.py b/src/gismo/__init__.py new file mode 100644 index 0000000..ca405f7 --- /dev/null +++ b/src/gismo/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +gismo sh-edraft Gismo +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'gismo' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/gismo/application.py b/src/gismo/application.py new file mode 100644 index 0000000..9602da6 --- /dev/null +++ b/src/gismo/application.py @@ -0,0 +1,36 @@ +from cpl_core.application import ApplicationABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.console import Console +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_core.logging import LoggerABC +from gismo_core.abc.bot_service_abc import BotServiceABC +from gismo_core.service.bot_service import BotService + + +class Gismo(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + + self._bot: BotService = services.get_service(BotServiceABC) + self._logger: LoggerABC = services.get_service(LoggerABC) + + async def configure(self): + pass + + async def main(self): + try: + self._logger.trace(__name__, f'Try to start {BotService}') + await self._bot.start_async() + except Exception as e: + self._logger.error(__name__, 'Start failed', e) + + async def stop_async(self): + try: + self._logger.trace(__name__, f'Try to stop {BotService}') + await self._bot.close() + self._logger.trace(__name__, f'Stopped {BotService}') + except Exception as e: + self._logger.error(__name__, 'stop failed', e) + + Console.write_line() diff --git a/src/gismo/appsettings.coBIANYXra.json b/src/gismo/appsettings.coBIANYXra.json new file mode 100644 index 0000000..eec0a76 --- /dev/null +++ b/src/gismo/appsettings.coBIANYXra.json @@ -0,0 +1,5 @@ +{ + "Discord": { + "Token": "OTExNjM5NjE2MTAzMjUyMDM4.YZkUjQ.MCqPkOTIMdvMYrmt47lfrZ0inhg" + } +} diff --git a/src/gismo/appsettings.development.json b/src/gismo/appsettings.development.json new file mode 100644 index 0000000..7b125c1 --- /dev/null +++ b/src/gismo/appsettings.development.json @@ -0,0 +1,28 @@ +{ + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_dev.log", + "ConsoleLogLevel": "DEBUG", + "FileLogLevel": "DEBUG" + }, + "Discord": { + "Token": "OTA5ODc4NDcyNzExNzU3ODQ1.YZKsXA.BXBszIF3z3wHpoe9s3pKfO3Yd5c" + }, + "Bot": { + "Prefix": "!gd", + "Servers": [ + { + "Id": "910199451145076828", + "LoginMessageChannelId": "910199452915093588", + "LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert", + "MessageDeleteTimer": 2 + } + ] + } +} \ No newline at end of file diff --git a/src/gismo/appsettings.edrafts-lapi.json b/src/gismo/appsettings.edrafts-lapi.json new file mode 100644 index 0000000..1a0300b --- /dev/null +++ b/src/gismo/appsettings.edrafts-lapi.json @@ -0,0 +1,22 @@ +{ + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_dev.log", + "ConsoleLogLevel": "TRACE", + "FileLogLevel": "TRACE" + }, + "Discord": { + "Token": "OTExNTc0NDQyMzMxNzM0MDI2.YZjX2w.9yhsrTfrmkoDUqRJVzV5FVEwF3U" + }, + "Bot": { + "Prefix": "!gde", + "Servers": [ + { + "Id": "910199451145076828", + "LoginMessageChannelId": "910199452915093588", + "LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert", + "MessageDeleteTimer": 2 + } + ] + } +} \ No newline at end of file diff --git a/src/gismo/appsettings.edrafts-pc.json b/src/gismo/appsettings.edrafts-pc.json new file mode 100644 index 0000000..1a0300b --- /dev/null +++ b/src/gismo/appsettings.edrafts-pc.json @@ -0,0 +1,22 @@ +{ + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_dev.log", + "ConsoleLogLevel": "TRACE", + "FileLogLevel": "TRACE" + }, + "Discord": { + "Token": "OTExNTc0NDQyMzMxNzM0MDI2.YZjX2w.9yhsrTfrmkoDUqRJVzV5FVEwF3U" + }, + "Bot": { + "Prefix": "!gde", + "Servers": [ + { + "Id": "910199451145076828", + "LoginMessageChannelId": "910199452915093588", + "LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert", + "MessageDeleteTimer": 2 + } + ] + } +} \ No newline at end of file diff --git a/src/gismo/appsettings.json b/src/gismo/appsettings.json new file mode 100644 index 0000000..629e6eb --- /dev/null +++ b/src/gismo/appsettings.json @@ -0,0 +1,15 @@ +{ + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "ERROR", + "FileLogLevel": "WARN" + } +} diff --git a/src/gismo/appsettings.production.json b/src/gismo/appsettings.production.json new file mode 100644 index 0000000..8ddbe25 --- /dev/null +++ b/src/gismo/appsettings.production.json @@ -0,0 +1,28 @@ +{ + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "ERROR", + "FileLogLevel": "WARN" + }, + "Discord": { + "Token": "OTA5ODc3NDg3MjEzODk5ODQ3.YZKrcQ.qwfDWBFdkOzxZZT10jUWG5fY2RA" + }, + "Bot": { + "Prefix": "!g", + "Servers": [ + { + "Id": "511824600884051979", + "LoginMessageChannelId": "521260270757347328", + "LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert", + "MessageDeleteTimer": 2 + } + ] + } +} \ No newline at end of file diff --git a/src/gismo/appsettings.staging.json b/src/gismo/appsettings.staging.json new file mode 100644 index 0000000..31aaa85 --- /dev/null +++ b/src/gismo/appsettings.staging.json @@ -0,0 +1,28 @@ +{ + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_staging_$start_time.log", + "ConsoleLogLevel": "DEBUG", + "FileLogLevel": "DEBUG" + }, + "Discord": { + "Token": "OTEwMjAxNjA1NDkwNjEwMjA3.YZPZTQ.kvMUuDUH_-qsllgkch8LYmXcKlo" + }, + "Bot": { + "Prefix": "!gt", + "Servers": [ + { + "Id": "511824600884051979", + "LoginMessageChannelId": "521260270757347328", + "LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert", + "MessageDeleteTimer": 2 + } + ] + } +} \ No newline at end of file diff --git a/src/gismo/gismo.json b/src/gismo/gismo.json new file mode 100644 index 0000000..b8a447a --- /dev/null +++ b/src/gismo/gismo.json @@ -0,0 +1,54 @@ +{ + "ProjectSettings": { + "Name": "gismo", + "Version": { + "Major": "0", + "Minor": "1", + "Micro": "0" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "sh-edraft Gismo", + "LongDescription": "sh-edraft Dicord bot Gismo", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2021 - 2022", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "sh_cpl-core>=2021.10.2", + "sh_cpl-query>=2021.10.2", + "discord.py==1.7.3" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "../../venv/bin/python" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "console", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "gismo.main", + "EntryPoint": "gismo", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": { + "cpl_cli": [ + "*.json" + ] + }, + "ProjectReferences": [ + "../gismo_core/gismo-core.json", + "../gismo_db/gismo-db.json", + "../modules_core/modules-core.json", + "../modules/boot_log/boot-log.json" + ] + } +} \ No newline at end of file diff --git a/src/gismo/main.py b/src/gismo/main.py new file mode 100644 index 0000000..4717405 --- /dev/null +++ b/src/gismo/main.py @@ -0,0 +1,44 @@ +import asyncio +from typing import Optional + +from cpl_core.application import ApplicationBuilder + +from gismo.application import Gismo +from gismo.startup import Startup +from modules.boot_log.boot_log_extension import BootLogExtension + + +class Main: + + def __init__(self): + self._gismo: Optional[Gismo] = None + + async def main(self): + app_builder = ApplicationBuilder(Gismo) + app_builder.use_extension(BootLogExtension) + app_builder.use_startup(Startup) + self._gismo: Gismo = await app_builder.build_async() + await self._gismo.run_async() + + async def stop(self): + await self._gismo.stop_async() + + +if __name__ == '__main__': + main = Main() + ml = asyncio.get_event_loop() + try: + ml.run_until_complete(main.main()) + except KeyboardInterrupt: + ml.run_until_complete(main.stop()) + + +# (( +# ( `) +# ; / , +# / \/ +# / | +# / ~/ +# / ) ) ~ edraft +# ___// | / +# `--' \_~-, \ No newline at end of file diff --git a/src/gismo/startup.py b/src/gismo/startup.py new file mode 100644 index 0000000..cd31396 --- /dev/null +++ b/src/gismo/startup.py @@ -0,0 +1,56 @@ +from datetime import datetime +from typing import Optional + +from cpl_core.application import StartupABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import (ServiceCollectionABC, + ServiceProviderABC) +from cpl_core.environment import ApplicationEnvironment +from cpl_core.logging import LoggerABC +from gismo_core.abc.bot_service_abc import BotServiceABC +from gismo_core.abc.message_service_abc import MessageServiceABC +from gismo_core.service.bot_service import BotService +from gismo_core.service.message_service import MessageService +from modules.boot_log.boot_log import BootLog +from modules_core.abc.module_abc import ModuleABC +from modules_core.abc.module_service_abc import ModuleServiceABC +from modules_core.service.module_service import ModuleService + + +class Startup(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + self._start_time = datetime.now() + + self._config: Optional[ConfigurationABC] = None + + async def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + configuration.add_environment_variables('GISMO_') + + configuration.add_json_file(f'appsettings.json', optional=False) + configuration.add_json_file(f'appsettings.{environment.environment_name}.json', optional=True) + configuration.add_json_file(f'appsettings.{environment.host_name}.json', optional=True) + + configuration.add_configuration('Startup_StartTime', self._start_time) + + self._config = configuration + return configuration + + async def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + services.add_logging() + + services.add_singleton(ModuleServiceABC, ModuleService) + services.add_singleton(BotServiceABC, BotService) + services.add_transient(MessageServiceABC, MessageService) + + services.add_transient(ModuleABC, BootLog) + + provider: ServiceProviderABC = services.build_service_provider() + + startup_init_time = round((datetime.now() - self._config.get_configuration('Startup_StartTime')).total_seconds(), 2) + self._config.add_configuration('Startup_InitTime', startup_init_time) + logger: LoggerABC = provider.get_service(LoggerABC) + logger.debug(__name__, f'Startup Init time: {startup_init_time}s') + + return provider diff --git a/src/gismo_cli/__init__.py b/src/gismo_cli/__init__.py new file mode 100644 index 0000000..8318a61 --- /dev/null +++ b/src/gismo_cli/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +gismo-cli sh-edraft Gismo - CLI +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - command line interface + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'gismo_cli' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/gismo_cli/application.py b/src/gismo_cli/application.py new file mode 100644 index 0000000..b2df025 --- /dev/null +++ b/src/gismo_cli/application.py @@ -0,0 +1,16 @@ +from cpl_core.application import ApplicationABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.console import Console +from cpl_core.dependency_injection import ServiceProviderABC + + +class Application(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + + async def configure(self): + pass + + async def main(self): + Console.write_line('Hello World') diff --git a/src/gismo_cli/appsettings.json b/src/gismo_cli/appsettings.json new file mode 100644 index 0000000..629e6eb --- /dev/null +++ b/src/gismo_cli/appsettings.json @@ -0,0 +1,15 @@ +{ + "TimeFormatSettings": { + "DateFormat": "%Y-%m-%d", + "TimeFormat": "%H:%M:%S", + "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", + "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" + }, + + "LoggingSettings": { + "Path": "logs/", + "Filename": "log_$start_time.log", + "ConsoleLogLevel": "ERROR", + "FileLogLevel": "WARN" + } +} diff --git a/src/gismo_cli/gismo-cli.json b/src/gismo_cli/gismo-cli.json new file mode 100644 index 0000000..eebe3c2 --- /dev/null +++ b/src/gismo_cli/gismo-cli.json @@ -0,0 +1,48 @@ +{ + "ProjectSettings": { + "Name": "gismo-cli", + "Version": { + "Major": "0", + "Minor": "1", + "Micro": "0" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "sh-edraft Gismo - CLI", + "LongDescription": "sh-edraft Dicord bot Gismo - command line interface", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2021 - 2022", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "sh_cpl-core>=2021.10.2", + "sh_cpl-query>=2021.10.2" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "../../venv/bin/python" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "console", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "gismo.main", + "EntryPoint": "gismo", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": { + "cpl_cli": [ + "*.json" + ] + }, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/gismo_cli/main.py b/src/gismo_cli/main.py new file mode 100644 index 0000000..e16a50d --- /dev/null +++ b/src/gismo_cli/main.py @@ -0,0 +1,18 @@ +import asyncio + +from cpl_core.application import ApplicationBuilder + +from gismo_cli.application import Application +from gismo_cli.startup import Startup + + +async def main(): + app_builder = ApplicationBuilder(Application) + app_builder.use_startup(Startup) + app: Application = await app_builder.build_async() + await app.run_async() + + +if __name__ == '__main__': + ml = asyncio.get_event_loop() + ml.run_until_complete(main()) diff --git a/src/gismo_cli/startup.py b/src/gismo_cli/startup.py new file mode 100644 index 0000000..dadaee3 --- /dev/null +++ b/src/gismo_cli/startup.py @@ -0,0 +1,16 @@ +from cpl_core.application import StartupABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironment + + +class Startup(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + + async def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + return configuration + + async def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + return services.build_service_provider() diff --git a/src/gismo_core/__init__.py b/src/gismo_core/__init__.py new file mode 100644 index 0000000..4ee4e9e --- /dev/null +++ b/src/gismo_core/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +gismo-core sh-edraft Gismo - core +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - core library + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'gismo_core' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/gismo_core/abc/__init__.py b/src/gismo_core/abc/__init__.py new file mode 100644 index 0000000..58b8479 --- /dev/null +++ b/src/gismo_core/abc/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +gismo-core sh-edraft Gismo - core +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - core library + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'gismo_core.abc' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/gismo_core/abc/bot_service_abc.py b/src/gismo_core/abc/bot_service_abc.py new file mode 100644 index 0000000..c33aaf2 --- /dev/null +++ b/src/gismo_core/abc/bot_service_abc.py @@ -0,0 +1,16 @@ +from abc import ABC, abstractmethod + +import discord +from discord.ext import commands + + +class BotServiceABC(ABC, commands.Bot): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def start_async(self): pass + + @abstractmethod + async def stop_async(self): pass diff --git a/src/gismo_core/abc/message_service_abc.py b/src/gismo_core/abc/message_service_abc.py new file mode 100644 index 0000000..1b91937 --- /dev/null +++ b/src/gismo_core/abc/message_service_abc.py @@ -0,0 +1,27 @@ +from abc import ABC, abstractmethod +from typing import Union + +import discord +from cpl_query.extension import List +from discord.ext.commands import Context + + +class MessageServiceABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def delete_messages(self, messages: List[discord.Message]): pass + + @abstractmethod + async def delete_message(self, message: discord.Message): pass + + @abstractmethod + async def send_channel_message(self, channel: discord.TextChannel, message: str): pass + + @abstractmethod + async def send_dm_message(self, message: str, receiver: Union[discord.User, discord.Member]): pass + + @abstractmethod + async def send_ctx_msg(self, ctx: Context, message: str, file: discord.File = None): pass diff --git a/src/gismo_core/configuration/__init__.py b/src/gismo_core/configuration/__init__.py new file mode 100644 index 0000000..3ae8faa --- /dev/null +++ b/src/gismo_core/configuration/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +gismo-core sh-edraft Gismo - core +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - core library + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'gismo_core.configuration' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/gismo_core/configuration/bot_settings.py b/src/gismo_core/configuration/bot_settings.py new file mode 100644 index 0000000..fb1bd63 --- /dev/null +++ b/src/gismo_core/configuration/bot_settings.py @@ -0,0 +1,36 @@ +import traceback + +from cpl_core.configuration import ConfigurationModelABC +from cpl_core.console import Console +from cpl_query.extension import List +from gismo_core.configuration.server_settings import ServerSettings + + +class BotSettings(ConfigurationModelABC): + + def __init__(self): + ConfigurationModelABC.__init__(self) + + self._prefix: str = '' + self._servers: List[ServerSettings] = List() + + @property + def prefix(self) -> str: + return self._prefix + + @property + def servers(self) -> List[ServerSettings]: + return self._servers + + def from_dict(self, settings: dict): + try: + self._prefix = settings['Prefix'] + servers = List(ServerSettings) + for s in settings['Servers']: + st = ServerSettings() + st.from_dict(s) + servers.append(st) + self._servers = servers + except Exception as e: + Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings') + Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') diff --git a/src/gismo_core/configuration/discord_settings.py b/src/gismo_core/configuration/discord_settings.py new file mode 100644 index 0000000..efec204 --- /dev/null +++ b/src/gismo_core/configuration/discord_settings.py @@ -0,0 +1,23 @@ +import traceback + +from cpl_core.configuration import ConfigurationModelABC +from cpl_core.console import Console + + +class DiscordSettings(ConfigurationModelABC): + + def __init__(self): + ConfigurationModelABC.__init__(self) + + self._token: str = '' + + @property + def token(self) -> str: + return self._token + + def from_dict(self, settings: dict): + try: + self._token = settings['Token'] + except Exception as e: + Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings') + Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') diff --git a/src/gismo_core/configuration/server_settings.py b/src/gismo_core/configuration/server_settings.py new file mode 100644 index 0000000..f339b9c --- /dev/null +++ b/src/gismo_core/configuration/server_settings.py @@ -0,0 +1,41 @@ +import traceback + +from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC +from cpl_core.console import Console + + +class ServerSettings(ConfigurationModelABC): + + def __init__(self): + ConfigurationModelABC.__init__(self) + + self._id: int = 0 + self._message_delete_timer: int = 0 + self._login_message_channel_id: int = 0 + self._login_message: str = '' + + @property + def id(self) -> str: + return self._id + + @property + def message_delete_timer(self) -> int: + return self._message_delete_timer + + @property + def login_message_channel_id(self) -> int: + return self._login_message_channel_id + + @property + def login_message(self) -> str: + return self._login_message + + def from_dict(self, settings: dict): + try: + self._id = int(settings['Id']) + self._message_delete_timer = int(settings['MessageDeleteTimer']) + self._login_message_channel_id = int(settings['LoginMessageChannelId']) + self._login_message = settings['LoginMessage'] + except Exception as e: + Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings') + Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') diff --git a/src/gismo_core/gismo-core.json b/src/gismo_core/gismo-core.json new file mode 100644 index 0000000..368ba0a --- /dev/null +++ b/src/gismo_core/gismo-core.json @@ -0,0 +1,44 @@ +{ + "ProjectSettings": { + "Name": "gismo-core", + "Version": { + "Major": "0", + "Minor": "1", + "Micro": "0" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "sh-edraft Gismo - core", + "LongDescription": "sh-edraft Dicord bot Gismo - core library", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2021 - 2022", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "sh_cpl-core>=2021.10.2", + "sh_cpl-query>=2021.10.2" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "../../venv/bin/python" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "gismo_core.main", + "EntryPoint": "gismo-core", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/gismo_core/service/__init__.py b/src/gismo_core/service/__init__.py new file mode 100644 index 0000000..2eae97b --- /dev/null +++ b/src/gismo_core/service/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +gismo-core sh-edraft Gismo - core +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - core library + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'gismo_core.service' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/gismo_core/service/bot_service.py b/src/gismo_core/service/bot_service.py new file mode 100644 index 0000000..becdab4 --- /dev/null +++ b/src/gismo_core/service/bot_service.py @@ -0,0 +1,71 @@ +import discord +from cpl_core.configuration import ConfigurationABC +from cpl_core.console import Console +from cpl_core.environment import ApplicationEnvironmentABC +from cpl_core.logging import LoggerABC, LoggingLevelEnum, LoggingSettings +from discord.ext import commands +from gismo_core.abc.bot_service_abc import BotServiceABC +from gismo_core.configuration.bot_settings import BotSettings +from gismo_core.configuration.discord_settings import DiscordSettings +from gismo_core.configuration.server_settings import ServerSettings +from modules_core.abc.module_service_abc import ModuleServiceABC +from modules_core.service.module_service import ModuleService + + +class BotService(BotServiceABC, commands.Bot): + + def __init__( + self, + config: ConfigurationABC, + logger: LoggerABC, + modules: ModuleService, + discord_settings: DiscordSettings, + bot_settings: BotSettings, + env: ApplicationEnvironmentABC, + logging_st: LoggingSettings, + ): + # services + self._config = config + self._logger = logger + self._modules = modules + self._env = env + self._logging_st = logging_st + + # settings + self._discord_settings = discord_settings + self._bot_settings: BotSettings = bot_settings + + # setup super + commands.Bot.__init__(self, command_prefix=bot_settings.prefix, help_command=None) + + async def start_async(self): + self._logger.trace(__name__, 'Try to connect to discord') + + self.add_cog(self._modules) + + await self.start(self._discord_settings.token) + # continue at on_ready + + async def stop_async(self): + self._logger.debug(__name__, f'Try to stop {BotService}') + try: + pass + # save data + except Exception as e: + self._logger.error(__name__, 'Stop failed', e) + + async def on_ready(self): + self._logger.info(__name__, 'Connected to discord') + + self._logger.debug(__name__, 'Try to load discord server configs') + for server in self._bot_settings.servers: + server: ServerSettings = server + self._logger.trace(__name__, f'Try to load config for server: {server.id}') + self._config.add_configuration(f'DSERVER_{server.id}', server) + self._logger.trace(__name__, f'Loaded config for server: {server.id}') + + self._logger.header(f'{self.user.name}:') + if self._logging_st.console.value >= LoggingLevelEnum.INFO.value: + Console.banner(self._env.application_name if self._env.application_name != '' else 'Gismo') + + await self._modules.on_ready() diff --git a/src/gismo_core/service/message_service.py b/src/gismo_core/service/message_service.py new file mode 100644 index 0000000..32ae1c3 --- /dev/null +++ b/src/gismo_core/service/message_service.py @@ -0,0 +1,76 @@ +import asyncio +from typing import Union + +import discord +from cpl_core.configuration.configuration_abc import ConfigurationABC +from cpl_core.logging import LoggerABC +from cpl_query.extension import List +from discord.ext.commands import Context + +from gismo_core.abc.bot_service_abc import BotServiceABC +from gismo_core.abc.message_service_abc import MessageServiceABC +from gismo_core.configuration.server_settings import ServerSettings + + +class MessageService(MessageServiceABC): + + def __init__(self, config: ConfigurationABC, logger: LoggerABC, bot: BotServiceABC): + self._config = config + self._logger = logger + self._bot = bot + + async def delete_messages(self, messages: List[discord.Message]): + self._logger.debug(__name__, f'Try to delete {messages.count()} messages') + for message in messages: + await self.delete_message(message) + self._logger.debug(__name__, 'Deleting messages finished') + + async def delete_message(self, message: discord.Message): + server_st: ServerSettings = self._config.get_configuration(f'DSERVER_{message.guild.id}') + await asyncio.sleep(server_st.message_delete_timer) + self._logger.debug(__name__, f'Try to delete message:\n\t{message}\n\t{message.content}') + try: + await message.delete() + except Exception as e: + self._logger.error(__name__, f'Deleting message failed', e) + else: + self._logger.info(__name__, f'Deleted message {message}') + + async def send_channel_message(self, channel: discord.TextChannel, message: str): + self._logger.debug(__name__, f'Try to send message\n\t{message}\n\tto: {channel}') + msg = None + try: + msg = await channel.send(message) + except Exception as e: + self._logger.error(__name__, f'Send message to channel {channel.id} failed', e) + else: + self._logger.info(__name__, f'Sent message to channel {channel.id}') + await self.delete_message(msg) + + async def send_dm_message(self, message: str, receiver: Union[discord.User, discord.Member]): + self._logger.debug(__name__, f'Try to send message\n\t{message}\n\tto: {receiver}') + try: + await receiver.send(message) + except Exception as e: + self._logger.error(__name__, f'Send message to user {receiver.id} failed', e) + else: + self._logger.info(__name__, f'Sent message to user {receiver.id}') + + async def send_ctx_msg(self, ctx: Context, message: Union[str, discord.File]): + if ctx is None: + self._logger.warn(__name__, 'Message context is empty') + self._logger.debug(__name__, f'Message: {message}') + return + + self._logger.debug(__name__, f'Try to send message\t\t{message}\n\tto: {ctx.channel}') + msg = None + try: + if isinstance(message, discord.File): + msg = await ctx.send(file=message) + else: + msg = await ctx.send(message) + except Exception as e: + self._logger.error(__name__, f'Send message to channel {ctx.channel.id} failed', e) + else: + self._logger.info(__name__, f'Sent message to channel {ctx.channel.id}') + await self.delete_message(msg) diff --git a/src/gismo_db/__init__.py b/src/gismo_db/__init__.py new file mode 100644 index 0000000..d9d752f --- /dev/null +++ b/src/gismo_db/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +gismo-db sh-edraft Gismo - Database +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - Database + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'gismo_db' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/gismo_db/gismo-db.json b/src/gismo_db/gismo-db.json new file mode 100644 index 0000000..c546daa --- /dev/null +++ b/src/gismo_db/gismo-db.json @@ -0,0 +1,44 @@ +{ + "ProjectSettings": { + "Name": "gismo-db", + "Version": { + "Major": "0", + "Minor": "1", + "Micro": "0" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "sh-edraft Gismo - Database", + "LongDescription": "sh-edraft Dicord bot Gismo - Database", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2021 - 2022", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "sh_cpl-core>=2021.10.2", + "sh_cpl-query>=2021.10.2" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "../../venv/bin/python" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "gismo_db.main", + "EntryPoint": "gismo_db", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/modules/__init__.py b/src/modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/boot_log/__init__.py b/src/modules/boot_log/__init__.py new file mode 100644 index 0000000..78e0aa2 --- /dev/null +++ b/src/modules/boot_log/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +modules/boot-log sh-edraft Gismo - Boot log +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - Boot log + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'boot_log' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports: + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/modules/boot_log/boot-log.json b/src/modules/boot_log/boot-log.json new file mode 100644 index 0000000..d86f1a0 --- /dev/null +++ b/src/modules/boot_log/boot-log.json @@ -0,0 +1,44 @@ +{ + "ProjectSettings": { + "Name": "modules/boot-log", + "Version": { + "Major": "0", + "Minor": "1", + "Micro": "0" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "sh-edraft Gismo - Boot log", + "LongDescription": "sh-edraft Dicord bot Gismo - Boot log", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2021 - 2022", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "sh_cpl-core>=2021.10.2", + "sh_cpl-query>=2021.10.2" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "../../venv/bin/python" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "modules/_boot_log.main", + "EntryPoint": "modules/boot-log", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/modules/boot_log/boot_log.py b/src/modules/boot_log/boot_log.py new file mode 100644 index 0000000..4ee4834 --- /dev/null +++ b/src/modules/boot_log/boot_log.py @@ -0,0 +1,72 @@ +from datetime import datetime + +import discord +from cpl_core.configuration import ConfigurationABC +from cpl_core.logging import LoggerABC +from discord import guild + +from gismo_core.abc.bot_service_abc import BotServiceABC +from gismo_core.abc.message_service_abc import MessageServiceABC +from gismo_core.configuration.server_settings import ServerSettings +from modules_core.abc.events.on_ready_abc import OnReadyABC +from modules_core.abc.module_abc import ModuleABC + + +class BootLog(ModuleABC, OnReadyABC): + + def __init__( + self, + config: ConfigurationABC, + logger: LoggerABC, + bot: BotServiceABC, + message_service: MessageServiceABC + ): + self._config = config + + self._logger = logger + self._bot = bot + self._message_service = message_service + + ModuleABC.__init__(self) + self._priorities[OnReadyABC] = 10 + self._logger.trace(__name__, f'Module {type(self)} loaded') + + async def on_ready(self): + self._logger.debug(__name__, f'Module {type(self)} started') + try: + start_time = self._config.get_configuration('Bot_StartTime') + init_time = round((datetime.now() - start_time).total_seconds(), 2) + self._config.add_configuration('InitTime', init_time) + self._logger.debug(__name__, f'Bot Init time: {init_time}s') + # print warning if initialisation took too long + if init_time >= 30: + self._logger.warn( + __name__, 'It takes long time to start the bot!') + + # print error if initialisation took way too long + elif init_time >= 90: + self._logger.error( + __name__, 'It takes very long time to start the bot!!!') + except Exception as e: + self._logger.error(__name__, 'Init time calculation failed', e) + return + + for g in self._bot.guilds: + g: guild = g + self._logger.debug(__name__, f'Server detected: {g.id}') + + server_settings: ServerSettings = self._config.get_configuration( + f'DSERVER_{g.id}') + if server_settings is None: + self._logger.error( + __name__, f'Config for server {g.id} not found!') + await self._bot.close() + return + + await self._message_service.send_channel_message( + self._bot.get_channel( + server_settings.login_message_channel_id), + server_settings.login_message.format(init_time) + ) + + self._logger.trace(__name__, f'Module {type(self)} stopped') \ No newline at end of file diff --git a/src/modules/boot_log/boot_log_extension.py b/src/modules/boot_log/boot_log_extension.py new file mode 100644 index 0000000..9d66642 --- /dev/null +++ b/src/modules/boot_log/boot_log_extension.py @@ -0,0 +1,17 @@ +from datetime import datetime + +from cpl_core.application.application_extension_abc import ApplicationExtensionABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_core.logging import LoggerABC + + +class BootLogExtension(ApplicationExtensionABC): + + def __init__(self): + pass + + async def run(self, config: ConfigurationABC, services: ServiceProviderABC): + logger: LoggerABC = services.get_service(LoggerABC) + logger.debug(__name__, 'BootLog extension started') + config.add_configuration('Bot_StartTime', datetime.now()) diff --git a/src/modules_core/__init__.py b/src/modules_core/__init__.py new file mode 100644 index 0000000..9086fbb --- /dev/null +++ b/src/modules_core/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +modules-core sh-edraft Gismo - Modules core +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - Modules core + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'modules_core' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/modules_core/abc/__init__.py b/src/modules_core/abc/__init__.py new file mode 100644 index 0000000..c345cc5 --- /dev/null +++ b/src/modules_core/abc/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +modules-core sh-edraft Gismo - Modules core +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - Modules core + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'modules_core.abc' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/modules_core/abc/events/on_bulk_message_delete_abc.py b/src/modules_core/abc/events/on_bulk_message_delete_abc.py new file mode 100644 index 0000000..15a19c6 --- /dev/null +++ b/src/modules_core/abc/events/on_bulk_message_delete_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnBulkMessageDeleteABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_bulk_message_delete(self, messages: list[discord.Message]): pass diff --git a/src/modules_core/abc/events/on_connect_abc.py b/src/modules_core/abc/events/on_connect_abc.py new file mode 100644 index 0000000..96d1909 --- /dev/null +++ b/src/modules_core/abc/events/on_connect_abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class OnConnectABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_connect(self): pass diff --git a/src/modules_core/abc/events/on_disconnect_abc.py b/src/modules_core/abc/events/on_disconnect_abc.py new file mode 100644 index 0000000..eb3be9a --- /dev/null +++ b/src/modules_core/abc/events/on_disconnect_abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class OnDisconnectABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_disconnect(self): pass \ No newline at end of file diff --git a/src/modules_core/abc/events/on_error_abc.py b/src/modules_core/abc/events/on_error_abc.py new file mode 100644 index 0000000..ff4badb --- /dev/null +++ b/src/modules_core/abc/events/on_error_abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class OnErrorABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_error(self, event: str, *args, **kwargs): pass \ No newline at end of file diff --git a/src/modules_core/abc/events/on_group_join_abc.py b/src/modules_core/abc/events/on_group_join_abc.py new file mode 100644 index 0000000..e0b3aaa --- /dev/null +++ b/src/modules_core/abc/events/on_group_join_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGroupJoinABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_group_join( + self, chhanel: discord.GroupChannel, user: discord.User): pass diff --git a/src/modules_core/abc/events/on_group_remove_abc.py b/src/modules_core/abc/events/on_group_remove_abc.py new file mode 100644 index 0000000..dc6fda8 --- /dev/null +++ b/src/modules_core/abc/events/on_group_remove_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + +class OnGroupRemoveABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_group_remove( + self, chhanel: discord.GroupChannel, user: discord.User): pass diff --git a/src/modules_core/abc/events/on_guild_available_abc.py b/src/modules_core/abc/events/on_guild_available_abc.py new file mode 100644 index 0000000..8b6eaa9 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_available_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildAvailableABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_available(self, guild: discord.Guild): pass diff --git a/src/modules_core/abc/events/on_guild_channel_create_abc.py b/src/modules_core/abc/events/on_guild_channel_create_abc.py new file mode 100644 index 0000000..3d36777 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_channel_create_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildChannelCreateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_channel_create(self, channel: discord.abc.GuildChannel): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_guild_channel_delete_abc.py b/src/modules_core/abc/events/on_guild_channel_delete_abc.py new file mode 100644 index 0000000..c34e7f1 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_channel_delete_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildChannelDeleteABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_channel_delete(self, channel: discord.abc.GuildChannel): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_guild_channel_pins_update_abc.py b/src/modules_core/abc/events/on_guild_channel_pins_update_abc.py new file mode 100644 index 0000000..3408e54 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_channel_pins_update_abc.py @@ -0,0 +1,14 @@ +from abc import ABC, abstractmethod +from datetime import datetime +from typing import Optional +import discord + + +class OnGuildChannelPinsUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_channel_pins_update(self, channel: discord.abc.GuildChannel, list_pin: Optional[datetime]): pass + diff --git a/src/modules_core/abc/events/on_guild_channel_update_abc.py b/src/modules_core/abc/events/on_guild_channel_update_abc.py new file mode 100644 index 0000000..17a8634 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_channel_update_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildChannelUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_channel_update(self, before: discord.abc.GuildChannel, after: discord.abc.GuildChannel): pass diff --git a/src/modules_core/abc/events/on_guild_emojis_update_abc.py b/src/modules_core/abc/events/on_guild_emojis_update_abc.py new file mode 100644 index 0000000..40a3247 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_emojis_update_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +from typing import Sequence +import discord + + +class OnGuildEmojisUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_emojis_update(self, guild: discord.Guild, before: Sequence[discord.Emoji], after: Sequence[discord.Emoji]): pass diff --git a/src/modules_core/abc/events/on_guild_integrations_update_abc.py b/src/modules_core/abc/events/on_guild_integrations_update_abc.py new file mode 100644 index 0000000..9e5f4f0 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_integrations_update_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildIntegrationsUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_integrations_update(self, guild: discord.Guild): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_guild_join_abc.py b/src/modules_core/abc/events/on_guild_join_abc.py new file mode 100644 index 0000000..c6e82f1 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_join_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildJoinABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_join(self, guild: discord.Guild): pass diff --git a/src/modules_core/abc/events/on_guild_remove_abc.py b/src/modules_core/abc/events/on_guild_remove_abc.py new file mode 100644 index 0000000..04f0e34 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_remove_abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildRemoveABC(ABC): + + @abstractmethod + def __init__(self): pass + @abstractmethod + async def on_guild_remove(self, guild: discord.Guild): pass diff --git a/src/modules_core/abc/events/on_guild_role_create_abc.py b/src/modules_core/abc/events/on_guild_role_create_abc.py new file mode 100644 index 0000000..f828988 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_role_create_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildRoleCreateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_role_create(self, role: discord.Role): pass diff --git a/src/modules_core/abc/events/on_guild_role_delete_abc.py b/src/modules_core/abc/events/on_guild_role_delete_abc.py new file mode 100644 index 0000000..a26bdd2 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_role_delete_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildRoleDeleteABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_role_delete(self, role: discord.Role): pass diff --git a/src/modules_core/abc/events/on_guild_role_update_abc.py b/src/modules_core/abc/events/on_guild_role_update_abc.py new file mode 100644 index 0000000..905efb5 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_role_update_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildRoleUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_role_update(self, before: discord.Role, after: discord.Role): pass diff --git a/src/modules_core/abc/events/on_guild_unavailable_abc.py b/src/modules_core/abc/events/on_guild_unavailable_abc.py new file mode 100644 index 0000000..5666407 --- /dev/null +++ b/src/modules_core/abc/events/on_guild_unavailable_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildUnavailableABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_unavailable(self, guild: discord.Guild): pass diff --git a/src/modules_core/abc/events/on_guild_update_abc.py b/src/modules_core/abc/events/on_guild_update_abc.py new file mode 100644 index 0000000..7ed4c1a --- /dev/null +++ b/src/modules_core/abc/events/on_guild_update_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnGuildUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_guild_update(self, before: discord.Guild, after: discord.Guild): pass diff --git a/src/modules_core/abc/events/on_invite_create_abc.py b/src/modules_core/abc/events/on_invite_create_abc.py new file mode 100644 index 0000000..ce4e2e0 --- /dev/null +++ b/src/modules_core/abc/events/on_invite_create_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnInviteCreateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_invite_create(self, invite: discord.Invite): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_invite_delete_abc.py b/src/modules_core/abc/events/on_invite_delete_abc.py new file mode 100644 index 0000000..bbd848c --- /dev/null +++ b/src/modules_core/abc/events/on_invite_delete_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnInviteDeleteABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_invite_delete(self, invite: discord.Invite): pass diff --git a/src/modules_core/abc/events/on_member_ban_abc.py b/src/modules_core/abc/events/on_member_ban_abc.py new file mode 100644 index 0000000..45e3f0d --- /dev/null +++ b/src/modules_core/abc/events/on_member_ban_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnMemberBanABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_member_ban(self, guild: discord.Guild, user: discord.User): pass diff --git a/src/modules_core/abc/events/on_member_join_abc.py b/src/modules_core/abc/events/on_member_join_abc.py new file mode 100644 index 0000000..51036e5 --- /dev/null +++ b/src/modules_core/abc/events/on_member_join_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnMemberJoinABC(ABC): + + @abstractmethod + def __init__(self): pass + + + @abstractmethod + async def on_member_join(self, member: discord.Member): pass diff --git a/src/modules_core/abc/events/on_member_remove_abc.py b/src/modules_core/abc/events/on_member_remove_abc.py new file mode 100644 index 0000000..b24f3d5 --- /dev/null +++ b/src/modules_core/abc/events/on_member_remove_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnMemberRemoveABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_member_remove(self, member: discord.Member): pass diff --git a/src/modules_core/abc/events/on_member_unban_abc.py b/src/modules_core/abc/events/on_member_unban_abc.py new file mode 100644 index 0000000..c5bbb8c --- /dev/null +++ b/src/modules_core/abc/events/on_member_unban_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnMemberUnbanABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_member_unban(self, guild: discord.Guild, user: discord.User): pass diff --git a/src/modules_core/abc/events/on_member_update_abc.py b/src/modules_core/abc/events/on_member_update_abc.py new file mode 100644 index 0000000..6ca11df --- /dev/null +++ b/src/modules_core/abc/events/on_member_update_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnMemberUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_member_update(self, before: discord.Member, after: discord.Member): pass diff --git a/src/modules_core/abc/events/on_message_abc.py b/src/modules_core/abc/events/on_message_abc.py new file mode 100644 index 0000000..08e3816 --- /dev/null +++ b/src/modules_core/abc/events/on_message_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnMessageABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_message(self, message: discord.Message): pass diff --git a/src/modules_core/abc/events/on_message_delete_abc.py b/src/modules_core/abc/events/on_message_delete_abc.py new file mode 100644 index 0000000..57cf30e --- /dev/null +++ b/src/modules_core/abc/events/on_message_delete_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnMessageDeleteABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_message_delete(self, message: discord.Message): pass \ No newline at end of file diff --git a/src/modules_core/abc/events/on_message_edit_abc.py b/src/modules_core/abc/events/on_message_edit_abc.py new file mode 100644 index 0000000..b8d4df8 --- /dev/null +++ b/src/modules_core/abc/events/on_message_edit_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnMessageEditABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_message_edit(self, before: discord.Message, after: discord.Message): pass diff --git a/src/modules_core/abc/events/on_private_channel_create_abc.py b/src/modules_core/abc/events/on_private_channel_create_abc.py new file mode 100644 index 0000000..371ccaf --- /dev/null +++ b/src/modules_core/abc/events/on_private_channel_create_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnPrivateChannelCreateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_private_channel_create(self, channel: discord.abc.PrivateChannel): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_private_channel_delete_abc.py b/src/modules_core/abc/events/on_private_channel_delete_abc.py new file mode 100644 index 0000000..0e6f775 --- /dev/null +++ b/src/modules_core/abc/events/on_private_channel_delete_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnPrivateChannelDeleteABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_private_channel_delete(self, channel: discord.abc.PrivateChannel): pass + diff --git a/src/modules_core/abc/events/on_private_channel_pins_update_abc.py b/src/modules_core/abc/events/on_private_channel_pins_update_abc.py new file mode 100644 index 0000000..4634b87 --- /dev/null +++ b/src/modules_core/abc/events/on_private_channel_pins_update_abc.py @@ -0,0 +1,14 @@ +from abc import ABC, abstractmethod +from datetime import datetime +from typing import Optional +import discord + + +class OnPrivateChannelPinsUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_private_channel_pins_update(self, channel: discord.abc.PrivateChannel, list_pin: Optional[datetime]): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_private_channel_update_abc.py b/src/modules_core/abc/events/on_private_channel_update_abc.py new file mode 100644 index 0000000..6c37031 --- /dev/null +++ b/src/modules_core/abc/events/on_private_channel_update_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnPrivateChannelUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_private_channel_update(self, before: discord.GroupChannel, after: discord.GroupChannel): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_reaction_add_abc.py b/src/modules_core/abc/events/on_reaction_add_abc.py new file mode 100644 index 0000000..c168222 --- /dev/null +++ b/src/modules_core/abc/events/on_reaction_add_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnReactionAddABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_reaction_clear_abc.py b/src/modules_core/abc/events/on_reaction_clear_abc.py new file mode 100644 index 0000000..7d2ef66 --- /dev/null +++ b/src/modules_core/abc/events/on_reaction_clear_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnReactionClearABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_reaction_clear(self, message: discord.Message, reactions: list[discord.Reaction]): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_reaction_clear_emoji_abc.py b/src/modules_core/abc/events/on_reaction_clear_emoji_abc.py new file mode 100644 index 0000000..1e683eb --- /dev/null +++ b/src/modules_core/abc/events/on_reaction_clear_emoji_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnReactionClearEmojiABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_reaction_clear_emoji(self, reaction: discord.Reaction): pass + diff --git a/src/modules_core/abc/events/on_reaction_remove_abc.py b/src/modules_core/abc/events/on_reaction_remove_abc.py new file mode 100644 index 0000000..6dc34d1 --- /dev/null +++ b/src/modules_core/abc/events/on_reaction_remove_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnReactionRemoveABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_reaction_remove(self, reaction: discord.Reaction, user: discord.User): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_ready_abc.py b/src/modules_core/abc/events/on_ready_abc.py new file mode 100644 index 0000000..053bf79 --- /dev/null +++ b/src/modules_core/abc/events/on_ready_abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class OnReadyABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_ready(self): pass diff --git a/src/modules_core/abc/events/on_relationship_add_abc.py b/src/modules_core/abc/events/on_relationship_add_abc.py new file mode 100644 index 0000000..5cba49a --- /dev/null +++ b/src/modules_core/abc/events/on_relationship_add_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + +class OnRelationshipAddABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_relationship_add(self, relationship: discord.Relationship): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_relationship_remove_abc.py b/src/modules_core/abc/events/on_relationship_remove_abc.py new file mode 100644 index 0000000..c842a4a --- /dev/null +++ b/src/modules_core/abc/events/on_relationship_remove_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + +class OnRelationshipRemoveABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_relationship_remove(self, relationship: discord.Relationship): pass + \ No newline at end of file diff --git a/src/modules_core/abc/events/on_relationship_update_abc.py b/src/modules_core/abc/events/on_relationship_update_abc.py new file mode 100644 index 0000000..4d97091 --- /dev/null +++ b/src/modules_core/abc/events/on_relationship_update_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnRelationshipUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_relationship_update( + self, before: discord.Relationship, after: discord.Relationship): pass diff --git a/src/modules_core/abc/events/on_resume_abc.py b/src/modules_core/abc/events/on_resume_abc.py new file mode 100644 index 0000000..28e63f9 --- /dev/null +++ b/src/modules_core/abc/events/on_resume_abc.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + + +class OnResumeABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_resume(self): pass \ No newline at end of file diff --git a/src/modules_core/abc/events/on_typing_abc.py b/src/modules_core/abc/events/on_typing_abc.py new file mode 100644 index 0000000..76b89a0 --- /dev/null +++ b/src/modules_core/abc/events/on_typing_abc.py @@ -0,0 +1,13 @@ +from abc import ABC, abstractmethod +from datetime import datetime +from typing import Union +import discord + + +class OnTypingABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_typing(self, channel: discord.abc.Messageable, user: Union[discord.User, discord.Member], when: datetime): pass diff --git a/src/modules_core/abc/events/on_user_update_abc.py b/src/modules_core/abc/events/on_user_update_abc.py new file mode 100644 index 0000000..0a9b7c9 --- /dev/null +++ b/src/modules_core/abc/events/on_user_update_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnUserUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_user_update(self, before: discord.User, after: discord.User): pass diff --git a/src/modules_core/abc/events/on_voice_state_update_abc.py b/src/modules_core/abc/events/on_voice_state_update_abc.py new file mode 100644 index 0000000..60d586f --- /dev/null +++ b/src/modules_core/abc/events/on_voice_state_update_abc.py @@ -0,0 +1,11 @@ +from abc import ABC, abstractmethod +import discord + + +class OnVoiceStateUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState,after: discord.VoiceState): pass diff --git a/src/modules_core/abc/events/on_webhooks_update_abc.py b/src/modules_core/abc/events/on_webhooks_update_abc.py new file mode 100644 index 0000000..db92f58 --- /dev/null +++ b/src/modules_core/abc/events/on_webhooks_update_abc.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +import discord + + +class OnWebhooksUpdateABC(ABC): + + @abstractmethod + def __init__(self): pass + + + @abstractmethod + async def on_webhooks_update(self, channel: discord.abc.GuildChannel): pass diff --git a/src/modules_core/abc/module_abc.py b/src/modules_core/abc/module_abc.py new file mode 100644 index 0000000..d860319 --- /dev/null +++ b/src/modules_core/abc/module_abc.py @@ -0,0 +1,21 @@ +from abc import ABC, abstractmethod + + +class ModuleABC(ABC): + + @abstractmethod + def __init__(self): + self._priorities = {} + self._success = True + + def get_priority(self, t: type) -> int: + if t not in self._priorities: + raise Exception(f'Priority for {t} not found!') + return self._priorities[t] + + def stop_propagation(self): + self._success = False + + @property + def success(self) -> bool: + return self._success diff --git a/src/modules_core/abc/module_service_abc.py b/src/modules_core/abc/module_service_abc.py new file mode 100644 index 0000000..407868a --- /dev/null +++ b/src/modules_core/abc/module_service_abc.py @@ -0,0 +1,152 @@ +from abc import ABC, abstractmethod +from datetime import datetime +from typing import Optional, Sequence, Union + +import discord + + +class ModuleServiceABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + async def on_connect(self): pass + + @abstractmethod + async def on_disconnect(self): pass + + @abstractmethod + async def on_ready(self): pass + + @abstractmethod + async def on_resume(self): pass + + @abstractmethod + async def on_error(self, event: str, *args, **kwargs): pass + + @abstractmethod + async def on_typing(self, channel: discord.abc.Messageable, user: Union[discord.User, discord.Member], when: datetime): pass + + @abstractmethod + async def on_message(self, message: discord.Message): pass + + @abstractmethod + async def on_message_delete(self, message: discord.Message): pass + + @abstractmethod + async def on_bulk_message_delete(self, messages: list[discord.Message]): pass + + @abstractmethod + async def on_message_edit(self, before: discord.Message, after: discord.Message): pass + + @abstractmethod + async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User): pass + + @abstractmethod + async def on_reaction_remove(self, reaction: discord.Reaction, user: discord.User): pass + + @abstractmethod + async def on_reaction_clear(self, message: discord.Message, reactions: list[discord.Reaction]): pass + + @abstractmethod + async def on_reaction_clear_emoji(self, reaction: discord.Reaction): pass + + @abstractmethod + async def on_private_channel_delete(self, channel: discord.abc.PrivateChannel): pass + + @abstractmethod + async def on_private_channel_create(self, channel: discord.abc.PrivateChannel): pass + + @abstractmethod + async def on_private_channel_update(self, before: discord.GroupChannel, after: discord.GroupChannel): pass + + @abstractmethod + async def on_private_channel_pins_update(self, channel: discord.abc.PrivateChannel, list_pin: Optional[datetime]): pass + + @abstractmethod + async def on_guild_channel_delete(self, channel: discord.abc.GuildChannel): pass + + @abstractmethod + async def on_guild_channel_create(self, channel: discord.abc.GuildChannel): pass + + @abstractmethod + async def on_guild_channel_update(self, before: discord.abc.GuildChannel, after: discord.abc.GuildChannel): pass + + @abstractmethod + async def on_guild_channel_pins_update(self, channel: discord.abc.GuildChannel, list_pin: Optional[datetime]): pass + + @abstractmethod + async def on_guild_integrations_update(self, guild: discord.Guild): pass + + @abstractmethod + async def on_webhooks_update(self, channel: discord.abc.GuildChannel): pass + + @abstractmethod + async def on_member_join(self, member: discord.Member): pass + + @abstractmethod + async def on_member_remove(self, member: discord.Member): pass + + @abstractmethod + async def on_member_update(self, before: discord.Member, after: discord.Member): pass + + @abstractmethod + async def on_user_update(self, before: discord.User, after: discord.User): pass + + @abstractmethod + async def on_guild_join(self, guild: discord.Guild): pass + + @abstractmethod + async def on_guild_remove(self, guild: discord.Guild): pass + + @abstractmethod + async def on_guild_update(self, before: discord.Guild, after: discord.Guild): pass + + @abstractmethod + async def on_guild_role_create(self, role: discord.Role): pass + + @abstractmethod + async def on_guild_role_delete(self, role: discord.Role): pass + + @abstractmethod + async def on_guild_role_update(self, before: discord.Role, after: discord.Role): pass + + @abstractmethod + async def on_guild_emojis_update(self, guild: discord.Guild, before: Sequence[discord.Emoji], after: Sequence[discord.Emoji]): pass + + @abstractmethod + async def on_guild_available(self, guild: discord.Guild): pass + + @abstractmethod + async def on_guild_unavailable(self, guild: discord.Guild): pass + + @abstractmethod + async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState,after: discord.VoiceState): pass + + @abstractmethod + async def on_member_ban(self, guild: discord.Guild, user: discord.User): pass + + @abstractmethod + async def on_member_unban(self, guild: discord.Guild, user: discord.User): pass + + @abstractmethod + async def on_invite_create(self, invite: discord.Invite): pass + + @abstractmethod + async def on_invite_delete(self, invite: discord.Invite): pass + + @abstractmethod + async def on_group_join(self, chhanel: discord.GroupChannel, user: discord.User): pass + + @abstractmethod + async def on_group_remove(self, chhanel: discord.GroupChannel, user: discord.User): pass + + @abstractmethod + async def on_relationship_add(self, relationship: discord.Relationship): pass + + @abstractmethod + async def on_relationship_remove(self, relationship: discord.Relationship): pass + + @abstractmethod + async def on_relationship_update(self, before: discord.Relationship, after: discord.Relationship): pass diff --git a/src/modules_core/events_enum.py b/src/modules_core/events_enum.py new file mode 100644 index 0000000..fafe57e --- /dev/null +++ b/src/modules_core/events_enum.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class EventsEnum(Enum): + + on_ready = 'on_ready' diff --git a/src/modules_core/modules-core.json b/src/modules_core/modules-core.json new file mode 100644 index 0000000..b1e991d --- /dev/null +++ b/src/modules_core/modules-core.json @@ -0,0 +1,44 @@ +{ + "ProjectSettings": { + "Name": "modules-core", + "Version": { + "Major": "0", + "Minor": "1", + "Micro": "0" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "sh-edraft Gismo - Modules core", + "LongDescription": "sh-edraft Dicord bot Gismo - Modules core", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2021 - 2022", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "sh_cpl-core>=2021.10.2", + "sh_cpl-query>=2021.10.2" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "../../venv/bin/python" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "modules_core.main", + "EntryPoint": "modules-core", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/src/modules_core/service/__init__.py b/src/modules_core/service/__init__.py new file mode 100644 index 0000000..6d10b94 --- /dev/null +++ b/src/modules_core/service/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +""" +modules-core sh-edraft Gismo - Modules core +~~~~~~~~~~~~~~~~~~~ + +sh-edraft Dicord bot Gismo - Modules core + +:copyright: (c) 2021 - 2022 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'modules_core.service' +__author__ = 'Sven Heidemann' +__license__ = 'MIT' +__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' +__version__ = '0.1.0' + +from collections import namedtuple + +# imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='1', micro='0') diff --git a/src/modules_core/service/module_service.py b/src/modules_core/service/module_service.py new file mode 100644 index 0000000..db61fbc --- /dev/null +++ b/src/modules_core/service/module_service.py @@ -0,0 +1,332 @@ +from abc import ABC, ABCMeta +from datetime import datetime +from typing import Optional, Sequence, Union + +import discord +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_core.environment import ApplicationEnvironmentABC +from cpl_core.logging import LoggerABC +from cpl_core.utils import String +from cpl_query.extension import List +from discord.ext import commands +from modules_core.abc.events.on_bulk_message_delete_abc import OnBulkMessageDeleteABC +from modules_core.abc.events.on_connect_abc import OnConnectABC +from modules_core.abc.events.on_disconnect_abc import OnDisconnectABC +from modules_core.abc.events.on_group_join_abc import OnGroupJoinABC +from modules_core.abc.events.on_group_remove_abc import OnGroupRemoveABC +from modules_core.abc.events.on_guild_available_abc import OnGuildAvailableABC +from modules_core.abc.events.on_guild_channel_create_abc import OnGuildChannelCreateABC +from modules_core.abc.events.on_guild_channel_delete_abc import OnGuildChannelDeleteABC +from modules_core.abc.events.on_guild_channel_pins_update_abc import OnGuildChannelPinsUpdateABC +from modules_core.abc.events.on_guild_channel_update_abc import OnGuildChannelUpdateABC +from modules_core.abc.events.on_guild_emojis_update_abc import OnGuildEmojisUpdateABC +from modules_core.abc.events.on_guild_integrations_update_abc import OnGuildIntegrationsUpdateABC +from modules_core.abc.events.on_guild_join_abc import OnGuildJoinABC +from modules_core.abc.events.on_guild_remove_abc import OnGuildRemoveABC +from modules_core.abc.events.on_guild_role_create_abc import OnGuildRoleCreateABC +from modules_core.abc.events.on_guild_role_delete_abc import OnGuildRoleDeleteABC +from modules_core.abc.events.on_guild_role_update_abc import OnGuildRoleUpdateABC +from modules_core.abc.events.on_guild_unavailable_abc import OnGuildUnavailableABC +from modules_core.abc.events.on_guild_update_abc import OnGuildUpdateABC +from modules_core.abc.events.on_invite_create_abc import OnInviteCreateABC +from modules_core.abc.events.on_invite_delete_abc import OnInviteDeleteABC +from modules_core.abc.events.on_member_ban_abc import OnMemberBanABC +from modules_core.abc.events.on_member_join_abc import OnMemberJoinABC +from modules_core.abc.events.on_member_remove_abc import OnMemberRemoveABC +from modules_core.abc.events.on_member_unban_abc import OnMemberUnbanABC +from modules_core.abc.events.on_member_update_abc import OnMemberUpdateABC +from modules_core.abc.events.on_message_abc import OnMessageABC +from modules_core.abc.events.on_message_delete_abc import OnMessageDeleteABC +from modules_core.abc.events.on_message_edit_abc import OnMessageEditABC +from modules_core.abc.events.on_private_channel_create_abc import OnPrivateChannelCreateABC +from modules_core.abc.events.on_private_channel_delete_abc import OnPrivateChannelDeleteABC +from modules_core.abc.events.on_private_channel_pins_update_abc import OnPrivateChannelPinsUpdateABC +from modules_core.abc.events.on_private_channel_update_abc import OnPrivateChannelUpdateABC +from modules_core.abc.events.on_reaction_add_abc import OnReactionAddABC +from modules_core.abc.events.on_reaction_clear_abc import OnReactionClearABC +from modules_core.abc.events.on_reaction_clear_emoji_abc import OnReactionClearEmojiABC +from modules_core.abc.events.on_reaction_remove_abc import OnReactionRemoveABC +from modules_core.abc.events.on_ready_abc import OnReadyABC +from modules_core.abc.events.on_relationship_add_abc import OnRelationshipAddABC +from modules_core.abc.events.on_relationship_remove_abc import OnRelationshipRemoveABC +from modules_core.abc.events.on_relationship_update_abc import OnRelationshipUpdateABC +from modules_core.abc.events.on_resume_abc import OnResumeABC +from modules_core.abc.events.on_typing_abc import OnTypingABC +from modules_core.abc.events.on_user_update_abc import OnUserUpdateABC +from modules_core.abc.events.on_voice_state_update_abc import OnVoiceStateUpdateABC +from modules_core.abc.events.on_webhooks_update_abc import OnWebhooksUpdateABC +from modules_core.abc.module_abc import ModuleABC +from modules_core.abc.module_service_abc import ModuleServiceABC + + +class _MetaCogABC(ABCMeta, commands.CogMeta): pass + + +class ModuleService(ModuleServiceABC, commands.Cog, metaclass=_MetaCogABC): + + def __init__(self, logger: LoggerABC, services: ServiceProviderABC, env: ApplicationEnvironmentABC): + self._logger = logger + self._services = services + self._env = env + self._modules: List[ModuleABC] = List() + self._modules.extend(ModuleABC.__subclasses__()) + + def _get_modules(self, t: type) -> List[ModuleABC]: + module_types = self._modules.where(lambda m: issubclass(m, t)) + modules = List(t) + for module_type in module_types: + modules.append(self._services.get_service(module_type)) + + return modules.order_by(lambda m: m.get_priority(t)) + + async def _handle_event(self, event: type, *args): + self._logger.debug(__name__, f'Start {event} modules') + modules = self._get_modules(event) + + if modules.count() < 1: + self._logger.debug(__name__, f'Stopped {event} modules') + return + + func_name = String.convert_to_snake_case(event.__name__.split('ABC')[0]) + for module in modules: + func = getattr(module, func_name) + await func(*args) + if not module.success: + self._logger.debug(__name__, f'Stopped propagation for {event} from {type(module)}') + break + + self._logger.debug(__name__, f'Stopped {event} modules') + + @commands.Cog.listener() + async def on_connect(self): + self._logger.trace(__name__, f'Received on_connect') + await self._handle_event(OnConnectABC) + + @commands.Cog.listener() + async def on_disconnect(self): + self._logger.trace(__name__, f'Received on_disconnect') + await self._handle_event(OnDisconnectABC) + + async def on_ready(self): + self._logger.trace(__name__, f'Received on_ready') + await self._handle_event(OnReadyABC) + + @commands.Cog.listener() + async def on_resume(self): + self._logger.trace(__name__, f'Received on_resume') + await self._handle_event(OnResumeABC) + + @commands.Cog.listener() + async def on_error(self, event: str, *args, **kwargs): + self._logger.trace(__name__, f'Received on_error:\n\t{event}\n\t{args}\n\t{kwargs}') + await self._handle_event(OnReadyABC, event, *args, **kwargs) + + @commands.Cog.listener() + async def on_typing(self, channel: discord.abc.Messageable, user: Union[discord.User, discord.Member], when: datetime): + self._logger.trace(__name__, f'Received on_typing:\n\t{channel}\n\t{user}\n\t{when}') + await self._handle_event(OnTypingABC, channel, user, when) + + @commands.Cog.listener() + async def on_message(self, message: discord.Message): + self._logger.trace(__name__, f'Received on_message:\n\t{message}\n\t{message.content}') + await self._handle_event(OnMessageABC, message) + + @commands.Cog.listener() + async def on_message_delete(self, message: discord.Message): + self._logger.trace(__name__, f'Received on_message_delete:\n\t{message}\n\t{message.content}') + await self._handle_event(OnMessageDeleteABC, message) + + @commands.Cog.listener() + async def on_bulk_message_delete(self, messages: list[discord.Message]): + self._logger.trace(__name__, f'Received on_bulk_message_delete:\n\t{len(messages)}') + await self._handle_event(OnBulkMessageDeleteABC, messages) + + @commands.Cog.listener() + async def on_message_edit(self, before: discord.Message, after: discord.Message): + self._logger.trace(__name__, f'Received on_message_edit:\n\t{before}\n\t{after}') + await self._handle_event(OnMessageEditABC, before, after) + + @commands.Cog.listener() + async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User): + self._logger.trace(__name__, f'Received on_reaction_add:\n\t{reaction}\n\t{user}') + await self._handle_event(OnReactionAddABC, reaction, user) + + @commands.Cog.listener() + async def on_reaction_remove(self, reaction: discord.Reaction, user: discord.User): + self._logger.trace(__name__, f'Received on_reaction_remove:\n\t{reaction}\n\t{user}') + await self._handle_event(OnReactionRemoveABC, reaction, user) + + @commands.Cog.listener() + async def on_reaction_clear(self, message: discord.Message, reactions: list[discord.Reaction]): + self._logger.trace(__name__, f'Received on_reaction_reon_reaction_clearmove:\n\t{message}\n\t{len(reactions)}') + await self._handle_event(OnReactionClearABC, message, reactions) + + @commands.Cog.listener() + async def on_reaction_clear_emoji(self, reaction: discord.Reaction): + self._logger.trace(__name__, f'Received on_reaction_clear_emoji:\n\t{reaction}') + await self._handle_event(OnReactionClearEmojiABC, reaction) + + @commands.Cog.listener() + async def on_private_channel_delete(self, channel: discord.abc.PrivateChannel): + self._logger.trace(__name__, f'Received on_private_channel_delete:\n\t{channel}') + await self._handle_event(OnPrivateChannelDeleteABC, channel) + + @commands.Cog.listener() + async def on_private_channel_create(self, channel: discord.abc.PrivateChannel): + self._logger.trace(__name__, f'Received on_private_channel_create:\n\t{channel}') + await self._handle_event(OnPrivateChannelCreateABC, channel) + + @commands.Cog.listener() + async def on_private_channel_update(self, before: discord.GroupChannel, after: discord.GroupChannel): + self._logger.trace(__name__, f'Received on_private_channel_update:\n\t{before}\n\t{after}') + await self._handle_event(OnPrivateChannelUpdateABC, before, after) + + @commands.Cog.listener() + async def on_private_channel_pins_update(self, channel: discord.abc.PrivateChannel, list_pin: Optional[datetime]): + self._logger.trace(__name__, f'Received on_private_channel_pins_update:\n\t{channel}\n\t{list_pin}') + await self._handle_event(OnPrivateChannelPinsUpdateABC, channel, list_pin) + + @commands.Cog.listener() + async def on_guild_channel_delete(self, channel: discord.abc.GuildChannel): + self._logger.trace(__name__, f'Received on_guild_channel_delete:\n\t{channel}') + await self._handle_event(OnGuildChannelDeleteABC, channel) + + @commands.Cog.listener() + async def on_guild_channel_create(self, channel: discord.abc.GuildChannel): + self._logger.trace(__name__, f'Received on_guild_channel_create:\n\t{channel}') + await self._handle_event(OnGuildChannelCreateABC, channel) + + @commands.Cog.listener() + async def on_guild_channel_update(self, before: discord.abc.GuildChannel, after: discord.abc.GuildChannel): + self._logger.trace(__name__, f'Received on_guild_channel_update:\n\t{before}\n\t{after}') + await self._handle_event(OnGuildChannelUpdateABC, before, after) + + @commands.Cog.listener() + async def on_guild_channel_pins_update(self, channel: discord.abc.GuildChannel, list_pin: Optional[datetime]): + self._logger.trace(__name__, f'Received on_guild_channel_pins_update:\n\t{channel}\n\t{list_pin}') + await self._handle_event(OnGuildChannelPinsUpdateABC, channel, list_pin) + + @commands.Cog.listener() + async def on_guild_integrations_update(self, guild: discord.Guild): + self._logger.trace(__name__, f'Received on_guild_integrations_update:\n\t{guild}') + await self._handle_event(OnGuildIntegrationsUpdateABC, guild) + + @commands.Cog.listener() + async def on_webhooks_update(self, channel: discord.abc.GuildChannel): + self._logger.trace(__name__, f'Received on_webhooks_update:\n\t{channel}') + await self._handle_event(OnWebhooksUpdateABC, channel) + + @commands.Cog.listener() + async def on_member_join(self, member: discord.Member): + self._logger.trace(__name__, f'Received on_member_join:\n\t{member}') + await self._handle_event(OnMemberJoinABC, member) + + @commands.Cog.listener() + async def on_member_remove(self, member: discord.Member): + self._logger.trace(__name__, f'Received on_member_remove:\n\t{member}') + await self._handle_event(OnMemberRemoveABC, member) + + @commands.Cog.listener() + async def on_member_update(self, before: discord.Member, after: discord.Member): + self._logger.trace(__name__, f'Received on_member_update:\n\t{before}\n\t{after}') + await self._handle_event(OnMemberUpdateABC, before, after) + + @commands.Cog.listener() + async def on_user_update(self, before: discord.User, after: discord.User): + self._logger.trace(__name__, f'Received on_user_update:\n\t{before}\n\t{after}') + await self._handle_event(OnUserUpdateABC, before, after) + + @commands.Cog.listener() + async def on_guild_join(self, guild: discord.Guild): + self._logger.trace(__name__, f'Received on_guild_join:\n\t{guild}') + await self._handle_event(OnGuildJoinABC, guild) + + @commands.Cog.listener() + async def on_guild_remove(self, guild: discord.Guild): + self._logger.trace(__name__, f'Received on_guild_remove:\n\t{guild}') + await self._handle_event(OnGuildRemoveABC, guild) + + @commands.Cog.listener() + async def on_guild_update(self, before: discord.Guild, after: discord.Guild): + self._logger.trace(__name__, f'Received on_guild_update:\n\t{before}\n\t{after}') + await self._handle_event(OnGuildUpdateABC, before, after) + + @commands.Cog.listener() + async def on_guild_role_create(self, role: discord.Role): + self._logger.trace(__name__, f'Received on_guild_role_create:\n\t{role}') + await self._handle_event(OnGuildRoleCreateABC, role) + + @commands.Cog.listener() + async def on_guild_role_delete(self, role: discord.Role): + self._logger.trace(__name__, f'Received on_guild_role_delete:\n\t{role}') + await self._handle_event(OnGuildRoleDeleteABC, role) + + @commands.Cog.listener() + async def on_guild_role_update(self, before: discord.Role, after: discord.Role): + self._logger.trace(__name__, f'Received on_guild_role_update:\n\t{before}\n\t{after}') + await self._handle_event(OnGuildRoleUpdateABC, before, after) + + @commands.Cog.listener() + async def on_guild_emojis_update(self, guild: discord.Guild, before: Sequence[discord.Emoji], after: Sequence[discord.Emoji]): + self._logger.trace(__name__, f'Received on_guild_emojis_update:\n\t{guild}\n\t{before}\n\t{after}') + await self._handle_event(OnGuildEmojisUpdateABC, guild, before, after) + + @commands.Cog.listener() + async def on_guild_available(self, guild: discord.Guild): + self._logger.trace(__name__, f'Received on_guild_available:\n\t{guild}') + await self._handle_event(OnGuildAvailableABC, guild) + + @commands.Cog.listener() + async def on_guild_unavailable(self, guild: discord.Guild): + self._logger.trace(__name__, f'Received on_guild_unavailable:\n\t{guild}') + await self._handle_event(OnGuildUnavailableABC, guild) + + @commands.Cog.listener() + async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): + self._logger.trace(__name__, f'Received on_voice_state_update:\n\t{member}\n\t{before}\n\t{after}') + await self._handle_event(OnVoiceStateUpdateABC, member, before, after) + + @commands.Cog.listener() + async def on_member_ban(self, guild: discord.Guild, user: discord.User): + self._logger.trace(__name__, f'Received on_member_ban:\n\t{guild}\n\t{user}') + await self._handle_event(OnMemberBanABC, guild, user) + + @commands.Cog.listener() + async def on_member_unban(self, guild: discord.Guild, user: discord.User): + self._logger.trace(__name__, f'Received on_member_unban:\n\t{guild}\n\t{user}') + await self._handle_event(OnMemberUnbanABC, guild, user) + + @commands.Cog.listener() + async def on_invite_create(self, invite: discord.Invite): + self._logger.trace(__name__, f'Received on_invite_create:\n\t{invite}') + await self._handle_event(OnInviteCreateABC, invite) + + @commands.Cog.listener() + async def on_invite_delete(self, invite: discord.Invite): + self._logger.trace(__name__, f'Received on_invite_create:\n\t{invite}') + await self._handle_event(OnInviteDeleteABC, invite) + + @commands.Cog.listener() + async def on_group_join(self, channel: discord.GroupChannel, user: discord.User): + self._logger.trace(__name__, f'Received on_group_join:\n\t{channel}\n\t{user}') + await self._handle_event(OnGroupJoinABC, channel, user) + + @commands.Cog.listener() + async def on_group_remove(self, channel: discord.GroupChannel, user: discord.User): + self._logger.trace(__name__, f'Received on_group_remove:\n\t{channel}\n\t{user}') + await self._handle_event(OnGroupRemoveABC, channel, user) + + @commands.Cog.listener() + async def on_relationship_add(self, relationship: discord.Relationship): + self._logger.trace(__name__, f'Received on_relationship_add:\n\t{relationship}') + await self._handle_event(OnRelationshipAddABC, relationship) + + @commands.Cog.listener() + async def on_relationship_remove(self, relationship: discord.Relationship): + self._logger.trace(__name__, f'Received on_relationship_remove:\n\t{relationship}') + await self._handle_event(OnRelationshipRemoveABC, relationship) + + @commands.Cog.listener() + async def on_relationship_update(self, before: discord.Relationship, after: discord.Relationship): + self._logger.trace(__name__, f'Received on_relationship_update:\n\t{before}\n\t{after}') + await self._handle_event(OnRelationshipUpdateABC, before, after) diff --git a/tools/level_generator/__init__.py b/tools/level_generator/__init__.py new file mode 100644 index 0000000..ad5eca3 --- /dev/null +++ b/tools/level_generator/__init__.py @@ -0,0 +1 @@ +# imports: diff --git a/tools/level_generator/application.py b/tools/level_generator/application.py new file mode 100644 index 0000000..6f142b5 --- /dev/null +++ b/tools/level_generator/application.py @@ -0,0 +1,56 @@ +import json + +from cpl_core.application import ApplicationABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.console import Console +from cpl_core.dependency_injection import ServiceProviderABC + + +class Application(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + + def configure(self): + pass + + def main(self): + f = open("./Levels.txt", "r", encoding='utf-8') + i = 0 + lines = f.readlines() + json_list = [] + + for line in lines: + if i > 0: + line = line.split('\n')[0] + words = line.split(' ') + use_words = [] + for word in words: + if word != '': + use_words.append(word) + + if len(use_words) == 6: + string = use_words[2] + use_words.remove(use_words[2]) + use_words[1] += f' {string}' + + loc_json = { + "id": int(use_words[0]), + "alias": use_words[1], + "min_ontime": int(use_words[2]), + "min_message_count": int(use_words[3]), + "color": use_words[4], + "hoist": "False", + "mentionable": "True", + "PermissionBagId": 0 + } + json_list.append(loc_json) + + i += 1 + + f.close() + + Console.write_line(json_list) + json_format = json.dumps(json_list, ensure_ascii=False) + with open("../src/sh_dobby_bot/assets/Level.json", "w", encoding='utf-8') as outfile: + outfile.write(json_format) diff --git a/tools/level_generator/level-generator.json b/tools/level_generator/level-generator.json new file mode 100644 index 0000000..4fcdfe9 --- /dev/null +++ b/tools/level_generator/level-generator.json @@ -0,0 +1,43 @@ +{ + "ProjectSettings": { + "Name": "tools/level-generator", + "Version": { + "Major": "0", + "Minor": "0", + "Micro": "0" + }, + "Author": "", + "AuthorEmail": "", + "Description": "", + "LongDescription": "", + "URL": "", + "CopyrightDate": "", + "CopyrightName": "", + "LicenseName": "", + "LicenseDescription": "", + "Dependencies": [ + "sh_cpl>=2021.10.2" + ], + "PythonVersion": ">=3.9.2", + "PythonPath": { + "linux": "" + }, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "console", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "tools/_level_generator.main", + "EntryPoint": "tools/level-generator", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/tools/level_generator/main.py b/tools/level_generator/main.py new file mode 100644 index 0000000..49614d1 --- /dev/null +++ b/tools/level_generator/main.py @@ -0,0 +1,14 @@ +from cpl_core.application import ApplicationBuilder + +from level_generator.application import Application +from level_generator.startup import Startup + + +def main(): + app_builder = ApplicationBuilder(Application) + app_builder.use_startup(Startup) + app_builder.build().run() + + +if __name__ == '__main__': + main() diff --git a/tools/level_generator/startup.py b/tools/level_generator/startup.py new file mode 100644 index 0000000..359c03d --- /dev/null +++ b/tools/level_generator/startup.py @@ -0,0 +1,16 @@ +from cpl_core.application import StartupABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironment + + +class Startup(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + + def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + return configuration + + def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + return services.build_service_provider() diff --git a/tools/ontime_calculator/__init__.py b/tools/ontime_calculator/__init__.py new file mode 100644 index 0000000..ad5eca3 --- /dev/null +++ b/tools/ontime_calculator/__init__.py @@ -0,0 +1 @@ +# imports: diff --git a/tools/ontime_calculator/application.py b/tools/ontime_calculator/application.py new file mode 100644 index 0000000..c860ec2 --- /dev/null +++ b/tools/ontime_calculator/application.py @@ -0,0 +1,25 @@ +from cpl_core.application import ApplicationABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.console import Console +from cpl_core.dependency_injection import ServiceProviderABC + + +class Application(ApplicationABC): + + def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): + ApplicationABC.__init__(self, config, services) + + def configure(self): + pass + + def main(self): + ontime = 0 + mc = 0 + for i in range(0, 31): + Console.write_line(f'i: {i} {ontime} {mc}') + if i == 0: + ontime = 4 + mc = 10 + else: + ontime = round((ontime * 1.2561), 0) + mc = round((mc * 1.26), 0) diff --git a/tools/ontime_calculator/main.py b/tools/ontime_calculator/main.py new file mode 100644 index 0000000..0fffb04 --- /dev/null +++ b/tools/ontime_calculator/main.py @@ -0,0 +1,14 @@ +from cpl_core.application import ApplicationBuilder + +from ontime_calculator.application import Application +from ontime_calculator.startup import Startup + + +def main(): + app_builder = ApplicationBuilder(Application) + app_builder.use_startup(Startup) + app_builder.build().run() + + +if __name__ == '__main__': + main() diff --git a/tools/ontime_calculator/startup.py b/tools/ontime_calculator/startup.py new file mode 100644 index 0000000..359c03d --- /dev/null +++ b/tools/ontime_calculator/startup.py @@ -0,0 +1,16 @@ +from cpl_core.application import StartupABC +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironment + + +class Startup(StartupABC): + + def __init__(self): + StartupABC.__init__(self) + + def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + return configuration + + def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + return services.build_service_provider()