Compare commits
90 Commits
1.0.1
...
5776854494
Author | SHA1 | Date | |
---|---|---|---|
5776854494 | |||
5c820214a1 | |||
f11d9af6c7 | |||
bff435d51e | |||
0f67bf467a | |||
2c7e5edbd7 | |||
0846bbb29b | |||
926323252a | |||
fedf2f4b8b | |||
4d4320dbcd | |||
c0b7e0913c | |||
9dcb75109f | |||
67baf350fa | |||
642a4d4dac | |||
6b86cc3ca8 | |||
fd10614b20 | |||
0ec67d41e2 | |||
51928dcb4d | |||
e36f0b8c76 | |||
2578c47c44 | |||
dda2e2f5f6 | |||
8aa96482c1 | |||
109bbf3729 | |||
3db548fb86 | |||
0e5ec588fc | |||
2c9434396d | |||
a49188b412 | |||
9e9879497a | |||
95e766d023 | |||
e25c29b2a6 | |||
1dd6db4c85 | |||
9a51e51235 | |||
fe5f3ced39 | |||
c1ec7dd97b | |||
09771ac2a3 | |||
6f27ce7bbc | |||
806144d9d3 | |||
877af6b945 | |||
979e0a0e6f | |||
fdf10f2728 | |||
f7ffd78dcc | |||
8ddb9f087a | |||
0ca3be478b | |||
bd8bd40863 | |||
ff009ffb61 | |||
074b03eecf | |||
5ea698ef97 | |||
400e54a501 | |||
3c0233e8b3 | |||
8d2ae38d85 | |||
2b866b5ab1 | |||
4da87ae3cb | |||
1ebad89c97 | |||
b8320c83fe | |||
0ee26ccf3d | |||
31ca9cd8f4 | |||
089de53136 | |||
280b22af55 | |||
ebdf375283 | |||
c058312af7 | |||
2befa921ea | |||
1792359e68 | |||
faaf14d63e | |||
49d1ec75c8 | |||
629556b5fc | |||
9ece541e52 | |||
fd51db8cac | |||
2005d93f44 | |||
010dafc655 | |||
bea9dd1590 | |||
ef0da25f11 | |||
c01a6b97fe | |||
059bd3aaf1 | |||
a9d180fdf1 | |||
c71b1092f2 | |||
c1e8274f46 | |||
583218b215 | |||
e05e67785b | |||
72d3ccded3 | |||
f30bd119df | |||
858fc062b3 | |||
6d622a70d3 | |||
4a0a6a4631 | |||
17c2acd77c | |||
27363522d3 | |||
1960b18058 | |||
91034cee09 | |||
a4d3cffa93 | |||
809c6d4cb9 | |||
2fecbf2c31 |
9
LICENSE
9
LICENSE
@@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022-2023 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 in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
@@ -7,6 +7,7 @@
|
||||
"bot-core": "src/bot_core/bot-core.json",
|
||||
"bot-data": "src/bot_data/bot-data.json",
|
||||
"bot-graphql": "src/bot_graphql/bot-graphql.json",
|
||||
"achievements": "src/modules/achievements/achievements.json",
|
||||
"auto-role": "src/modules/auto_role/auto-role.json",
|
||||
"base": "src/modules/base/base.json",
|
||||
"boot-log": "src/modules/boot_log/boot-log.json",
|
||||
@@ -21,25 +22,18 @@
|
||||
},
|
||||
"Scripts": {
|
||||
"format": "black ./",
|
||||
|
||||
"sv": "cpl set-version $ARGS",
|
||||
"set-version": "cpl run set-version $ARGS --dev; echo '';",
|
||||
|
||||
"gv": "cpl get-version",
|
||||
"get-version": "export VERSION=$(cpl run get-version --dev); echo $VERSION;",
|
||||
|
||||
"pre-build": "cpl set-version $ARGS; black ./;",
|
||||
"post-build": "cpl run post-build --dev; black ./;",
|
||||
|
||||
"pre-prod": "cpl build",
|
||||
"prod": "export KDB_ENVIRONMENT=production; export KDB_NAME=KDB-Prod; cpl start;",
|
||||
|
||||
"pre-stage": "cpl build",
|
||||
"stage": "export KDB_ENVIRONMENT=staging; export KDB_NAME=KDB-Stage; cpl start;",
|
||||
|
||||
"pre-dev": "cpl build",
|
||||
"dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;",
|
||||
|
||||
"docker-build": "cpl build $ARGS; docker build -t kdb-bot/kdb-bot:$(cpl gv) .;",
|
||||
"dc-up": "docker-compose up -d",
|
||||
"dc-down": "docker-compose down",
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -10,6 +10,7 @@ from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSet
|
||||
from bot_api.api_thread import ApiThread
|
||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
||||
from bot_core.service.data_integrity_service import DataIntegrityService
|
||||
|
||||
|
||||
class Application(DiscordBotApplicationABC):
|
||||
@@ -21,6 +22,7 @@ class Application(DiscordBotApplicationABC):
|
||||
|
||||
# cpl-core
|
||||
self._logger: LoggerABC = services.get_service(LoggerABC)
|
||||
self._data_integrity: DataIntegrityService = services.get_service(DataIntegrityService)
|
||||
# cpl-discord
|
||||
self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC)
|
||||
self._bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings)
|
||||
@@ -52,7 +54,7 @@ class Application(DiscordBotApplicationABC):
|
||||
self._api.join()
|
||||
return
|
||||
|
||||
self._logger.trace(__name__, f"Try to start {DiscordBotService.__name__}")
|
||||
self._logger.info(__name__, f"Try to start {DiscordBotService.__name__}")
|
||||
await self._bot.start_async()
|
||||
await self._bot.stop_async()
|
||||
except Exception as e:
|
||||
@@ -64,13 +66,17 @@ class Application(DiscordBotApplicationABC):
|
||||
|
||||
self._is_stopping = True
|
||||
try:
|
||||
self._logger.trace(__name__, f"Try to stop {DiscordBotService.__name__}")
|
||||
self._logger.info(__name__, f"Try to stop {DiscordBotService.__name__}")
|
||||
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||
self._api.stop()
|
||||
|
||||
await self._bot.close()
|
||||
self._logger.trace(__name__, f"Stopped {DiscordBotService.__name__}")
|
||||
self._data_integrity.check_data_integrity(is_for_shutdown=True)
|
||||
self._logger.info(__name__, f"Stopped {DiscordBotService.__name__}")
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, "stop failed", e)
|
||||
|
||||
Console.write_line()
|
||||
|
||||
def is_restart(self):
|
||||
return True if self._configuration.get_configuration("IS_RESTART") == "true" else False #
|
||||
return True if self._configuration.get_configuration("IS_RESTART") == "true" else False
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "0",
|
||||
"Micro": "1"
|
||||
"Micro": "7"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
@@ -16,23 +16,23 @@
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"cpl-core==2022.12.1.post3",
|
||||
"cpl-translation==2022.12.1",
|
||||
"cpl-query==2022.12.2.post2",
|
||||
"cpl-discord==2022.12.2.post1",
|
||||
"Flask==2.2.2",
|
||||
"cpl-core==2023.4.0.post2",
|
||||
"cpl-translation==2023.4.0.post1",
|
||||
"cpl-query==2023.4.0.post1",
|
||||
"cpl-discord==2023.4.0.post3",
|
||||
"Flask==2.3.2",
|
||||
"Flask-Classful==0.14.2",
|
||||
"Flask-Cors==3.0.10",
|
||||
"PyJWT==2.6.0",
|
||||
"PyJWT==2.7.0",
|
||||
"waitress==2.1.2",
|
||||
"Flask-SocketIO==5.3.2",
|
||||
"Flask-SocketIO==5.3.4",
|
||||
"eventlet==0.33.3",
|
||||
"requests-oauthlib==1.3.1",
|
||||
"icmplib==3.0.3",
|
||||
"ariadne==0.17.1"
|
||||
"ariadne==0.19.1"
|
||||
],
|
||||
"DevDependencies": [
|
||||
"cpl-cli==2022.12.1.post3",
|
||||
"cpl-cli==2023.4.0.post3",
|
||||
"pygount==1.5.1"
|
||||
],
|
||||
"PythonVersion": ">=3.10.4",
|
||||
|
Submodule kdb-bot/src/bot/config updated: 0c94637537...440fb3bd35
@@ -15,7 +15,7 @@ __title__ = "bot.extension"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -39,6 +39,7 @@ class Program:
|
||||
)
|
||||
self.app: Application = await app_builder.build_async()
|
||||
await self.app.run_async()
|
||||
Console.write_line(f"[ INFO ] [ {__name__} ]: Finished app.run_async")
|
||||
|
||||
async def stop(self):
|
||||
if self.app is None:
|
||||
|
@@ -5,6 +5,7 @@ from bot_core.core_extension.core_extension_module import CoreExtensionModule
|
||||
from bot_core.core_module import CoreModule
|
||||
from bot_data.data_module import DataModule
|
||||
from bot_graphql.graphql_module import GraphQLModule
|
||||
from modules.achievements.achievements_module import AchievementsModule
|
||||
from modules.auto_role.auto_role_module import AutoRoleModule
|
||||
from modules.base.base_module import BaseModule
|
||||
from modules.boot_log.boot_log_module import BootLogModule
|
||||
@@ -25,12 +26,13 @@ class ModuleList:
|
||||
DataModule,
|
||||
GraphQLModule,
|
||||
PermissionModule,
|
||||
LevelModule,
|
||||
DatabaseModule,
|
||||
AutoRoleModule,
|
||||
BaseModule,
|
||||
LevelModule,
|
||||
ApiModule,
|
||||
TechnicianModule,
|
||||
AchievementsModule,
|
||||
# has to be last!
|
||||
BootLogModule,
|
||||
CoreExtensionModule,
|
||||
|
@@ -4,6 +4,7 @@ from cpl_core.dependency_injection import ServiceCollectionABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
|
||||
from bot_data.abc.migration_abc import MigrationABC
|
||||
from bot_data.migration.achievements_migration import AchievementsMigration
|
||||
from bot_data.migration.api_key_migration import ApiKeyMigration
|
||||
from bot_data.migration.api_migration import ApiMigration
|
||||
from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration
|
||||
@@ -42,3 +43,4 @@ class StartupMigrationExtension(StartupExtensionABC):
|
||||
services.add_transient(MigrationABC, RemoveStatsMigration) # 19.02.2023 #190 - 1.0.0
|
||||
services.add_transient(MigrationABC, UserWarningMigration) # 21.02.2023 #35 - 1.0.0
|
||||
services.add_transient(MigrationABC, DBHistoryMigration) # 06.03.2023 #246 - 1.0.0
|
||||
services.add_transient(MigrationABC, AchievementsMigration) # 14.06.2023 #268 - 1.1.0
|
||||
|
@@ -11,7 +11,6 @@ from bot_core.configuration.bot_logging_settings import BotLoggingSettings
|
||||
from bot_core.configuration.bot_settings import BotSettings
|
||||
from modules.base.configuration.base_settings import BaseSettings
|
||||
from modules.boot_log.configuration.boot_log_settings import BootLogSettings
|
||||
from modules.level.configuration.level_settings import LevelSettings
|
||||
from modules.permission.configuration.permission_settings import PermissionSettings
|
||||
|
||||
|
||||
@@ -37,7 +36,6 @@ class StartupSettingsExtension(StartupExtensionABC):
|
||||
self._configure_settings_with_sub_settings(configuration, BotSettings, lambda x: x.servers, lambda x: x.id)
|
||||
self._configure_settings_with_sub_settings(configuration, BaseSettings, lambda x: x.servers, lambda x: x.id)
|
||||
self._configure_settings_with_sub_settings(configuration, BootLogSettings, lambda x: x.servers, lambda x: x.id)
|
||||
self._configure_settings_with_sub_settings(configuration, LevelSettings, lambda x: x.servers, lambda x: x.id)
|
||||
self._configure_settings_with_sub_settings(
|
||||
configuration, PermissionSettings, lambda x: x.servers, lambda x: x.id
|
||||
)
|
||||
@@ -50,9 +48,9 @@ class StartupSettingsExtension(StartupExtensionABC):
|
||||
|
||||
@staticmethod
|
||||
def _configure_settings_with_sub_settings(
|
||||
config: ConfigurationABC, settings: Type, list_atr: Callable, atr: Callable
|
||||
config: ConfigurationABC, settings_type: Type, list_atr: Callable, atr: Callable
|
||||
):
|
||||
settings: Optional[settings] = config.get_configuration(settings)
|
||||
settings: Optional[settings_type] = config.get_configuration(settings_type)
|
||||
if settings is None:
|
||||
return
|
||||
|
||||
|
@@ -93,6 +93,12 @@
|
||||
}
|
||||
},
|
||||
"modules": {
|
||||
"achievements": {
|
||||
"got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D",
|
||||
"commands": {
|
||||
"check": "Alles klar, ich schaue eben nach... nom nom"
|
||||
}
|
||||
},
|
||||
"auto_role": {
|
||||
"add": {
|
||||
"error": {
|
||||
@@ -145,6 +151,18 @@
|
||||
}
|
||||
},
|
||||
"base": {
|
||||
"complaints": {
|
||||
"title": "Beschwerde einreichen",
|
||||
"label": "Beschwerde",
|
||||
"message": "{} hat eine Beschwerde eingereicht:\n{}",
|
||||
"response": "Danke für deine Beschwerde"
|
||||
},
|
||||
"bug": {
|
||||
"title": "Bug melden",
|
||||
"label": "Bug",
|
||||
"message": "{} meldet einen Bug:\n{}",
|
||||
"response": "Danke für dein Feedback :D"
|
||||
},
|
||||
"afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?",
|
||||
"afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)",
|
||||
"game_server": {
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.abc"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import socket
|
||||
import sys
|
||||
import textwrap
|
||||
import uuid
|
||||
from functools import partial
|
||||
from typing import Union
|
||||
from typing import Union, Optional
|
||||
|
||||
import eventlet
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
@@ -53,10 +54,15 @@ class Api(Flask):
|
||||
self.register_error_handler(exc_class, self.handle_exception)
|
||||
|
||||
# websockets
|
||||
self._socketio = SocketIO(self, cors_allowed_origins="*", path="/api/socket.io")
|
||||
# Added async_mode see link below
|
||||
# https://github.com/miguelgrinberg/Flask-SocketIO/discussions/1849
|
||||
# https://stackoverflow.com/questions/39370848/flask-socket-io-sometimes-client-calls-freeze-the-server
|
||||
self._socketio = SocketIO(self, cors_allowed_origins="*", path="/api/socket.io", async_mode="eventlet")
|
||||
self._socketio.on_event("connect", self.on_connect)
|
||||
self._socketio.on_event("disconnect", self.on_disconnect)
|
||||
|
||||
self._socket: Optional[socket] = None
|
||||
|
||||
self._requests = {}
|
||||
|
||||
@staticmethod
|
||||
@@ -149,7 +155,14 @@ class Api(Flask):
|
||||
# from waitress import serve
|
||||
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html
|
||||
# serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10)
|
||||
wsgi.server(eventlet.listen((self._api_settings.host, self._api_settings.port)), self, log_output=False)
|
||||
self._socket = eventlet.listen((self._api_settings.host, self._api_settings.port))
|
||||
wsgi.server(self._socket, self, log_output=False)
|
||||
|
||||
def stop(self):
|
||||
if self._socket is None:
|
||||
return
|
||||
self._socket.shutdown(socket.SHUT_RDWR)
|
||||
self._socket.close()
|
||||
|
||||
def on_connect(self):
|
||||
self._logger.info(__name__, f"Client connected")
|
||||
|
@@ -17,3 +17,10 @@ class ApiThread(threading.Thread):
|
||||
self._api.start()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, "Start failed", e)
|
||||
|
||||
def stop(self):
|
||||
try:
|
||||
self._logger.trace(__name__, f"Try to stop {type(self._api).__name__}")
|
||||
self._api.stop()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, "Stop failed", e)
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "0",
|
||||
"Micro": "1"
|
||||
"Micro": "7"
|
||||
},
|
||||
"Author": "",
|
||||
"AuthorEmail": "",
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.configuration"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.controller"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -1,5 +1,5 @@
|
||||
from ariadne import graphql_sync
|
||||
from ariadne.constants import PLAYGROUND_HTML
|
||||
from ariadne.explorer import ExplorerPlayground
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
from flask import request, jsonify
|
||||
@@ -30,7 +30,7 @@ class GraphQLController:
|
||||
if self._env.environment_name != "development":
|
||||
return "", 403
|
||||
|
||||
return PLAYGROUND_HTML, 200
|
||||
return ExplorerPlayground().html(None), 200
|
||||
|
||||
@Route.post(f"{BasePath}")
|
||||
@Route.authorize(by_api_key=True)
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.event"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.exception"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.filter"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.filter.discord"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.logging"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.model"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.model.discord"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.route"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.service"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.transformer"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.abc"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "0",
|
||||
"Micro": "1"
|
||||
"Micro": "7"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.configuration"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -1,32 +1,26 @@
|
||||
import traceback
|
||||
|
||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
||||
from cpl_core.console import Console, ForegroundColorEnum
|
||||
from cpl_core.utils.json_processor import JSONProcessor
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_core.configuration.file_logging_settings import FileLoggingSettings
|
||||
|
||||
|
||||
class BotLoggingSettings(ConfigurationModelABC):
|
||||
def __init__(self):
|
||||
def __init__(self, custom_logs: dict = None):
|
||||
ConfigurationModelABC.__init__(self)
|
||||
self._files: List[FileLoggingSettings] = List(FileLoggingSettings)
|
||||
|
||||
if custom_logs is not None:
|
||||
self._files_from_dict(custom_logs)
|
||||
|
||||
@property
|
||||
def files(self) -> List[FileLoggingSettings]:
|
||||
return self._files
|
||||
|
||||
def from_dict(self, settings: dict):
|
||||
try:
|
||||
def _files_from_dict(self, settings: dict):
|
||||
files = List(FileLoggingSettings)
|
||||
for s in settings:
|
||||
st = FileLoggingSettings()
|
||||
settings[s]["Key"] = s
|
||||
st.from_dict(settings[s])
|
||||
st = JSONProcessor.process(FileLoggingSettings, settings[s])
|
||||
files.append(st)
|
||||
self._files = files
|
||||
except Exception as e:
|
||||
Console.set_foreground_color(ForegroundColorEnum.red)
|
||||
Console.write_line(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||
Console.write_line(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||
Console.set_foreground_color(ForegroundColorEnum.default)
|
||||
|
@@ -1,21 +1,30 @@
|
||||
import traceback
|
||||
|
||||
from cpl_core.configuration import ConfigurationModelABC
|
||||
from cpl_core.console import Console
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_api.json_processor import JSONProcessor
|
||||
from bot_core.configuration.server_settings import ServerSettings
|
||||
|
||||
|
||||
class BotSettings(ConfigurationModelABC):
|
||||
def __init__(self):
|
||||
def __init__(
|
||||
self,
|
||||
technicians: list = None,
|
||||
wait_for_restart: int = 2,
|
||||
wait_for_shutdown: int = 2,
|
||||
cache_max_messages: int = 1000,
|
||||
server_settings: dict = None,
|
||||
):
|
||||
ConfigurationModelABC.__init__(self)
|
||||
|
||||
self._technicians: List[int] = List(int) if technicians is None else technicians
|
||||
self._wait_for_restart = wait_for_restart
|
||||
self._wait_for_shutdown = wait_for_shutdown
|
||||
self._cache_max_messages = cache_max_messages
|
||||
|
||||
self._servers: List[ServerSettings] = List(ServerSettings)
|
||||
self._technicians: List[int] = List(int)
|
||||
self._wait_for_restart = 2
|
||||
self._wait_for_shutdown = 2
|
||||
self._cache_max_messages = 1000
|
||||
|
||||
if server_settings is not None:
|
||||
self._servers_from_dict(server_settings)
|
||||
|
||||
@property
|
||||
def servers(self) -> List[ServerSettings]:
|
||||
@@ -37,26 +46,34 @@ class BotSettings(ConfigurationModelABC):
|
||||
def cache_max_messages(self) -> int:
|
||||
return self._cache_max_messages
|
||||
|
||||
def from_dict(self, settings: dict):
|
||||
try:
|
||||
self._technicians = settings["Technicians"]
|
||||
self._wait_for_restart = settings["WaitForRestart"]
|
||||
self._wait_for_shutdown = settings["WaitForShutdown"]
|
||||
settings.pop("Technicians")
|
||||
settings.pop("WaitForRestart")
|
||||
settings.pop("WaitForShutdown")
|
||||
|
||||
if "CacheMaxMessages" in settings:
|
||||
self._cache_max_messages = settings["CacheMaxMessages"]
|
||||
settings.pop("CacheMaxMessages")
|
||||
|
||||
def _servers_from_dict(self, settings: dict):
|
||||
servers = List(ServerSettings)
|
||||
for s in settings:
|
||||
st = ServerSettings()
|
||||
settings[s]["Id"] = s
|
||||
st.from_dict(settings[s])
|
||||
settings[s]["id"] = int(s)
|
||||
st = JSONProcessor.process(ServerSettings, settings[s])
|
||||
servers.append(st)
|
||||
self._servers = servers
|
||||
except Exception as e:
|
||||
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||
|
||||
# def from_dict(self, settings: dict):
|
||||
# try:
|
||||
# self._technicians = settings["Technicians"]
|
||||
# self._wait_for_restart = settings["WaitForRestart"]
|
||||
# self._wait_for_shutdown = settings["WaitForShutdown"]
|
||||
# settings.pop("Technicians")
|
||||
# settings.pop("WaitForRestart")
|
||||
# settings.pop("WaitForShutdown")
|
||||
#
|
||||
# if "CacheMaxMessages" in settings:
|
||||
# self._cache_max_messages = settings["CacheMaxMessages"]
|
||||
# settings.pop("CacheMaxMessages")
|
||||
#
|
||||
# servers = List(ServerSettings)
|
||||
# for s in settings:
|
||||
# st = ServerSettings()
|
||||
# settings[s]["Id"] = s
|
||||
# st.from_dict(settings[s])
|
||||
# servers.append(st)
|
||||
# self._servers = servers
|
||||
# except Exception as e:
|
||||
# Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||
# Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||
|
@@ -3,6 +3,7 @@ from enum import Enum
|
||||
|
||||
class FeatureFlagsEnum(Enum):
|
||||
# modules
|
||||
achievements_module = "AchievementsModule"
|
||||
api_module = "ApiModule"
|
||||
admin_module = "AdminModule"
|
||||
auto_role_module = "AutoRoleModule"
|
||||
|
@@ -12,6 +12,7 @@ class FeatureFlagsSettings(ConfigurationModelABC):
|
||||
|
||||
self._flags = {
|
||||
# modules
|
||||
FeatureFlagsEnum.achievements_module.value: False, # 14.06.2023 #268
|
||||
FeatureFlagsEnum.api_module.value: False, # 13.10.2022 #70
|
||||
FeatureFlagsEnum.admin_module.value: False, # 02.10.2022 #48
|
||||
FeatureFlagsEnum.auto_role_module.value: True, # 03.10.2022 #54
|
||||
|
@@ -1,23 +1,27 @@
|
||||
import traceback
|
||||
|
||||
from cpl_core.console import Console
|
||||
from cpl_core.logging import LoggingSettings
|
||||
from cpl_core.logging import LoggingSettings, LoggingLevelEnum
|
||||
|
||||
|
||||
class FileLoggingSettings(LoggingSettings):
|
||||
def __init__(self):
|
||||
LoggingSettings.__init__(self)
|
||||
def __init__(
|
||||
self,
|
||||
key: str,
|
||||
path: str = None,
|
||||
filename: str = None,
|
||||
console_log_level: LoggingLevelEnum = None,
|
||||
file_log_level: LoggingLevelEnum = None,
|
||||
):
|
||||
LoggingSettings.__init__(self, path, filename, console_log_level, file_log_level)
|
||||
|
||||
self._key = ""
|
||||
self._key = key
|
||||
|
||||
@property
|
||||
def key(self) -> str:
|
||||
return self._key
|
||||
|
||||
def from_dict(self, settings: dict):
|
||||
try:
|
||||
self._key = settings["Key"]
|
||||
super().from_dict(settings)
|
||||
except Exception as e:
|
||||
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||
# def from_dict(self, settings: dict):
|
||||
# try:
|
||||
# self._key = settings["Key"]
|
||||
# super().from_dict(settings)
|
||||
# except Exception as e:
|
||||
# Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||
# Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||
|
@@ -1,15 +1,18 @@
|
||||
import traceback
|
||||
|
||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
||||
from cpl_core.console import Console
|
||||
|
||||
|
||||
class ServerSettings(ConfigurationModelABC):
|
||||
def __init__(self):
|
||||
def __init__(
|
||||
self,
|
||||
id: int = None,
|
||||
message_delete_timer: int = None,
|
||||
notification_chat_id: int = None,
|
||||
):
|
||||
ConfigurationModelABC.__init__(self)
|
||||
|
||||
self._id: int = 0
|
||||
self._message_delete_timer: int = 0
|
||||
self._id: int = id
|
||||
self._message_delete_timer: int = message_delete_timer
|
||||
self._notification_chat_id: int = notification_chat_id
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
@@ -19,10 +22,15 @@ class ServerSettings(ConfigurationModelABC):
|
||||
def message_delete_timer(self) -> int:
|
||||
return self._message_delete_timer
|
||||
|
||||
def from_dict(self, settings: dict):
|
||||
try:
|
||||
self._id = int(settings["Id"])
|
||||
self._message_delete_timer = int(settings["MessageDeleteTimer"])
|
||||
except Exception as e:
|
||||
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in settings")
|
||||
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||
@property
|
||||
def notification_chat_id(self) -> int:
|
||||
return self._notification_chat_id
|
||||
|
||||
# def from_dict(self, settings: dict):
|
||||
# try:
|
||||
# self._id = int(settings["Id"])
|
||||
# self._message_delete_timer = int(settings["MessageDeleteTimer"])
|
||||
# self._notification_chat_id = int(settings["NotificationChatId"])
|
||||
# except Exception as e:
|
||||
# Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in settings")
|
||||
# Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.core_extension"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -11,6 +11,7 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
from bot_core.events.core_on_ready_event import CoreOnReadyEvent
|
||||
from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe
|
||||
from bot_core.service.client_utils_service import ClientUtilsService
|
||||
from bot_core.service.data_integrity_service import DataIntegrityService
|
||||
from bot_core.service.message_service import MessageService
|
||||
|
||||
|
||||
@@ -24,6 +25,7 @@ class CoreModule(ModuleABC):
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
services.add_transient(MessageServiceABC, MessageService)
|
||||
services.add_transient(ClientUtilsABC, ClientUtilsService)
|
||||
services.add_transient(DataIntegrityService)
|
||||
|
||||
# pipes
|
||||
services.add_transient(DateTimeOffsetPipe)
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.events"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.exception"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.helper"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -1,13 +1,9 @@
|
||||
from typing import Optional
|
||||
|
||||
from cpl_translation import TranslatePipe
|
||||
from discord.ext import commands
|
||||
from discord.ext.commands import Context
|
||||
|
||||
from bot_core.abc.client_utils_abc import ClientUtilsABC
|
||||
from bot_core.abc.message_service_abc import MessageServiceABC
|
||||
from bot_core.exception.check_error import CheckError
|
||||
from modules.permission.abc.permission_service_abc import PermissionServiceABC
|
||||
|
||||
|
||||
class EventChecks:
|
||||
@@ -23,7 +19,7 @@ class EventChecks:
|
||||
@classmethod
|
||||
def check_is_ready(cls):
|
||||
async def check_if_bot_is_ready() -> bool:
|
||||
result = await cls._client_utils.check_if_bot_is_ready()
|
||||
result = await cls._client_utils.check_if_bot_is_ready_yet()
|
||||
if not result:
|
||||
raise CheckError(f"Bot is not ready")
|
||||
return result
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.logging"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.pipes"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_core.service"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
396
kdb-bot/src/bot_core/service/data_integrity_service.py
Normal file
396
kdb-bot/src/bot_core/service/data_integrity_service.py
Normal file
@@ -0,0 +1,396 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Union
|
||||
|
||||
import discord
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
|
||||
from bot_core.logging.database_logger import DatabaseLogger
|
||||
from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe
|
||||
from bot_data.abc.client_repository_abc import ClientRepositoryABC
|
||||
from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC
|
||||
from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC
|
||||
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
|
||||
from bot_data.abc.user_joined_voice_channel_repository_abc import (
|
||||
UserJoinedVoiceChannelRepositoryABC,
|
||||
)
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_data.model.client import Client
|
||||
from bot_data.model.known_user import KnownUser
|
||||
from bot_data.model.server import Server
|
||||
from bot_data.model.user import User
|
||||
from bot_data.model.user_joined_server import UserJoinedServer
|
||||
from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
|
||||
from bot_data.service.seeder_service import SeederService
|
||||
from bot_data.service.user_repository_service import ServerRepositoryABC
|
||||
from modules.achievements.achievement_service import AchievementService
|
||||
from modules.base.configuration.base_server_settings import BaseServerSettings
|
||||
|
||||
|
||||
class DataIntegrityService:
|
||||
def __init__(
|
||||
self,
|
||||
config: ConfigurationABC,
|
||||
logger: DatabaseLogger,
|
||||
seeder: SeederService,
|
||||
bot: DiscordBotServiceABC,
|
||||
db_context: DatabaseContextABC,
|
||||
server_repo: ServerRepositoryABC,
|
||||
user_repo: UserRepositoryABC,
|
||||
client_repo: ClientRepositoryABC,
|
||||
known_users: KnownUserRepositoryABC,
|
||||
user_joins: UserJoinedServerRepositoryABC,
|
||||
user_joins_vc: UserJoinedVoiceChannelRepositoryABC,
|
||||
user_joined_gs: UserJoinedGameServerRepositoryABC,
|
||||
achievement_service: AchievementService,
|
||||
dtp: DateTimeOffsetPipe,
|
||||
):
|
||||
self._config = config
|
||||
|
||||
self._logger = logger
|
||||
self._seeder = seeder
|
||||
self._bot = bot
|
||||
self._db_context = db_context
|
||||
self._servers = server_repo
|
||||
self._users = user_repo
|
||||
self._clients = client_repo
|
||||
self._known_users = known_users
|
||||
self._user_joins = user_joins
|
||||
self._user_joins_vc = user_joins_vc
|
||||
self._user_joined_gs = user_joined_gs
|
||||
self._achievements = achievement_service
|
||||
self._dtp = dtp
|
||||
|
||||
self._is_for_shutdown = False
|
||||
|
||||
def _check_known_users(self):
|
||||
self._logger.debug(__name__, f"Start checking KnownUsers table, {len(self._bot.users)}")
|
||||
for u in self._bot.users:
|
||||
u: discord.User = u
|
||||
try:
|
||||
if u.bot:
|
||||
self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot")
|
||||
continue
|
||||
|
||||
user = self._known_users.find_user_by_discord_id(u.id)
|
||||
if user is not None:
|
||||
continue
|
||||
|
||||
self._logger.warn(__name__, f"Unknown user: {u.id}")
|
||||
self._logger.debug(__name__, f"Add user: {u.id}")
|
||||
self._known_users.add_user(KnownUser(u.id))
|
||||
self._db_context.save_changes()
|
||||
|
||||
user = self._known_users.find_user_by_discord_id(u.id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f"Cannot add user: {u.id}")
|
||||
|
||||
self._logger.debug(__name__, f"Added user: {u.id}")
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot get user", e)
|
||||
|
||||
def _check_servers(self):
|
||||
self._logger.debug(__name__, f"Start checking Servers table")
|
||||
for g in self._bot.guilds:
|
||||
g: discord.Guild = g
|
||||
try:
|
||||
server = self._servers.find_server_by_discord_id(g.id)
|
||||
if server is not None:
|
||||
continue
|
||||
|
||||
self._logger.warn(__name__, f"Server not found in database: {g.id}")
|
||||
self._logger.debug(__name__, f"Add server: {g.id}")
|
||||
self._servers.add_server(Server(g.id))
|
||||
self._db_context.save_changes()
|
||||
|
||||
server = self._servers.find_server_by_discord_id(g.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f"Cannot add server: {g.id}")
|
||||
|
||||
self._logger.debug(__name__, f"Added server: {g.id}")
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot get server", e)
|
||||
|
||||
results = self._servers.get_servers()
|
||||
if results is None or len(results) == 0:
|
||||
self._logger.error(__name__, f"Table Servers is empty!")
|
||||
|
||||
def _check_clients(self):
|
||||
self._logger.debug(__name__, f"Start checking Clients table")
|
||||
for g in self._bot.guilds:
|
||||
g: discord.Guild = g
|
||||
try:
|
||||
server: Server = self._servers.find_server_by_discord_id(g.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f"Server not found in database: {g.id}")
|
||||
|
||||
client = self._clients.find_client_by_server_id(server.id)
|
||||
if client is not None:
|
||||
continue
|
||||
|
||||
self._logger.warn(
|
||||
__name__,
|
||||
f"Client for server {g.id} not found in database: {self._bot.user.id}",
|
||||
)
|
||||
self._logger.debug(__name__, f"Add client: {self._bot.user.id}")
|
||||
self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server))
|
||||
self._db_context.save_changes()
|
||||
|
||||
client = self._clients.find_client_by_server_id(server.id)
|
||||
if client is None:
|
||||
self._logger.fatal(
|
||||
__name__,
|
||||
f"Cannot add client {self._bot.user.id} for server {g.id}",
|
||||
)
|
||||
|
||||
self._logger.debug(__name__, f"Added client: {g.id}")
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot get client", e)
|
||||
|
||||
results = self._servers.get_servers()
|
||||
if results is None or len(results) == 0:
|
||||
self._logger.error(__name__, f"Table Servers is empty!")
|
||||
|
||||
def _check_users(self):
|
||||
self._logger.debug(__name__, f"Start checking Users table")
|
||||
for g in self._bot.guilds:
|
||||
g: discord.Guild = g
|
||||
|
||||
try:
|
||||
server = self._servers.find_server_by_discord_id(g.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f"Server not found in database: {g.id}")
|
||||
|
||||
for u in g.members:
|
||||
u: Union[discord.Member, discord.User] = u
|
||||
if u.bot:
|
||||
self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot")
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id)
|
||||
if user is not None:
|
||||
continue
|
||||
|
||||
self._logger.warn(__name__, f"User not found in database: {u.id}")
|
||||
self._logger.debug(__name__, f"Add user: {u.id}")
|
||||
self._users.add_user(User(u.id, 0, server))
|
||||
self._db_context.save_changes()
|
||||
|
||||
self._logger.debug(__name__, f"Added User: {u.id}")
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot get User", e)
|
||||
|
||||
results = self._users.get_users()
|
||||
if results is None or len(results) == 0:
|
||||
self._logger.error(__name__, f"Table Users is empty!")
|
||||
|
||||
def _check_user_joins(self):
|
||||
self._logger.debug(__name__, f"Start checking UserJoinedServers table")
|
||||
for guild in self._bot.guilds:
|
||||
guild: discord.Guild = guild
|
||||
|
||||
server = self._servers.find_server_by_discord_id(guild.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f"Server not found in database: {guild.id}")
|
||||
|
||||
try:
|
||||
for u in guild.members:
|
||||
u: discord.User = u
|
||||
if u.bot:
|
||||
self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot")
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f"User not found in database: {u.id}")
|
||||
|
||||
join = self._user_joins.find_active_user_joined_server_by_user_id(user.id)
|
||||
if join is not None:
|
||||
continue
|
||||
|
||||
m: discord.Member = u
|
||||
self._logger.warn(
|
||||
__name__,
|
||||
f"Active UserJoinedServer not found in database: {guild.id}:{u.id}@{m.joined_at}",
|
||||
)
|
||||
self._logger.debug(
|
||||
__name__,
|
||||
f"Add UserJoinedServer: {guild.id}:{u.id}@{m.joined_at}",
|
||||
)
|
||||
self._user_joins.add_user_joined_server(
|
||||
UserJoinedServer(user, self._dtp.transform(m.joined_at), None)
|
||||
)
|
||||
self._db_context.save_changes()
|
||||
|
||||
self._logger.debug(__name__, f"Added UserJoinedServer: {u.id}")
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot get UserJoinedServer", e)
|
||||
|
||||
results = self._users.get_users()
|
||||
if results is None or len(results) == 0:
|
||||
self._logger.error(__name__, f"Table Users is empty!")
|
||||
|
||||
joins = self._user_joins.get_user_joined_servers()
|
||||
for join in joins:
|
||||
join: UserJoinedServer = join
|
||||
if join.user.server.discord_id != guild.id:
|
||||
continue
|
||||
|
||||
if join.leaved_on is not None:
|
||||
continue
|
||||
|
||||
dc_user = guild.get_member(join.user.discord_id)
|
||||
if dc_user is None:
|
||||
self._logger.warn(
|
||||
__name__,
|
||||
f"User {join.user.discord_id} already left the server.",
|
||||
)
|
||||
join.leaved_on = datetime.now()
|
||||
self._user_joins.update_user_joined_server(join)
|
||||
|
||||
self._db_context.save_changes()
|
||||
|
||||
def _check_user_joins_vc(self):
|
||||
self._logger.debug(__name__, f"Start checking UserJoinedVoiceChannel table")
|
||||
for guild in self._bot.guilds:
|
||||
guild: discord.Guild = guild
|
||||
settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}")
|
||||
|
||||
server = self._servers.find_server_by_discord_id(guild.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f"Server not found in database: {guild.id}")
|
||||
|
||||
try:
|
||||
# close open voice states
|
||||
for member in guild.members:
|
||||
if member.bot:
|
||||
self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot")
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f"User not found in database: {member.id}")
|
||||
|
||||
joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.id)
|
||||
if joins is None or len(joins) == 0:
|
||||
continue
|
||||
|
||||
for join in joins:
|
||||
self._logger.warn(
|
||||
__name__,
|
||||
f"Active UserJoinedVoiceChannel found in database: {guild.id}:{member.id}@{join.joined_on}",
|
||||
)
|
||||
join.leaved_on = datetime.now()
|
||||
|
||||
if (
|
||||
(join.leaved_on - join.joined_on).total_seconds() / 60 / 60
|
||||
) > settings.max_voice_state_hours:
|
||||
join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours)
|
||||
|
||||
self._user_joins_vc.update_user_joined_voice_channel(join)
|
||||
|
||||
if self._is_for_shutdown:
|
||||
user.xp = round(join.time * settings.xp_per_ontime_hour)
|
||||
self._users.update_user(user)
|
||||
|
||||
self._db_context.save_changes()
|
||||
if self._is_for_shutdown:
|
||||
return
|
||||
|
||||
# add open voice states
|
||||
for member in guild.members:
|
||||
if member.bot:
|
||||
self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot")
|
||||
continue
|
||||
|
||||
if member.voice is None or member.voice.channel.id in settings.afk_channel_ids:
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f"User not found in database: {member.id}")
|
||||
|
||||
join = UserJoinedVoiceChannel(user, member.voice.channel.id, datetime.now())
|
||||
self._user_joins_vc.add_user_joined_voice_channel(join)
|
||||
self._db_context.save_changes()
|
||||
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot get UserJoinedVoiceChannel", e)
|
||||
|
||||
def _check_user_joined_gs(self):
|
||||
self._logger.debug(__name__, f"Start checking UserJoinedGameServer table")
|
||||
for guild in self._bot.guilds:
|
||||
guild: discord.Guild = guild
|
||||
|
||||
server = self._servers.find_server_by_discord_id(guild.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f"Server not found in database: {guild.id}")
|
||||
|
||||
try:
|
||||
for member in guild.members:
|
||||
if member.bot:
|
||||
self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot")
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f"User not found in database: {member.id}")
|
||||
|
||||
joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.id)
|
||||
if joins is None or len(joins) == 0:
|
||||
continue
|
||||
|
||||
for join in joins:
|
||||
self._logger.warn(
|
||||
__name__,
|
||||
f"Active UserJoinedGameServer found in database: {guild.id}:{member.id}@{join.joined_on}",
|
||||
)
|
||||
join.leaved_on = datetime.now()
|
||||
settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}")
|
||||
|
||||
if (
|
||||
(join.leaved_on - join.joined_on).total_seconds() / 60 / 60
|
||||
) > settings.max_voice_state_hours:
|
||||
join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours)
|
||||
|
||||
self._user_joined_gs.update_user_joined_game_server(join)
|
||||
if self._is_for_shutdown:
|
||||
user.xp = round(join.time * settings.xp_per_ontime_hour)
|
||||
self._users.update_user(user)
|
||||
|
||||
self._db_context.save_changes()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot get UserJoinedGameServer", e)
|
||||
|
||||
def _check_for_user_achievements(self):
|
||||
self._logger.debug(__name__, f"Start checking UserGotAchievement table")
|
||||
|
||||
for guild in self._bot.guilds:
|
||||
server = self._servers.find_server_by_discord_id(guild.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f"Server not found in database: {guild.id}")
|
||||
|
||||
for member in guild.members:
|
||||
if member.bot:
|
||||
self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot")
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f"User not found in database: {member.id}")
|
||||
|
||||
self._bot.loop.create_task(self._achievements.validate_achievements_for_user(user))
|
||||
|
||||
def check_data_integrity(self, is_for_shutdown=False):
|
||||
if is_for_shutdown != self._is_for_shutdown:
|
||||
self._is_for_shutdown = is_for_shutdown
|
||||
|
||||
self._check_known_users()
|
||||
self._check_servers()
|
||||
self._check_clients()
|
||||
self._check_users()
|
||||
self._check_user_joins()
|
||||
self._check_user_joins_vc()
|
||||
self._check_user_joined_gs()
|
||||
self._check_for_user_achievements()
|
@@ -15,7 +15,7 @@ __title__ = "bot_data"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_data.abc"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
52
kdb-bot/src/bot_data/abc/achievement_repository_abc.py
Normal file
52
kdb-bot/src/bot_data/abc/achievement_repository_abc.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_data.model.achievement import Achievement
|
||||
from bot_data.model.user_got_achievement import UserGotAchievement
|
||||
|
||||
|
||||
class AchievementRepositoryABC(ABC):
|
||||
@abstractmethod
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_achievements(self) -> List[Achievement]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_achievement_by_id(self, id: int) -> Achievement:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_got_achievements_by_achievement_id(self, achievement_id: int) -> List[Achievement]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def add_achievement(self, achievement: Achievement):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update_achievement(self, achievement: Achievement):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_achievement(self, achievement: Achievement):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def add_user_got_achievement(self, join: UserGotAchievement):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_user_got_achievement(self, join: UserGotAchievement):
|
||||
pass
|
@@ -4,7 +4,7 @@
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "0",
|
||||
"Micro": "1"
|
||||
"Micro": "7"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
|
@@ -5,6 +5,7 @@ from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
|
||||
|
||||
from bot_core.abc.module_abc import ModuleABC
|
||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||
from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC
|
||||
from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
|
||||
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
|
||||
@@ -24,9 +25,11 @@ from bot_data.abc.user_message_count_per_hour_repository_abc import (
|
||||
)
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC
|
||||
from bot_data.service.achievements_repository_service import AchievementRepositoryService
|
||||
from bot_data.service.api_key_repository_service import ApiKeyRepositoryService
|
||||
from bot_data.service.auth_user_repository_service import AuthUserRepositoryService
|
||||
from bot_data.service.auto_role_repository_service import AutoRoleRepositoryService
|
||||
from bot_data.service.cache_service import CacheService
|
||||
from bot_data.service.client_repository_service import ClientRepositoryService
|
||||
from bot_data.service.game_server_repository_service import GameServerRepositoryService
|
||||
from bot_data.service.known_user_repository_service import KnownUserRepositoryService
|
||||
@@ -56,6 +59,8 @@ class DataModule(ModuleABC):
|
||||
pass
|
||||
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
services.add_singleton(CacheService)
|
||||
|
||||
services.add_transient(ApiKeyRepositoryABC, ApiKeyRepositoryService)
|
||||
services.add_transient(AuthUserRepositoryABC, AuthUserRepositoryService)
|
||||
services.add_transient(ServerRepositoryABC, ServerRepositoryService)
|
||||
@@ -74,5 +79,6 @@ class DataModule(ModuleABC):
|
||||
)
|
||||
services.add_transient(GameServerRepositoryABC, GameServerRepositoryService)
|
||||
services.add_transient(UserGameIdentRepositoryABC, UserGameIdentRepositoryService)
|
||||
services.add_transient(AchievementRepositoryABC, AchievementRepositoryService)
|
||||
|
||||
services.add_transient(SeederService)
|
||||
|
@@ -11,6 +11,7 @@ class DBContext(DatabaseContext):
|
||||
self._logger = logger
|
||||
|
||||
DatabaseContext.__init__(self)
|
||||
self._fails = 0
|
||||
|
||||
def connect(self, database_settings: DatabaseSettings):
|
||||
try:
|
||||
@@ -32,7 +33,11 @@ class DBContext(DatabaseContext):
|
||||
try:
|
||||
return super(DBContext, self).select(statement)
|
||||
except Exception as e:
|
||||
if self._fails >= 3:
|
||||
self._logger.fatal(__name__, f"Database error caused by {statement}", e)
|
||||
|
||||
self._logger.error(__name__, f"Database error caused by {statement}", e)
|
||||
self._fails += 1
|
||||
try:
|
||||
time.sleep(0.5)
|
||||
return self.select(statement)
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_data.migration"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
127
kdb-bot/src/bot_data/migration/achievements_migration.py
Normal file
127
kdb-bot/src/bot_data/migration/achievements_migration.py
Normal file
@@ -0,0 +1,127 @@
|
||||
from bot_core.logging.database_logger import DatabaseLogger
|
||||
from bot_data.abc.migration_abc import MigrationABC
|
||||
from bot_data.db_context import DBContext
|
||||
|
||||
|
||||
class AchievementsMigration(MigrationABC):
|
||||
name = "1.1.0_AchievementsMigration"
|
||||
|
||||
def __init__(self, logger: DatabaseLogger, db: DBContext):
|
||||
MigrationABC.__init__(self)
|
||||
self._logger = logger
|
||||
self._db = db
|
||||
self._cursor = db.cursor
|
||||
|
||||
def upgrade(self):
|
||||
self._logger.debug(__name__, "Running upgrade")
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS `Achievements` (
|
||||
`Id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`Name` VARCHAR(255) NOT NULL,
|
||||
`Description` VARCHAR(255) NOT NULL,
|
||||
`Attribute` VARCHAR(255) NOT NULL,
|
||||
`Operator` VARCHAR(255) NOT NULL,
|
||||
`Value` VARCHAR(255) NOT NULL,
|
||||
`ServerId` BIGINT,
|
||||
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY(`Id`),
|
||||
FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`)
|
||||
);
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS `AchievementsHistory`
|
||||
(
|
||||
`Id` BIGINT(20) NOT NULL,
|
||||
`Name` VARCHAR(255) NOT NULL,
|
||||
`Description` VARCHAR(255) NOT NULL,
|
||||
`Attribute` VARCHAR(255) NOT NULL,
|
||||
`Operator` VARCHAR(255) NOT NULL,
|
||||
`Value` VARCHAR(255) NOT NULL,
|
||||
`ServerId` BIGINT,
|
||||
`Deleted` BOOL DEFAULT FALSE,
|
||||
`DateFrom` DATETIME(6) NOT NULL,
|
||||
`DateTo` DATETIME(6) NOT NULL
|
||||
);
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS `UserGotAchievements` (
|
||||
`Id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`UserId` BIGINT,
|
||||
`AchievementId` BIGINT,
|
||||
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY(`Id`),
|
||||
FOREIGN KEY (`UserId`) REFERENCES `Users`(`UserId`),
|
||||
FOREIGN KEY (`AchievementId`) REFERENCES `Achievements`(`Id`)
|
||||
);
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
# A join table history between users and achievements is not necessary.
|
||||
|
||||
self._cursor.execute(str(f"""ALTER TABLE Users ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
||||
self._cursor.execute(str(f"""ALTER TABLE Users ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
||||
self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
||||
self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
||||
|
||||
self._cursor.execute(str(f"""DROP TRIGGER IF EXISTS `TR_AchievementsUpdate`;"""))
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
CREATE TRIGGER `TR_AchievementsUpdate`
|
||||
AFTER UPDATE
|
||||
ON `Achievements`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT INTO `AchievementsHistory` (
|
||||
`Id`, `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId`, `DateFrom`, `DateTo`
|
||||
)
|
||||
VALUES (
|
||||
OLD.Id, OLD.Name, OLD.Description, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
|
||||
);
|
||||
END;
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
self._cursor.execute(str(f"""DROP TRIGGER IF EXISTS `TR_AchievementsDelete`;"""))
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
CREATE TRIGGER `TR_AchievementsDelete`
|
||||
AFTER DELETE
|
||||
ON `Achievements`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT INTO `AchievementsHistory` (
|
||||
`Id`, `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId`, `Deleted`, `DateFrom`, `DateTo`
|
||||
)
|
||||
VALUES (
|
||||
OLD.Id, OLD.Name, OLD.Description, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
|
||||
);
|
||||
END;
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
def downgrade(self):
|
||||
self._cursor.execute("DROP TABLE `Achievements`;")
|
||||
|
||||
self._cursor.execute(str(f"""ALTER TABLE Users DROP COLUMN MessageCount;"""))
|
||||
self._cursor.execute(str(f"""ALTER TABLE Users DROP COLUMN ReactionCount;"""))
|
@@ -15,7 +15,7 @@ __title__ = "bot_data.model"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
149
kdb-bot/src/bot_data/model/achievement.py
Normal file
149
kdb-bot/src/bot_data/model/achievement.py
Normal file
@@ -0,0 +1,149 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.database import TableABC
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
|
||||
from bot_data.model.server import Server
|
||||
|
||||
|
||||
class Achievement(TableABC):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
description: str,
|
||||
attribute: str,
|
||||
operator: str,
|
||||
value: str,
|
||||
server: Optional[Server],
|
||||
created_at: datetime = None,
|
||||
modified_at: datetime = None,
|
||||
id=0,
|
||||
):
|
||||
self._id = id
|
||||
self._name = name
|
||||
self._description = description
|
||||
self._attribute = attribute
|
||||
|
||||
if self._is_operator_valid(operator):
|
||||
raise ValueError("Operator invalid")
|
||||
|
||||
self._operator = operator
|
||||
self._value = value
|
||||
self._server = server
|
||||
|
||||
TableABC.__init__(self)
|
||||
self._created_at = created_at if created_at is not None else self._created_at
|
||||
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||
|
||||
@ServiceProviderABC.inject
|
||||
def _is_operator_valid(self, operator, service: ServiceProviderABC) -> bool:
|
||||
from modules.achievements.achievement_service import AchievementService
|
||||
|
||||
achievements: AchievementService = service.get_service(AchievementService)
|
||||
return operator not in achievements.get_operators()
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
def name(self, value: str):
|
||||
self._name = value
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return self._description
|
||||
|
||||
@description.setter
|
||||
def description(self, value: str):
|
||||
self._description = value
|
||||
|
||||
@property
|
||||
def attribute(self) -> str:
|
||||
return self._attribute
|
||||
|
||||
@attribute.setter
|
||||
def attribute(self, value: str):
|
||||
self._attribute = value
|
||||
|
||||
@property
|
||||
def operator(self) -> str:
|
||||
return self._operator
|
||||
|
||||
@operator.setter
|
||||
def operator(self, value: str):
|
||||
self._operator = value
|
||||
|
||||
@property
|
||||
def value(self) -> str:
|
||||
return self._value
|
||||
|
||||
@value.setter
|
||||
def value(self, value: str):
|
||||
self._value = value
|
||||
|
||||
@property
|
||||
def server(self) -> Server:
|
||||
return self._server
|
||||
|
||||
@staticmethod
|
||||
def get_select_all_string() -> str:
|
||||
return str(
|
||||
f"""
|
||||
SELECT * FROM `Achievements`;
|
||||
"""
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_id_string(id: int) -> str:
|
||||
return str(
|
||||
f"""
|
||||
SELECT * FROM `Achievements`
|
||||
WHERE `Id` = {id};
|
||||
"""
|
||||
)
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
return str(
|
||||
f"""
|
||||
INSERT INTO `Achievements` (
|
||||
`Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId`
|
||||
) VALUES (
|
||||
'{self._name}',
|
||||
'{self._description}',
|
||||
'{self._attribute}',
|
||||
'{self._operator}',
|
||||
'{self._value}',
|
||||
{self._server.id}
|
||||
);
|
||||
"""
|
||||
)
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return str(
|
||||
f"""
|
||||
UPDATE `Achievements`
|
||||
SET `Name` = '{self._name}',
|
||||
`Description` = '{self._description}',
|
||||
`Attribute` = '{self._attribute}',
|
||||
`Operator` = '{self._operator}',
|
||||
`Value` = '{self._value}'
|
||||
WHERE `Id` = {self._id};
|
||||
"""
|
||||
)
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(
|
||||
f"""
|
||||
DELETE FROM `Achievements`
|
||||
WHERE `Id` = {self._id};
|
||||
"""
|
||||
)
|
58
kdb-bot/src/bot_data/model/achievement_history.py
Normal file
58
kdb-bot/src/bot_data/model/achievement_history.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from bot_data.abc.history_table_abc import HistoryTableABC
|
||||
|
||||
|
||||
class AchievementHistory(HistoryTableABC):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
description: str,
|
||||
attribute: str,
|
||||
operator: str,
|
||||
value: str,
|
||||
server: int,
|
||||
deleted: bool,
|
||||
date_from: str,
|
||||
date_to: str,
|
||||
id=0,
|
||||
):
|
||||
HistoryTableABC.__init__(self)
|
||||
|
||||
self._id = id
|
||||
self._name = name
|
||||
self._description = description
|
||||
self._attribute = attribute
|
||||
self._operator = operator
|
||||
self._value = value
|
||||
self._server = server
|
||||
|
||||
self._deleted = deleted
|
||||
self._date_from = date_from
|
||||
self._date_to = date_to
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return self._description
|
||||
|
||||
@property
|
||||
def attribute(self) -> str:
|
||||
return self._attribute
|
||||
|
||||
@property
|
||||
def operator(self) -> str:
|
||||
return self._operator
|
||||
|
||||
@property
|
||||
def value(self) -> str:
|
||||
return self._value
|
||||
|
||||
@property
|
||||
def server(self) -> int:
|
||||
return self._server
|
@@ -15,6 +15,8 @@ class User(TableABC):
|
||||
self,
|
||||
dc_id: int,
|
||||
xp: int,
|
||||
message_count: int,
|
||||
reaction_count: int,
|
||||
server: Optional[Server],
|
||||
created_at: datetime = None,
|
||||
modified_at: datetime = None,
|
||||
@@ -23,6 +25,8 @@ class User(TableABC):
|
||||
self._user_id = id
|
||||
self._discord_id = dc_id
|
||||
self._xp = xp
|
||||
self._message_count = message_count
|
||||
self._reaction_count = reaction_count
|
||||
self._server = server
|
||||
|
||||
TableABC.__init__(self)
|
||||
@@ -59,6 +63,22 @@ class User(TableABC):
|
||||
def xp(self, value: int):
|
||||
self._xp = value
|
||||
|
||||
@property
|
||||
def message_count(self) -> int:
|
||||
return self._message_count
|
||||
|
||||
@message_count.setter
|
||||
def message_count(self, value: int):
|
||||
self._message_count = value
|
||||
|
||||
@property
|
||||
def reaction_count(self) -> int:
|
||||
return self._reaction_count
|
||||
|
||||
@reaction_count.setter
|
||||
def reaction_count(self, value: int):
|
||||
self._reaction_count = value
|
||||
|
||||
@property
|
||||
@ServiceProviderABC.inject
|
||||
def ontime(self, services: ServiceProviderABC) -> float:
|
||||
@@ -151,10 +171,12 @@ class User(TableABC):
|
||||
return str(
|
||||
f"""
|
||||
INSERT INTO `Users` (
|
||||
`DiscordId`, `XP`, `ServerId`
|
||||
`DiscordId`, `XP`, `MessageCount`, `ReactionCount`, `ServerId`
|
||||
) VALUES (
|
||||
{self._discord_id},
|
||||
{self._xp},
|
||||
{self._message_count},
|
||||
{self._reaction_count},
|
||||
{self._server.id}
|
||||
);
|
||||
"""
|
||||
@@ -165,7 +187,9 @@ class User(TableABC):
|
||||
return str(
|
||||
f"""
|
||||
UPDATE `Users`
|
||||
SET `XP` = {self._xp}
|
||||
SET `XP` = {self._xp},
|
||||
`MessageCount` = {self._message_count},
|
||||
`ReactionCount` = {self._reaction_count}
|
||||
WHERE `UserId` = {self._user_id};
|
||||
"""
|
||||
)
|
||||
|
105
kdb-bot/src/bot_data/model/user_got_achievement.py
Normal file
105
kdb-bot/src/bot_data/model/user_got_achievement.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.database import TableABC
|
||||
|
||||
from bot_data.model.achievement import Achievement
|
||||
from bot_data.model.user import User
|
||||
|
||||
|
||||
class UserGotAchievement(TableABC):
|
||||
def __init__(
|
||||
self,
|
||||
user: Optional[User],
|
||||
achievement: Optional[Achievement],
|
||||
created_at: datetime = None,
|
||||
modified_at: datetime = None,
|
||||
id=0,
|
||||
):
|
||||
self._id = id
|
||||
self._user = user
|
||||
self._achievement = achievement
|
||||
|
||||
TableABC.__init__(self)
|
||||
self._created_at = created_at if created_at is not None else self._created_at
|
||||
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def user(self) -> User:
|
||||
return self._user
|
||||
|
||||
@property
|
||||
def achievement(self) -> Achievement:
|
||||
return self._achievement
|
||||
|
||||
@staticmethod
|
||||
def get_select_all_string() -> str:
|
||||
return str(
|
||||
f"""
|
||||
SELECT * FROM `UserGotAchievements`;
|
||||
"""
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_id_string(id: int) -> str:
|
||||
return str(
|
||||
f"""
|
||||
SELECT * FROM `UserGotAchievements`
|
||||
WHERE `Id` = {id};
|
||||
"""
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_user_id_string(id: int) -> str:
|
||||
return str(
|
||||
f"""
|
||||
SELECT * FROM `UserGotAchievements`
|
||||
WHERE `UserId` = {id};
|
||||
"""
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_achievement_id_string(id: int) -> str:
|
||||
return str(
|
||||
f"""
|
||||
SELECT * FROM `UserGotAchievements`
|
||||
WHERE `AchievementId` = {id};
|
||||
"""
|
||||
)
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
return str(
|
||||
f"""
|
||||
INSERT INTO `UserGotAchievements` (
|
||||
`UserId`, `AchievementId`
|
||||
) VALUES (
|
||||
{self._user.id},
|
||||
{self._achievement.id}
|
||||
);
|
||||
"""
|
||||
)
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return str(
|
||||
f"""
|
||||
UPDATE `UserGotAchievements`
|
||||
SET `UserId` = '{self._user.id}',
|
||||
`AchievementId` = '{self._achievement.id}'
|
||||
WHERE `Id` = {self._id};
|
||||
"""
|
||||
)
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(
|
||||
f"""
|
||||
DELETE FROM `UserGotAchievements`
|
||||
WHERE `Id` = {self._id};
|
||||
"""
|
||||
)
|
@@ -9,6 +9,8 @@ class UserHistory(HistoryTableABC):
|
||||
self,
|
||||
dc_id: int,
|
||||
xp: int,
|
||||
message_count: int,
|
||||
reaction_count: int,
|
||||
server: int,
|
||||
deleted: bool,
|
||||
date_from: str,
|
||||
@@ -20,6 +22,8 @@ class UserHistory(HistoryTableABC):
|
||||
self._user_id = id
|
||||
self._discord_id = dc_id
|
||||
self._xp = xp
|
||||
self._message_count = message_count
|
||||
self._reaction_count = reaction_count
|
||||
self._server = server
|
||||
|
||||
self._deleted = deleted
|
||||
@@ -38,6 +42,14 @@ class UserHistory(HistoryTableABC):
|
||||
def xp(self) -> int:
|
||||
return self._xp
|
||||
|
||||
@property
|
||||
def message_count(self) -> int:
|
||||
return self._message_count
|
||||
|
||||
@property
|
||||
def reaction_count(self) -> int:
|
||||
return self._reaction_count
|
||||
|
||||
@property
|
||||
def server(self) -> int:
|
||||
return self._server
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_data.service"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
123
kdb-bot/src/bot_data/service/achievements_repository_service.py
Normal file
123
kdb-bot/src/bot_data/service/achievements_repository_service.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_core.logging.database_logger import DatabaseLogger
|
||||
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_data.model.achievement import Achievement
|
||||
from bot_data.model.user_got_achievement import UserGotAchievement
|
||||
|
||||
|
||||
class AchievementRepositoryService(AchievementRepositoryABC):
|
||||
def __init__(
|
||||
self,
|
||||
logger: DatabaseLogger,
|
||||
db_context: DatabaseContextABC,
|
||||
servers: ServerRepositoryABC,
|
||||
users: UserRepositoryABC,
|
||||
):
|
||||
self._logger = logger
|
||||
self._context = db_context
|
||||
|
||||
self._servers = servers
|
||||
self._users = users
|
||||
|
||||
AchievementRepositoryABC.__init__(self)
|
||||
|
||||
def _from_result(self, result: tuple):
|
||||
return Achievement(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
self._servers.get_server_by_id(result[6]),
|
||||
result[7],
|
||||
result[8],
|
||||
id=result[0],
|
||||
)
|
||||
|
||||
def _join_from_result(self, result: tuple):
|
||||
return UserGotAchievement(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
self.get_achievement_by_id(result[2]),
|
||||
result[3],
|
||||
result[4],
|
||||
id=result[0],
|
||||
)
|
||||
|
||||
def get_achievements(self) -> List[Achievement]:
|
||||
achievements = List(Achievement)
|
||||
self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_all_string()}")
|
||||
results = self._context.select(Achievement.get_select_all_string())
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f"Get user with id {result[0]}")
|
||||
achievements.append(self._from_result(result))
|
||||
|
||||
return achievements
|
||||
|
||||
def get_achievement_by_id(self, id: int) -> Achievement:
|
||||
self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_by_id_string(id)}")
|
||||
result = self._context.select(Achievement.get_select_by_id_string(id))[0]
|
||||
|
||||
return self._from_result(result)
|
||||
|
||||
def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]:
|
||||
achievements = List(Achievement)
|
||||
self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_by_id_string(server_id)}")
|
||||
results = self._context.select(Achievement.get_select_all_string())
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f"Get user with id {result[0]}")
|
||||
achievements.append(self._from_result(result))
|
||||
|
||||
return achievements
|
||||
|
||||
def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]:
|
||||
achievements = List(Achievement)
|
||||
achievements_joins = List(UserGotAchievement)
|
||||
self._logger.trace(__name__, f"Send SQL command: {UserGotAchievement.get_select_by_user_id_string(user_id)}")
|
||||
results = self._context.select(UserGotAchievement.get_select_by_user_id_string(user_id))
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f"Got UserGotAchievement with id {result[0]}")
|
||||
achievements_joins.append(self._join_from_result(result))
|
||||
|
||||
for achievements_join in achievements_joins:
|
||||
results = self._context.select(Achievement.get_select_by_id_string(achievements_join.achievement.id))
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f"Got Achievement with id {result[0]}")
|
||||
achievements.append(self._from_result(result))
|
||||
|
||||
return achievements
|
||||
|
||||
def get_user_got_achievements_by_achievement_id(self, achievement_id: int) -> List[Achievement]:
|
||||
achievements_joins = List(UserGotAchievement)
|
||||
self._logger.trace(
|
||||
__name__, f"Send SQL command: {UserGotAchievement.get_select_by_achievement_id_string(achievement_id)}"
|
||||
)
|
||||
results = self._context.select(UserGotAchievement.get_select_by_achievement_id_string(achievement_id))
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f"Got UserGotAchievement with id {result[0]}")
|
||||
achievements_joins.append(self._join_from_result(result))
|
||||
|
||||
return achievements_joins
|
||||
|
||||
def add_achievement(self, achievement: Achievement):
|
||||
self._logger.trace(__name__, f"Send SQL command: {achievement.insert_string}")
|
||||
self._context.cursor.execute(achievement.insert_string)
|
||||
|
||||
def update_achievement(self, achievement: Achievement):
|
||||
self._logger.trace(__name__, f"Send SQL command: {achievement.udpate_string}")
|
||||
self._context.cursor.execute(achievement.udpate_string)
|
||||
|
||||
def delete_achievement(self, achievement: Achievement):
|
||||
self._logger.trace(__name__, f"Send SQL command: {achievement.delete_string}")
|
||||
self._context.cursor.execute(achievement.delete_string)
|
||||
|
||||
def add_user_got_achievement(self, join: UserGotAchievement):
|
||||
self._logger.trace(__name__, f"Send SQL command: {join.insert_string}")
|
||||
self._context.cursor.execute(join.insert_string)
|
||||
|
||||
def delete_user_got_achievement(self, join: UserGotAchievement):
|
||||
self._logger.trace(__name__, f"Send SQL command: {join.delete_string}")
|
||||
self._context.cursor.execute(join.delete_string)
|
25
kdb-bot/src/bot_data/service/cache_service.py
Normal file
25
kdb-bot/src/bot_data/service/cache_service.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_data.model.server import Server
|
||||
|
||||
|
||||
class CacheService:
|
||||
def __init__(self):
|
||||
self._cached_servers = List(Server)
|
||||
|
||||
@property
|
||||
def cached_server(self) -> List[Server]:
|
||||
return self._cached_servers
|
||||
|
||||
def add_server(self, server: Server):
|
||||
if self._cached_servers.where(lambda x: x.id == server.id).count() > 0:
|
||||
return
|
||||
self._cached_servers.add(server)
|
||||
|
||||
def add_servers(self, servers: List[Server]):
|
||||
new_ids = servers.select(lambda x: x.id)
|
||||
for s in self._cached_servers:
|
||||
if s.id in new_ids:
|
||||
return
|
||||
|
||||
self._cached_servers.extend(servers)
|
@@ -8,12 +8,14 @@ from bot_core.logging.database_logger import DatabaseLogger
|
||||
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from bot_data.filtered_result import FilteredResult
|
||||
from bot_data.model.server import Server
|
||||
from bot_data.service.cache_service import CacheService
|
||||
|
||||
|
||||
class ServerRepositoryService(ServerRepositoryABC):
|
||||
def __init__(self, logger: DatabaseLogger, db_context: DatabaseContextABC):
|
||||
def __init__(self, logger: DatabaseLogger, db_context: DatabaseContextABC, cache: CacheService):
|
||||
self._logger = logger
|
||||
self._context = db_context
|
||||
self._cache = cache
|
||||
|
||||
ServerRepositoryABC.__init__(self)
|
||||
|
||||
@@ -24,6 +26,7 @@ class ServerRepositoryService(ServerRepositoryABC):
|
||||
for result in results:
|
||||
servers.append(Server(result[1], result[2], result[3], id=result[0]))
|
||||
|
||||
self._cache.add_servers(servers)
|
||||
return servers
|
||||
|
||||
def get_filtered_servers(self, criteria: ServerSelectCriteria) -> FilteredResult:
|
||||
@@ -52,11 +55,22 @@ class ServerRepositoryService(ServerRepositoryABC):
|
||||
return result
|
||||
|
||||
def get_server_by_id(self, server_id: int) -> Server:
|
||||
cs = self._cache.cached_server.where(lambda x: x.id == server_id).single_or_default()
|
||||
|
||||
if cs is not None:
|
||||
return cs
|
||||
|
||||
self._logger.trace(__name__, f"Send SQL command: {Server.get_select_by_id_string(server_id)}")
|
||||
result = self._context.select(Server.get_select_by_id_string(server_id))[0]
|
||||
return Server(result[1], result[2], result[3], id=result[0])
|
||||
server = Server(result[1], result[2], result[3], id=result[0])
|
||||
self._cache.add_server(server)
|
||||
return server
|
||||
|
||||
def get_server_by_discord_id(self, discord_id: int) -> Server:
|
||||
cs = self._cache.cached_server.where(lambda x: x.discord_id == discord_id).single_or_default()
|
||||
if cs is not None:
|
||||
return cs
|
||||
|
||||
self._logger.trace(
|
||||
__name__,
|
||||
f"Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}",
|
||||
@@ -65,6 +79,10 @@ class ServerRepositoryService(ServerRepositoryABC):
|
||||
return Server(result[1], result[2], result[3], id=result[0])
|
||||
|
||||
def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]:
|
||||
cs = self._cache.cached_server.where(lambda x: x.discord_id == discord_id).single_or_default()
|
||||
if cs is not None:
|
||||
return cs
|
||||
|
||||
self._logger.trace(
|
||||
__name__,
|
||||
f"Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}",
|
||||
|
@@ -27,9 +27,11 @@ class UserRepositoryService(UserRepositoryABC):
|
||||
return User(
|
||||
result[1],
|
||||
result[2],
|
||||
self._servers.get_server_by_id(result[3]),
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
self._servers.get_server_by_id(result[5]),
|
||||
result[6],
|
||||
result[7],
|
||||
id=result[0],
|
||||
)
|
||||
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_graphql"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_graphql.abc"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "0",
|
||||
"Micro": "1"
|
||||
"Micro": "7"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
@@ -16,10 +16,10 @@
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"cpl-core>=1.0.1"
|
||||
"cpl-core==2022.12.0"
|
||||
],
|
||||
"DevDependencies": [
|
||||
"cpl-cli>=1.0.1"
|
||||
"cpl-core==2022.12.0"
|
||||
],
|
||||
"PythonVersion": ">=3.10.4",
|
||||
"PythonPath": {},
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_graphql.filter"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
67
kdb-bot/src/bot_graphql/filter/achievement_filter.py
Normal file
67
kdb-bot/src/bot_graphql/filter/achievement_filter.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_data.model.user import User
|
||||
from bot_graphql.abc.filter_abc import FilterABC
|
||||
|
||||
|
||||
class AchievementFilter(FilterABC):
|
||||
def __init__(self):
|
||||
FilterABC.__init__(self)
|
||||
|
||||
self._id = None
|
||||
self._name = None
|
||||
self._description = None
|
||||
self._attribute = None
|
||||
self._operator = None
|
||||
self._value = None
|
||||
self._server = None
|
||||
|
||||
def from_dict(self, values: dict):
|
||||
if "id" in values:
|
||||
self._id = int(values["id"])
|
||||
|
||||
if "name" in values:
|
||||
self._name = values["name"]
|
||||
|
||||
if "description" in values:
|
||||
self._description = values["description"]
|
||||
|
||||
if "attribute" in values:
|
||||
self._attribute = values["attribute"]
|
||||
|
||||
if "operator" in values:
|
||||
self._operator = values["operator"]
|
||||
|
||||
if "value" in values:
|
||||
self._value = values["value"]
|
||||
|
||||
if "server" in values:
|
||||
from bot_graphql.filter.server_filter import ServerFilter
|
||||
|
||||
self._server: ServerFilter = self._services.get_service(ServerFilter)
|
||||
self._server.from_dict(values["server"])
|
||||
|
||||
def filter(self, query: List[User]) -> List[User]:
|
||||
if self._id is not None:
|
||||
query = query.where(lambda x: x.id == self._id)
|
||||
|
||||
if self._name is not None:
|
||||
query = query.where(lambda x: x.name == self._name or self._name in x.name)
|
||||
|
||||
if self._description is not None:
|
||||
query = query.where(lambda x: x.description == self._description or self._description in x.description)
|
||||
|
||||
if self._attribute is not None:
|
||||
query = query.where(lambda x: x.attribute == self._attribute or self._attribute in x.attribute)
|
||||
|
||||
if self._operator is not None:
|
||||
query = query.where(lambda x: x.operator == self._operator)
|
||||
|
||||
if self._value is not None:
|
||||
query = query.where(lambda x: x.value == self._value)
|
||||
|
||||
if self._server is not None:
|
||||
servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id)
|
||||
query = query.where(lambda x: x.server.id in servers)
|
||||
|
||||
return query
|
@@ -8,6 +8,7 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
from bot_data.service.seeder_service import SeederService
|
||||
from bot_graphql.abc.filter_abc import FilterABC
|
||||
from bot_graphql.abc.query_abc import QueryABC
|
||||
from bot_graphql.filter.achievement_filter import AchievementFilter
|
||||
from bot_graphql.filter.auto_role_filter import AutoRoleFilter
|
||||
from bot_graphql.filter.auto_role_rule_filter import AutoRoleRuleFilter
|
||||
from bot_graphql.filter.client_filter import ClientFilter
|
||||
@@ -19,17 +20,22 @@ from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter
|
||||
from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter
|
||||
from bot_graphql.graphql_service import GraphQLService
|
||||
from bot_graphql.mutation import Mutation
|
||||
from bot_graphql.mutations.achievement_mutation import AchievementMutation
|
||||
from bot_graphql.mutations.auto_role_mutation import AutoRoleMutation
|
||||
from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation
|
||||
from bot_graphql.mutations.level_mutation import LevelMutation
|
||||
from bot_graphql.mutations.user_joined_game_server_mutation import UserJoinedGameServerMutation
|
||||
from bot_graphql.mutations.user_mutation import UserMutation
|
||||
from bot_graphql.queries.achievement_attribute_query import AchievementAttributeQuery
|
||||
from bot_graphql.queries.achievement_history_query import AchievementHistoryQuery
|
||||
from bot_graphql.queries.achievement_query import AchievementQuery
|
||||
from bot_graphql.queries.auto_role_history_query import AutoRoleHistoryQuery
|
||||
from bot_graphql.queries.auto_role_query import AutoRoleQuery
|
||||
from bot_graphql.queries.auto_role_rule_history_query import AutoRoleRuleHistoryQuery
|
||||
from bot_graphql.queries.auto_role_rule_query import AutoRoleRuleQuery
|
||||
from bot_graphql.queries.client_history_query import ClientHistoryQuery
|
||||
from bot_graphql.queries.client_query import ClientQuery
|
||||
from bot_graphql.queries.game_server_query import GameServerQuery
|
||||
from bot_graphql.queries.known_user_history_query import KnownUserHistoryQuery
|
||||
from bot_graphql.queries.known_user_query import KnownUserQuery
|
||||
from bot_graphql.queries.level_history_query import LevelHistoryQuery
|
||||
@@ -62,6 +68,9 @@ class GraphQLModule(ModuleABC):
|
||||
services.add_singleton(Mutation)
|
||||
|
||||
# queries
|
||||
services.add_transient(QueryABC, AchievementAttributeQuery)
|
||||
services.add_transient(QueryABC, AchievementQuery)
|
||||
services.add_transient(QueryABC, AchievementHistoryQuery)
|
||||
services.add_transient(QueryABC, AutoRoleHistoryQuery)
|
||||
services.add_transient(QueryABC, AutoRoleQuery)
|
||||
services.add_transient(QueryABC, AutoRoleRuleHistoryQuery)
|
||||
@@ -74,6 +83,7 @@ class GraphQLModule(ModuleABC):
|
||||
services.add_transient(QueryABC, LevelQuery)
|
||||
services.add_transient(QueryABC, ServerHistoryQuery)
|
||||
services.add_transient(QueryABC, ServerQuery)
|
||||
services.add_transient(QueryABC, GameServerQuery)
|
||||
services.add_transient(QueryABC, UserHistoryQuery)
|
||||
services.add_transient(QueryABC, UserQuery)
|
||||
services.add_transient(QueryABC, UserJoinedServerHistoryQuery)
|
||||
@@ -90,6 +100,7 @@ class GraphQLModule(ModuleABC):
|
||||
services.add_transient(FilterABC, LevelFilter)
|
||||
services.add_transient(FilterABC, ServerFilter)
|
||||
services.add_transient(FilterABC, UserFilter)
|
||||
services.add_transient(FilterABC, AchievementFilter)
|
||||
services.add_transient(FilterABC, UserJoinedServerFilter)
|
||||
services.add_transient(FilterABC, UserJoinedVoiceChannelFilter)
|
||||
services.add_transient(FilterABC, UserJoinedGameServerFilter)
|
||||
@@ -99,6 +110,7 @@ class GraphQLModule(ModuleABC):
|
||||
services.add_transient(QueryABC, AutoRoleRuleMutation)
|
||||
services.add_transient(QueryABC, LevelMutation)
|
||||
services.add_transient(QueryABC, UserMutation)
|
||||
services.add_transient(QueryABC, AchievementMutation)
|
||||
services.add_transient(QueryABC, UserJoinedGameServerMutation)
|
||||
|
||||
services.add_transient(SeederService)
|
||||
|
64
kdb-bot/src/bot_graphql/model/achievement.gql
Normal file
64
kdb-bot/src/bot_graphql/model/achievement.gql
Normal file
@@ -0,0 +1,64 @@
|
||||
type AchievementAttribute {
|
||||
name: String
|
||||
type: String
|
||||
|
||||
createdAt: String
|
||||
modifiedAt: String
|
||||
}
|
||||
|
||||
type Achievement implements TableWithHistoryQuery {
|
||||
id: ID
|
||||
name: String
|
||||
description: String
|
||||
attribute: String
|
||||
operator: String
|
||||
value: String
|
||||
|
||||
server: Server
|
||||
|
||||
createdAt: String
|
||||
modifiedAt: String
|
||||
|
||||
history: [AchievementHistory]
|
||||
}
|
||||
|
||||
type AchievementHistory implements HistoryTableQuery {
|
||||
id: ID
|
||||
name: String
|
||||
description: String
|
||||
attribute: String
|
||||
operator: String
|
||||
value: String
|
||||
|
||||
server: ID
|
||||
|
||||
deleted: Boolean
|
||||
dateFrom: String
|
||||
dateTo: String
|
||||
}
|
||||
|
||||
input AchievementFilter {
|
||||
id: ID
|
||||
name: String
|
||||
description: String
|
||||
attribute: String
|
||||
operator: String
|
||||
value: String
|
||||
server: ServerFilter
|
||||
}
|
||||
|
||||
type AchievementMutation {
|
||||
createAchievement(input: AchievementInput!): Achievement
|
||||
updateAchievement(input: AchievementInput!): Achievement
|
||||
deleteAchievement(id: ID): Achievement
|
||||
}
|
||||
|
||||
input AchievementInput {
|
||||
id: ID
|
||||
name: String
|
||||
description: String
|
||||
attribute: String
|
||||
operator: String
|
||||
value: String
|
||||
serverId: ID
|
||||
}
|
@@ -4,4 +4,5 @@ type Mutation {
|
||||
level: LevelMutation
|
||||
user: UserMutation
|
||||
userJoinedGameServer: UserJoinedGameServerMutation
|
||||
achievement: AchievementMutation
|
||||
}
|
@@ -17,6 +17,9 @@ type Query {
|
||||
serverCount: Int
|
||||
servers(filter: ServerFilter, page: Page, sort: Sort): [Server]
|
||||
|
||||
gameServerCount: Int
|
||||
gameServers: [GameServer]
|
||||
|
||||
userJoinedServerCount: Int
|
||||
userJoinedServers(filter: UserJoinedServerFilter, page: Page, sort: Sort): [UserJoinedServer]
|
||||
|
||||
@@ -29,5 +32,10 @@ type Query {
|
||||
userCount: Int
|
||||
users(filter: UserFilter, page: Page, sort: Sort): [User]
|
||||
|
||||
achievementCount: Int
|
||||
achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement]
|
||||
achievementAttributes: [AchievementAttribute]
|
||||
achievementOperators: [String]
|
||||
|
||||
guilds(filter: GuildFilter): [Guild]
|
||||
}
|
@@ -1,3 +1,12 @@
|
||||
type GameServer {
|
||||
id: ID
|
||||
name: String
|
||||
server: Server
|
||||
|
||||
createdAt: String
|
||||
modifiedAt: String
|
||||
}
|
||||
|
||||
type Server implements TableWithHistoryQuery {
|
||||
id: ID
|
||||
discordId: String
|
||||
@@ -13,9 +22,15 @@ type Server implements TableWithHistoryQuery {
|
||||
levelCount: Int
|
||||
levels(filter: LevelFilter, page: Page, sort: Sort): [Level]
|
||||
|
||||
gameServerCount: Int
|
||||
gameServers: [GameServer]
|
||||
|
||||
userCount: Int
|
||||
users(filter: UserFilter, page: Page, sort: Sort): [User]
|
||||
|
||||
achievementCount: Int
|
||||
achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement]
|
||||
|
||||
createdAt: String
|
||||
modifiedAt: String
|
||||
|
||||
|
@@ -3,6 +3,8 @@ type User implements TableWithHistoryQuery {
|
||||
discordId: String
|
||||
name: String
|
||||
xp: Int
|
||||
messageCount: Int
|
||||
reactionCount: Int
|
||||
ontime: Float
|
||||
level: Level
|
||||
|
||||
@@ -15,6 +17,9 @@ type User implements TableWithHistoryQuery {
|
||||
userJoinedGameServerCount: Int
|
||||
userJoinedGameServers(filter: UserJoinedGameServerFilter, page: Page, sort: Sort): [UserJoinedGameServer]
|
||||
|
||||
achievementCount: Int
|
||||
achievements(filter: AchievementFilter, page: Page, sort: Sort): [Achievement]
|
||||
|
||||
server: Server
|
||||
leftServer: Boolean
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
from ariadne import MutationType
|
||||
|
||||
from bot_data.model.user_joined_game_server import UserJoinedGameServer
|
||||
from bot_graphql.mutations.achievement_mutation import AchievementMutation
|
||||
from bot_graphql.mutations.auto_role_mutation import AutoRoleMutation
|
||||
from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation
|
||||
from bot_graphql.mutations.level_mutation import LevelMutation
|
||||
@@ -15,6 +15,7 @@ class Mutation(MutationType):
|
||||
auto_role_rule_mutation: AutoRoleRuleMutation,
|
||||
level_mutation: LevelMutation,
|
||||
user_mutation: UserMutation,
|
||||
achievement_mutation: AchievementMutation,
|
||||
user_joined_game_server: UserJoinedGameServerMutation,
|
||||
):
|
||||
MutationType.__init__(self)
|
||||
@@ -23,4 +24,5 @@ class Mutation(MutationType):
|
||||
self.set_field("autoRoleRule", lambda *_: auto_role_rule_mutation)
|
||||
self.set_field("level", lambda *_: level_mutation)
|
||||
self.set_field("user", lambda *_: user_mutation)
|
||||
self.set_field("achievement", lambda *_: achievement_mutation)
|
||||
self.set_field("userJoinedGameServer", lambda *_: user_joined_game_server)
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_graphql.mutations"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
87
kdb-bot/src/bot_graphql/mutations/achievement_mutation.py
Normal file
87
kdb-bot/src/bot_graphql/mutations/achievement_mutation.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
|
||||
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from bot_data.model.achievement import Achievement
|
||||
from bot_data.model.user_role_enum import UserRoleEnum
|
||||
from bot_graphql.abc.query_abc import QueryABC
|
||||
from modules.permission.service.permission_service import PermissionService
|
||||
|
||||
|
||||
class AchievementMutation(QueryABC):
|
||||
def __init__(
|
||||
self,
|
||||
servers: ServerRepositoryABC,
|
||||
achievements: AchievementRepositoryABC,
|
||||
bot: DiscordBotServiceABC,
|
||||
db: DatabaseContextABC,
|
||||
permissions: PermissionService,
|
||||
):
|
||||
QueryABC.__init__(self, "AchievementMutation")
|
||||
|
||||
self._servers = servers
|
||||
self._achievements = achievements
|
||||
self._bot = bot
|
||||
self._db = db
|
||||
self._permissions = permissions
|
||||
|
||||
self.set_field("createAchievement", self.resolve_create_achievement)
|
||||
self.set_field("updateAchievement", self.resolve_update_achievement)
|
||||
self.set_field("deleteAchievement", self.resolve_delete_achievement)
|
||||
|
||||
def resolve_create_achievement(self, *_, input: dict):
|
||||
server = self._servers.get_server_by_id(input["serverId"])
|
||||
self._can_user_mutate_data(server, UserRoleEnum.admin)
|
||||
|
||||
achievement = Achievement(
|
||||
input["name"],
|
||||
input["description"],
|
||||
input["attribute"],
|
||||
input["operator"],
|
||||
input["value"],
|
||||
server,
|
||||
)
|
||||
self._achievements.add_achievement(achievement)
|
||||
self._db.save_changes()
|
||||
|
||||
def get_new_achievement(a: Achievement):
|
||||
return (
|
||||
a.name == achievement.name
|
||||
and a.description == achievement.description
|
||||
and a.attribute == achievement.attribute
|
||||
and a.operator == achievement.operator
|
||||
and a.value == achievement.value
|
||||
and a.server.id == server.id
|
||||
)
|
||||
|
||||
return self._achievements.get_achievements_by_server_id(achievement.server.id).where(get_new_achievement).last()
|
||||
|
||||
def resolve_update_achievement(self, *_, input: dict):
|
||||
achievement = self._achievements.get_achievement_by_id(input["id"])
|
||||
self._can_user_mutate_data(achievement.server, UserRoleEnum.moderator)
|
||||
|
||||
achievement.name = input["name"] if "name" in input else achievement.name
|
||||
achievement.description = input["description"] if "description" in input else achievement.description
|
||||
achievement.attribute = input["attribute"] if "attribute" in input else achievement.attribute
|
||||
achievement.operator = input["operator"] if "operator" in input else achievement.operator
|
||||
achievement.value = input["value"] if "value" in input else achievement.value
|
||||
|
||||
self._achievements.update_achievement(achievement)
|
||||
self._db.save_changes()
|
||||
|
||||
achievement = self._achievements.get_achievement_by_id(input["id"])
|
||||
return achievement
|
||||
|
||||
def resolve_delete_achievement(self, *_, id: int):
|
||||
achievement = self._achievements.get_achievement_by_id(id)
|
||||
self._can_user_mutate_data(achievement.server, UserRoleEnum.admin)
|
||||
|
||||
joins = self._achievements.get_user_got_achievements_by_achievement_id(id)
|
||||
for join in joins:
|
||||
self._achievements.delete_user_got_achievement(join)
|
||||
|
||||
self._achievements.delete_achievement(achievement)
|
||||
self._db.save_changes()
|
||||
|
||||
return achievement
|
@@ -50,6 +50,7 @@ class LevelMutation(QueryABC):
|
||||
and l.color == level.color
|
||||
and l.min_xp == level.min_xp
|
||||
and l.permissions == level.permissions
|
||||
and l.server.id == server.id
|
||||
)
|
||||
|
||||
self._bot.loop.create_task(self._level_seeder.seed())
|
||||
|
@@ -37,12 +37,13 @@ class UserMutation(QueryABC):
|
||||
user = self._users.get_user_by_id(input["id"])
|
||||
self._can_user_mutate_data(user.server, UserRoleEnum.moderator)
|
||||
|
||||
new_xp = None
|
||||
if "levelId" in input:
|
||||
level = self._levels.get_level_by_id(input["levelId"])
|
||||
if user.level.id != level.id:
|
||||
user.xp = level.min_xp
|
||||
else:
|
||||
user.xp = input["xp"] if "xp" in input else user.xp
|
||||
new_xp = level.min_xp
|
||||
|
||||
user.xp = new_xp if new_xp is not None else input["xp"] if "xp" in input else user.xp
|
||||
|
||||
self._users.update_user(user)
|
||||
self._db.save_changes()
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_graphql.queries"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
@@ -0,0 +1,11 @@
|
||||
from bot_graphql.abc.data_query_abc import DataQueryABC
|
||||
|
||||
|
||||
class AchievementAttributeQuery(DataQueryABC):
|
||||
def __init__(
|
||||
self,
|
||||
):
|
||||
DataQueryABC.__init__(self, "AchievementAttribute")
|
||||
|
||||
self.set_field("name", lambda x, *_: x.name)
|
||||
self.set_field("type", lambda x, *_: x.type)
|
14
kdb-bot/src/bot_graphql/queries/achievement_history_query.py
Normal file
14
kdb-bot/src/bot_graphql/queries/achievement_history_query.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from bot_graphql.abc.history_query_abc import HistoryQueryABC
|
||||
|
||||
|
||||
class AchievementHistoryQuery(HistoryQueryABC):
|
||||
def __init__(self):
|
||||
HistoryQueryABC.__init__(self, "Achievement")
|
||||
|
||||
self.set_field("id", lambda x, *_: x.id)
|
||||
self.set_field("name", lambda x, *_: x.name)
|
||||
self.set_field("description", lambda x, *_: x.description)
|
||||
self.set_field("attribute", lambda x, *_: x.attribute)
|
||||
self.set_field("operator", lambda x, *_: x.operator)
|
||||
self.set_field("value", lambda x, *_: x.value)
|
||||
self.set_field("server", lambda x, *_: x.server)
|
20
kdb-bot/src/bot_graphql/queries/achievement_query.py
Normal file
20
kdb-bot/src/bot_graphql/queries/achievement_query.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
|
||||
from bot_data.model.achievement_history import AchievementHistory
|
||||
from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC
|
||||
|
||||
|
||||
class AchievementQuery(DataQueryWithHistoryABC):
|
||||
def __init__(
|
||||
self,
|
||||
db: DatabaseContextABC,
|
||||
):
|
||||
DataQueryWithHistoryABC.__init__(self, "Achievement", "AchievementsHistory", AchievementHistory, db)
|
||||
|
||||
self.set_field("id", lambda x, *_: x.id)
|
||||
self.set_field("name", lambda x, *_: x.name)
|
||||
self.set_field("description", lambda x, *_: x.description)
|
||||
self.set_field("attribute", lambda x, *_: x.attribute)
|
||||
self.set_field("operator", lambda x, *_: x.operator)
|
||||
self.set_field("value", lambda x, *_: x.value)
|
||||
self.set_field("server", lambda x, *_: x.server)
|
@@ -15,7 +15,7 @@ __title__ = "bot_graphql.queries.discord"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.0.1"
|
||||
__version__ = "1.0.7"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="1")
|
||||
version_info = VersionInfo(major="1", minor="0", micro="7")
|
||||
|
10
kdb-bot/src/bot_graphql/queries/game_server_query.py
Normal file
10
kdb-bot/src/bot_graphql/queries/game_server_query.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from bot_graphql.abc.data_query_abc import DataQueryABC
|
||||
|
||||
|
||||
class GameServerQuery(DataQueryABC):
|
||||
def __init__(self):
|
||||
DataQueryABC.__init__(self, "GameServer")
|
||||
|
||||
self.set_field("id", lambda x, *_: x.id)
|
||||
self.set_field("name", lambda x, *_: x.name)
|
||||
self.set_field("server", lambda x, *_: x.server)
|
@@ -1,16 +1,18 @@
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
|
||||
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
|
||||
from bot_data.abc.client_repository_abc import ClientRepositoryABC
|
||||
from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC
|
||||
from bot_data.abc.level_repository_abc import LevelRepositoryABC
|
||||
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
|
||||
from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_data.model.server import Server
|
||||
from bot_data.model.server_history import ServerHistory
|
||||
from bot_graphql.abc.data_query_abc import DataQueryABC
|
||||
from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC
|
||||
from bot_graphql.filter.achievement_filter import AchievementFilter
|
||||
from bot_graphql.filter.auto_role_filter import AutoRoleFilter
|
||||
from bot_graphql.filter.client_filter import ClientFilter
|
||||
from bot_graphql.filter.level_filter import LevelFilter
|
||||
@@ -25,9 +27,11 @@ class ServerQuery(DataQueryWithHistoryABC):
|
||||
auto_roles: AutoRoleRepositoryABC,
|
||||
clients: ClientRepositoryABC,
|
||||
levels: LevelRepositoryABC,
|
||||
game_servers: GameServerRepositoryABC,
|
||||
users: UserRepositoryABC,
|
||||
ujs: UserJoinedServerRepositoryABC,
|
||||
ujvs: UserJoinedVoiceChannelRepositoryABC,
|
||||
achievements: AchievementRepositoryABC,
|
||||
):
|
||||
DataQueryWithHistoryABC.__init__(self, "Server", "ServersHistory", ServerHistory, db)
|
||||
|
||||
@@ -54,6 +58,10 @@ class ServerQuery(DataQueryWithHistoryABC):
|
||||
)
|
||||
self.add_collection("level", lambda server, *_: self._levels.get_levels_by_server_id(server.id), LevelFilter)
|
||||
self.add_collection("user", lambda server, *_: self._users.get_users_by_server_id(server.id), UserFilter)
|
||||
self.add_collection("gameServer", lambda server, *_: game_servers.get_game_servers_by_server_id(server.id))
|
||||
self.add_collection(
|
||||
"achievement", lambda server, *_: achievements.get_achievements_by_server_id(server.id), AchievementFilter
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def resolve_id(server: Server, *_):
|
||||
|
@@ -2,12 +2,14 @@ from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
|
||||
from bot_core.abc.client_utils_abc import ClientUtilsABC
|
||||
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||
from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC
|
||||
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
|
||||
from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC
|
||||
from bot_data.model.user import User
|
||||
from bot_data.model.user_history import UserHistory
|
||||
from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC
|
||||
from bot_graphql.filter.achievement_filter import AchievementFilter
|
||||
from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter
|
||||
from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter
|
||||
from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter
|
||||
@@ -26,6 +28,7 @@ class UserQuery(DataQueryWithHistoryABC):
|
||||
ujvs: UserJoinedVoiceChannelRepositoryABC,
|
||||
user_joined_game_server: UserJoinedGameServerRepositoryABC,
|
||||
permissions: PermissionServiceABC,
|
||||
achievements: AchievementRepositoryABC,
|
||||
):
|
||||
DataQueryWithHistoryABC.__init__(self, "User", "UsersHistory", UserHistory, db)
|
||||
|
||||
@@ -36,11 +39,14 @@ class UserQuery(DataQueryWithHistoryABC):
|
||||
self._ujs = ujs
|
||||
self._ujvs = ujvs
|
||||
self._permissions = permissions
|
||||
self._achievements = achievements
|
||||
|
||||
self.set_field("id", self.resolve_id)
|
||||
self.set_field("discordId", self.resolve_discord_id)
|
||||
self.set_field("name", self.resolve_name)
|
||||
self.set_field("xp", self.resolve_xp)
|
||||
self.set_field("messageCount", lambda x, *_: x.message_count)
|
||||
self.set_field("reactionCount", lambda x, *_: x.reaction_count)
|
||||
self.set_field("ontime", self.resolve_ontime)
|
||||
self.set_field("level", self.resolve_level)
|
||||
self.add_collection(
|
||||
@@ -58,6 +64,10 @@ class UserQuery(DataQueryWithHistoryABC):
|
||||
lambda user, *_: self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.id),
|
||||
UserJoinedGameServerFilter,
|
||||
)
|
||||
self.add_collection(
|
||||
"achievement", lambda user, *_: achievements.get_achievements_by_user_id(user.id), AchievementFilter
|
||||
)
|
||||
|
||||
self.set_field("server", self.resolve_server)
|
||||
self.set_field("leftServer", self.resolve_left_server)
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
|
||||
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
|
||||
from bot_data.abc.client_repository_abc import ClientRepositoryABC
|
||||
from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC
|
||||
from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC
|
||||
from bot_data.abc.level_repository_abc import LevelRepositoryABC
|
||||
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
@@ -10,6 +12,7 @@ from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepos
|
||||
from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_graphql.abc.query_abc import QueryABC
|
||||
from bot_graphql.filter.achievement_filter import AchievementFilter
|
||||
from bot_graphql.filter.auto_role_filter import AutoRoleFilter
|
||||
from bot_graphql.filter.auto_role_rule_filter import AutoRoleRuleFilter
|
||||
from bot_graphql.filter.client_filter import ClientFilter
|
||||
@@ -19,6 +22,7 @@ from bot_graphql.filter.user_filter import UserFilter
|
||||
from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter
|
||||
from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter
|
||||
from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter
|
||||
from modules.achievements.achievement_service import AchievementService
|
||||
|
||||
|
||||
class Query(QueryABC):
|
||||
@@ -30,10 +34,13 @@ class Query(QueryABC):
|
||||
known_users: KnownUserRepositoryABC,
|
||||
levels: LevelRepositoryABC,
|
||||
servers: ServerRepositoryABC,
|
||||
game_servers: GameServerRepositoryABC,
|
||||
user_joined_servers: UserJoinedServerRepositoryABC,
|
||||
user_joined_voice_channels: UserJoinedVoiceChannelRepositoryABC,
|
||||
user_joined_game_server: UserJoinedGameServerRepositoryABC,
|
||||
users: UserRepositoryABC,
|
||||
achievements: AchievementRepositoryABC,
|
||||
achievement_service: AchievementService,
|
||||
):
|
||||
QueryABC.__init__(self, "Query")
|
||||
|
||||
@@ -45,6 +52,7 @@ class Query(QueryABC):
|
||||
self.add_collection("knownUser", lambda *_: known_users.get_users())
|
||||
self.add_collection("level", lambda *_: levels.get_levels(), LevelFilter)
|
||||
self.add_collection("server", lambda *_: servers.get_servers(), ServerFilter)
|
||||
self.add_collection("gameServer", lambda *_: game_servers.get_game_servers())
|
||||
self.add_collection(
|
||||
"userJoinedServer", lambda *_: user_joined_servers.get_user_joined_servers(), UserJoinedServerFilter
|
||||
)
|
||||
@@ -59,8 +67,11 @@ class Query(QueryABC):
|
||||
UserJoinedGameServerFilter,
|
||||
)
|
||||
self.add_collection("user", lambda *_: users.get_users(), UserFilter)
|
||||
self.add_collection("achievement", lambda *_: achievements.get_achievements(), AchievementFilter)
|
||||
|
||||
self.set_field("guilds", self._resolve_guilds)
|
||||
self.set_field("achievementAttributes", lambda x, *_: achievement_service.get_attributes())
|
||||
self.set_field("achievementOperators", lambda x, *_: achievement_service.get_operators())
|
||||
|
||||
def _resolve_guilds(self, *_, filter=None):
|
||||
if filter is None or "id" not in filter:
|
||||
|
1
kdb-bot/src/modules/achievements/__init__.py
Normal file
1
kdb-bot/src/modules/achievements/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# imports
|
@@ -0,0 +1,50 @@
|
||||
from typing import List
|
||||
|
||||
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
|
||||
from bot_data.abc.client_repository_abc import ClientRepositoryABC
|
||||
from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC
|
||||
from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC
|
||||
from bot_data.abc.level_repository_abc import LevelRepositoryABC
|
||||
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC
|
||||
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
|
||||
from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_data.model.user import User
|
||||
|
||||
|
||||
class AchievementAttributeResolver:
|
||||
def __init__(
|
||||
self,
|
||||
auto_roles: AutoRoleRepositoryABC,
|
||||
clients: ClientRepositoryABC,
|
||||
known_users: KnownUserRepositoryABC,
|
||||
levels: LevelRepositoryABC,
|
||||
servers: ServerRepositoryABC,
|
||||
game_servers: GameServerRepositoryABC,
|
||||
user_joined_servers: UserJoinedServerRepositoryABC,
|
||||
user_joined_voice_channels: UserJoinedVoiceChannelRepositoryABC,
|
||||
user_joined_game_server: UserJoinedGameServerRepositoryABC,
|
||||
users: UserRepositoryABC,
|
||||
achievements: AchievementRepositoryABC,
|
||||
):
|
||||
self._auto_roles = auto_roles
|
||||
self._clients = clients
|
||||
self._known_users = known_users
|
||||
self._levels = levels
|
||||
self._servers = servers
|
||||
self._game_servers = game_servers
|
||||
self._user_joined_servers = user_joined_servers
|
||||
self._user_joined_voice_channels = user_joined_voice_channels
|
||||
self._user_joined_game_server = user_joined_game_server
|
||||
self._users = users
|
||||
self._achievements = achievements
|
||||
|
||||
def get_played_on_game_server(self, user: User) -> List[str]:
|
||||
joins = self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.id)
|
||||
return joins.select(lambda x: x.game_server.name)
|
||||
|
||||
def get_last_ontime_hours(self, user: User) -> int:
|
||||
ujvs = self._user_joined_voice_channels.get_user_joined_voice_channels_by_user_id(user.id)
|
||||
return int(str(ujvs.max(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600)))
|
116
kdb-bot/src/modules/achievements/achievement_service.py
Normal file
116
kdb-bot/src/modules/achievements/achievement_service.py
Normal file
@@ -0,0 +1,116 @@
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
from cpl_query.extension import List
|
||||
from cpl_translation import TranslatePipe
|
||||
|
||||
from bot_core.configuration.server_settings import ServerSettings
|
||||
from bot_core.service.message_service import MessageService
|
||||
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_data.model.achievement import Achievement
|
||||
from bot_data.model.user import User
|
||||
from bot_data.model.user_got_achievement import UserGotAchievement
|
||||
from modules.achievements.achievement_attribute_resolver import AchievementAttributeResolver
|
||||
from modules.achievements.model.achievement_attribute import AchievementAttribute
|
||||
from modules.base.configuration.base_server_settings import BaseServerSettings
|
||||
|
||||
|
||||
class AchievementService:
|
||||
def __init__(
|
||||
self,
|
||||
config: ConfigurationABC,
|
||||
logger: LoggerABC,
|
||||
bot: DiscordBotServiceABC,
|
||||
achievements: AchievementRepositoryABC,
|
||||
users: UserRepositoryABC,
|
||||
db: DatabaseContextABC,
|
||||
message_service: MessageService,
|
||||
resolver: AchievementAttributeResolver,
|
||||
t: TranslatePipe,
|
||||
):
|
||||
self._config = config
|
||||
self._logger = logger
|
||||
self._bot = bot
|
||||
self._achievements = achievements
|
||||
self._users = users
|
||||
self._db = db
|
||||
self._message_service = message_service
|
||||
self._t = t
|
||||
|
||||
self._attributes = List(AchievementAttribute)
|
||||
|
||||
self._attributes.extend(
|
||||
[
|
||||
AchievementAttribute("xp", lambda user: user.xp, "number"),
|
||||
AchievementAttribute("message_count", lambda user: user.message_count, "number"),
|
||||
AchievementAttribute("reaction_count", lambda user: user.reaction_count, "number"),
|
||||
AchievementAttribute("ontime", lambda user: user.ontime, "number"),
|
||||
AchievementAttribute("level", lambda user: user.level, "Level"),
|
||||
# special cases
|
||||
AchievementAttribute(
|
||||
"played_on_game_server", lambda user: resolver.get_played_on_game_server(user), "GameServer"
|
||||
),
|
||||
AchievementAttribute(
|
||||
"last_single_ontime_hours", lambda user: resolver.get_last_ontime_hours(user), "number"
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
self._operators = {
|
||||
"==": lambda value, expected_value: value == expected_value,
|
||||
"!=": lambda value, expected_value: value != expected_value,
|
||||
"<=": lambda value, expected_value: value <= expected_value,
|
||||
">=": lambda value, expected_value: value >= expected_value,
|
||||
"<": lambda value, expected_value: value < expected_value,
|
||||
">": lambda value, expected_value: value > expected_value,
|
||||
"contains": lambda value, expected_value: expected_value in value,
|
||||
}
|
||||
|
||||
def add_achievement_attribute(self, atr: AchievementAttribute):
|
||||
self._attributes.add(atr)
|
||||
|
||||
def get_operators(self) -> list[str]:
|
||||
return [x for x in self._operators.keys()]
|
||||
|
||||
def get_attributes(self) -> List[AchievementAttribute]:
|
||||
return self._attributes
|
||||
|
||||
def _match(self, value: any, operator: str, expected_value: str) -> bool:
|
||||
return self._operators[operator](str(value), expected_value)
|
||||
|
||||
def has_user_achievement_already(self, user: User, achievement: Achievement) -> bool:
|
||||
user_achievements = self._achievements.get_achievements_by_user_id(user.id)
|
||||
return user_achievements.where(lambda x: x.name == achievement.name).count() > 0
|
||||
|
||||
def has_user_achievement(self, user: User, achievement: Achievement) -> bool:
|
||||
attribute: AchievementAttribute = self._attributes.where(lambda x: x.name == achievement.attribute).single()
|
||||
return self._match(attribute.resolve(user), achievement.operator, achievement.value)
|
||||
|
||||
async def validate_achievements_for_user(self, user: User):
|
||||
achievements = self._achievements.get_achievements_by_server_id(user.server.id)
|
||||
for achievement in achievements:
|
||||
if self.has_user_achievement_already(user, achievement) or not self.has_user_achievement(user, achievement):
|
||||
continue
|
||||
|
||||
self._achievements.add_user_got_achievement(UserGotAchievement(user, achievement, user.server))
|
||||
self._db.save_changes()
|
||||
self._give_user_xp(user)
|
||||
await self._send_achievement_notification(user.server.discord_id, user.discord_id, achievement.name)
|
||||
|
||||
def _give_user_xp(self, user: User):
|
||||
settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{user.server.discord_id}")
|
||||
user.xp += settings.xp_per_achievement
|
||||
self._users.update_user(user)
|
||||
self._db.save_changes()
|
||||
|
||||
async def _send_achievement_notification(self, guild_id: int, member_id: int, achievement_name: str):
|
||||
member = self._bot.get_guild(guild_id).get_member(member_id)
|
||||
|
||||
settings: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild_id}")
|
||||
await self._message_service.send_channel_message(
|
||||
self._bot.get_channel(settings.notification_chat_id),
|
||||
self._t.transform("modules.achievements.got_new_achievement").format(member.mention, achievement_name),
|
||||
is_persistent=True,
|
||||
)
|
44
kdb-bot/src/modules/achievements/achievements.json
Normal file
44
kdb-bot/src/modules/achievements/achievements.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"ProjectSettings": {
|
||||
"Name": "achievements",
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "1",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
"Description": "Keksdose bot - achievements",
|
||||
"LongDescription": "Discord bot for the Keksdose discord Server - achievements module",
|
||||
"URL": "https://www.sh-edraft.de",
|
||||
"CopyrightDate": "2023",
|
||||
"CopyrightName": "sh-edraft.de",
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"cpl-core>=2023.4.0.post2"
|
||||
],
|
||||
"DevDependencies": [
|
||||
"cpl-cli>=2023.4.0.post3"
|
||||
],
|
||||
"PythonVersion": ">=3.10.4",
|
||||
"PythonPath": {},
|
||||
"Classifiers": []
|
||||
},
|
||||
"BuildSettings": {
|
||||
"ProjectType": "library",
|
||||
"SourcePath": "",
|
||||
"OutputPath": "../../dist",
|
||||
"Main": "achievements.main",
|
||||
"EntryPoint": "achievements",
|
||||
"IncludePackageData": false,
|
||||
"Included": [],
|
||||
"Excluded": [
|
||||
"*/__pycache__",
|
||||
"*/logs",
|
||||
"*/tests"
|
||||
],
|
||||
"PackageData": {},
|
||||
"ProjectReferences": []
|
||||
}
|
||||
}
|
28
kdb-bot/src/modules/achievements/achievements_module.py
Normal file
28
kdb-bot/src/modules/achievements/achievements_module.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceCollectionABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum
|
||||
from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
|
||||
|
||||
from bot_core.abc.module_abc import ModuleABC
|
||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
from modules.achievements.achievement_attribute_resolver import AchievementAttributeResolver
|
||||
from modules.achievements.achievement_service import AchievementService
|
||||
from modules.achievements.commands.achievements_group import AchievementGroup
|
||||
from modules.achievements.events.achievement_on_message_event import AchievementOnMessageEvent
|
||||
|
||||
|
||||
class AchievementsModule(ModuleABC):
|
||||
def __init__(self, dc: DiscordCollectionABC):
|
||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.auto_role_module)
|
||||
|
||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||
pass
|
||||
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
services.add_transient(AchievementAttributeResolver)
|
||||
services.add_transient(AchievementService)
|
||||
|
||||
self._dc.add_command(AchievementGroup)
|
||||
|
||||
self._dc.add_event(DiscordEventTypesEnum.on_message.value, AchievementOnMessageEvent)
|
1
kdb-bot/src/modules/achievements/commands/__init__.py
Normal file
1
kdb-bot/src/modules/achievements/commands/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# imports
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user