123 Commits

Author SHA1 Message Date
a869ee4780 Merge pull request '#293_complaints' (#326) from #293_complaints into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#326
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-08-14 09:37:08 +02:00
5776854494 Merge branch '1.1.0' into #293_complaints 2023-08-14 09:36:27 +02:00
5c820214a1 Merge pull request '#268_achievements' (#325) from #268_achievements into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#325
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-08-14 09:36:20 +02:00
f11d9af6c7 Fixed workspace #268_achievements 2023-08-14 09:35:46 +02:00
bff435d51e Added bug report #293_complaints 2023-07-18 11:43:50 +02:00
0f67bf467a Improved complaint command #293_complaints 2023-07-18 11:30:05 +02:00
2c7e5edbd7 [UNTESTED] Added complaint command #293_complaints 2023-07-18 11:15:20 +02:00
0846bbb29b Added achievements to data integrity service #268_achievements 2023-07-18 11:14:29 +02:00
926323252a Add xp for achievement #268_achievements 2023-07-18 11:06:12 +02:00
fedf2f4b8b Added description to achievements #268_achievements 2023-07-18 11:06:12 +02:00
4d4320dbcd Added history for achievements to frontend #268_achievements 2023-07-18 11:06:12 +02:00
c0b7e0913c Fixed achievements in user profile #268_achievements 2023-07-18 11:06:12 +02:00
9dcb75109f Added achievements to user profile #268_achievements 2023-07-18 11:06:12 +02:00
67baf350fa Added last_single_ontime_hours achievement logic #268_achievements 2023-07-18 11:06:12 +02:00
642a4d4dac Added played_on_game_server achievement logic #268_achievements 2023-07-18 11:06:12 +02:00
6b86cc3ca8 Improved generic achievement logic #268_achievements 2023-07-18 11:06:11 +02:00
fd10614b20 Improved internal achievement checks #268_achievements 2023-07-18 11:06:11 +02:00
0ec67d41e2 Added logic to make achievement config more generic #268_achievements 2023-07-18 11:06:11 +02:00
51928dcb4d Fixed config #268_achievements 2023-07-18 11:06:11 +02:00
e36f0b8c76 Improved achievement logic #268_achievements 2023-07-18 11:06:11 +02:00
2578c47c44 Improved achievement endpoint #268_achievements 2023-07-18 11:06:11 +02:00
dda2e2f5f6 Improved achievement component #268_achievements 2023-07-18 11:06:11 +02:00
8aa96482c1 Fixed server cache & improved frontend implementation #268_achievements 2023-07-18 11:06:11 +02:00
109bbf3729 First step to add achievements to frontend #268_achievements 2023-07-18 11:06:11 +02:00
3db548fb86 Fixed achievement query #268_achievements 2023-07-18 11:06:11 +02:00
0e5ec588fc Fixed achievement query #268_achievements 2023-07-18 11:06:11 +02:00
2c9434396d Added achievement gql endpoint [UNTESTED] #268_achievements 2023-07-18 11:06:11 +02:00
a49188b412 Fixed models #268_achievements 2023-07-18 11:06:11 +02:00
9e9879497a Added achievement data model #268_achievements 2023-07-18 11:06:11 +02:00
95e766d023 Merge pull request '#292_shutdown_procedure' (#321) from #292_shutdown_procedure into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#321
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #292
2023-07-18 11:03:16 +02:00
e25c29b2a6 Merge branch '1.1.0' into #292_shutdown_procedure 2023-07-18 11:03:00 +02:00
1dd6db4c85 Merge pull request 'Fixed gql playground' (#322) from 1.1.0_fix_playground into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#322
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-06-26 10:27:51 +02:00
9a51e51235 Fixed gql playground 2023-06-18 18:51:36 +02:00
fe5f3ced39 Merge branch '1.1.0' into #292_shutdown_procedure 2023-06-16 10:40:18 +02:00
c1ec7dd97b Merge pull request 'Updated packages #297_cpl_update' (#320) from #297_cpl_update into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#320
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-06-16 10:39:33 +02:00
09771ac2a3 Ensure bot shutdown before data checks #292_shutdown_procedure 2023-06-14 11:48:49 +02:00
6f27ce7bbc Improved open voice state check #292_shutdown_procedure 2023-06-14 09:34:31 +02:00
806144d9d3 Added data integrity check to shutdown #292_shutdown_procedure 2023-06-14 09:29:07 +02:00
877af6b945 Moved data integrity check #292_shutdown_procedure 2023-06-14 09:25:54 +02:00
979e0a0e6f Removed comments #297_cpl_update 2023-06-14 09:00:19 +02:00
fdf10f2728 Updated cpl-discord #297_cpl_update 2023-06-13 16:24:38 +02:00
f7ffd78dcc Updated stuff #297_cpl_update 2023-06-13 16:16:52 +02:00
8ddb9f087a Updated packages #297_cpl_update 2023-06-12 20:52:01 +02:00
0ca3be478b Merge pull request 'Added reaction channel null check #318' (#319) from #318 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#319
2023-06-08 08:48:31 +02:00
bd8bd40863 Added reaction channel null check #318 2023-06-08 08:47:56 +02:00
ff009ffb61 Merge pull request 'support' (#316) from support into master
Reviewed-on: sh-edraft.de/kd_discord_bot#316
2023-04-18 22:23:59 +02:00
074b03eecf Merge branch 'master' into support 2023-04-18 22:23:51 +02:00
5ea698ef97 Build 1.0.7 patch 2023-04-14 23:28:56 +02:00
400e54a501 Merge pull request 'Als Nutzer des WI möchte ich nicht, dass Tabellen mit vielen Daten so lange laden #300' (#312) from #300 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#312
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #300
2023-04-14 23:25:39 +02:00
3c0233e8b3 Merge pull request 'Fixed closed navbar #307' (#311) from #307 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#311
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #307
2023-04-14 23:25:30 +02:00
8d2ae38d85 Set frontend version #300 2023-04-14 22:02:01 +02:00
2b866b5ab1 Improved level data loading #300 2023-04-14 22:01:06 +02:00
4da87ae3cb Improved auto-role data loading #300 2023-04-14 21:56:02 +02:00
1ebad89c97 Improved members data loading #300 2023-04-14 21:46:01 +02:00
b8320c83fe Fixed closed navbar #307 2023-04-14 21:09:03 +02:00
0ee26ccf3d Merge pull request 'Fixed register re nav #306' (#308) from #306 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#308
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-04-12 22:08:31 +02:00
31ca9cd8f4 Merge pull request 'Fixed is ready function #309' (#310) from #309 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#310
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-04-12 22:08:25 +02:00
089de53136 Fixed is ready function #309 2023-04-12 22:04:49 +02:00
280b22af55 Fixed register re nav #306 2023-04-12 21:43:45 +02:00
ebdf375283 Merge pull request 'Added level checks #304' (#305) from #304 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#305
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #304
2023-04-12 21:20:52 +02:00
c058312af7 Merge branch 'support' into #304 2023-04-12 21:02:40 +02:00
2befa921ea Added level on reaction handling #304 2023-04-12 21:02:18 +02:00
1792359e68 Merge pull request 'support' (#303) from support into master
Reviewed-on: sh-edraft.de/kd_discord_bot#303
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-04-12 20:20:20 +02:00
faaf14d63e Merge branch 'master' into support 2023-04-12 20:19:26 +02:00
49d1ec75c8 Build new patch version 2023-04-12 20:10:34 +02:00
629556b5fc Merge pull request 'Potentially fixed bug to kill web api on restart #301' (#302) from #301 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#302
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #301
2023-04-12 20:09:05 +02:00
9ece541e52 Fixed log message #301 2023-04-12 20:06:30 +02:00
fd51db8cac Merge branch 'support' into #301 2023-04-10 13:15:41 +02:00
2005d93f44 Merge pull request 'support in master' (#299) from support into master
Reviewed-on: sh-edraft.de/kd_discord_bot#299
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-04-10 13:15:32 +02:00
010dafc655 Potentially fixed bug to kill web api on restart #301 2023-04-10 00:13:09 +02:00
bea9dd1590 Merge branch 'master' into support 2023-04-09 20:04:54 +02:00
ef0da25f11 Improved license 2023-04-03 10:05:26 +02:00
c01a6b97fe Build patch version 2023-04-03 07:59:30 +02:00
059bd3aaf1 Build patch version 2023-04-03 07:56:25 +02:00
a9d180fdf1 Fixed last api changes 2023-04-03 07:53:24 +02:00
c71b1092f2 Merge pull request '#290' (#291) from #290 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#291
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #290
2023-04-02 21:17:30 +02:00
c1e8274f46 Set async mode in web api #290 2023-04-02 18:32:34 +02:00
583218b215 Set async mode in web api #290 2023-04-02 14:41:05 +02:00
e05e67785b Build patched version 2023-03-31 12:25:37 +02:00
72d3ccded3 Merge pull request 'Fixed reaction handling #287' (#288) from 1.0.4 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#288
Closes #287
2023-03-31 12:04:09 +02:00
f30bd119df Fixed reaction handling #287 2023-03-31 12:03:07 +02:00
858fc062b3 Merge pull request '1.0.3 #285' (#286) from 1.0.3 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#286
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #285
2023-03-30 16:55:32 +02:00
6d622a70d3 Build patch version 2023-03-30 14:45:37 +02:00
4a0a6a4631 Improved logging to app end 2023-03-30 14:43:21 +02:00
17c2acd77c Improved logging to app end 2023-03-30 14:37:02 +02:00
27363522d3 Fixed xp input #285 2023-03-30 14:29:31 +02:00
1960b18058 Improved level service 2023-03-30 14:23:29 +02:00
91034cee09 Merge pull request '1.0.2 #283' (#284) from 1.0.2 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#284
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #283
2023-03-29 23:06:51 +02:00
a4d3cffa93 Removed test logs 2023-03-29 23:05:41 +02:00
809c6d4cb9 Build patch version 2023-03-29 22:59:40 +02:00
2fecbf2c31 Added cache service to cache server 2023-03-29 22:58:32 +02:00
c439d5925f Merge pull request '1.0.1' (#278) from 1.0.1 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#278
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-03-29 21:00:02 +02:00
1777a32899 Merge pull request '#281' (#282) from #281 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#282
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #281
2023-03-29 19:45:10 +02:00
3e5301b2d8 Merge branch '1.0.1' into #281 2023-03-29 19:39:04 +02:00
653562b908 idk #281 2023-03-29 19:38:42 +02:00
8025c31339 Set xp by level only when incoming level is different from user level #281 2023-03-29 19:38:25 +02:00
ccf41bec79 Retry select after half a second 2023-03-29 15:17:19 +02:00
f75d8f2068 Merge pull request 'Fixed reaction handling #279' (#280) from #279 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#280
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #279
2023-03-29 14:53:49 +02:00
da02aca7e4 Fixed reaction handling #279 2023-03-29 14:52:36 +02:00
3762f16c7e Merge pull request 'Fixed remove warning team notification #270' (#271) from #270 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#271
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #270
2023-03-28 23:39:41 +02:00
b3099121ab Build bot version #270 2023-03-28 23:36:33 +02:00
6a750ee31b Set bot version #270 2023-03-28 23:36:06 +02:00
3c371ec074 Set correct frontend version #270 2023-03-28 23:34:42 +02:00
d818eafb9d Merge branch '1.0.1' into #270 2023-03-28 23:30:32 +02:00
b4a5fdb258 Merge pull request 'Fixed unnecessary voice states #274' (#275) from #274 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#275
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #274
2023-03-28 23:29:47 +02:00
cf69436168 Merge pull request 'Fixed can_user_see_element #272' (#273) from #272 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#273
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #272
2023-03-28 23:29:35 +02:00
ccf171e876 Merge pull request 'Fixed id access #266' (#267) from #266 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#267
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #266
2023-03-28 23:29:22 +02:00
5a312bf660 Merge pull request 'Als Admin möchte ich, dass bei Erstellung einer AutoRollen Regel die Reaktion automatisch hinzugefügt wird #259' (#263) from #259 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#263
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #259
2023-03-28 23:29:05 +02:00
0003255d7c Merge branch '1.0.1' into #274 2023-03-28 18:24:21 +02:00
27a4c140e4 Fixed unnecessary voice states #274 2023-03-28 18:23:45 +02:00
3183461195 Merge branch '1.0.1' into #272 2023-03-28 15:46:14 +02:00
cb4f8d870c Fixed can_user_see_element #272 2023-03-28 15:45:38 +02:00
7c447bb0f2 Set frontend version for patch version #270 2023-03-28 15:04:20 +02:00
4debe4e2ba Fixed remove warning team notification #270 2023-03-28 15:01:35 +02:00
3cd3df3e5f Merge branch '1.0.1' into #266 2023-03-27 19:46:51 +02:00
b4a631d4e4 Fixed id access #266 2023-03-27 19:46:10 +02:00
7ba0247519 Merge pull request 'Fixed dropdown color #260' (#262) from #260 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#262
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #260
2023-03-27 19:35:30 +02:00
209e75fdcc Merge pull request 'Disabled add button for mods in level list #264' (#265) from #264 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#265
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #264
2023-03-27 19:35:04 +02:00
3bca3f86eb Disabled add button for mods in level list #264 2023-03-27 19:33:22 +02:00
657a8fa586 Added comment #259 2023-03-27 10:17:56 +02:00
3c8a092f40 Added logic to add reaction after creating auto role rule in WI #259 2023-03-27 10:17:55 +02:00
61bf508cea Fixed dropdown color #260 2023-03-27 10:04:18 +02:00
75ad07477a Merge pull request '1.0.0' (#253) from 1.0.0 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#253
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-03-27 09:30:49 +02:00
206 changed files with 3596 additions and 764 deletions

View File

@@ -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.

View File

@@ -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",

View File

@@ -15,7 +15,7 @@ __title__ = "bot"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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

View File

@@ -4,7 +4,7 @@
"Version": {
"Major": "1",
"Minor": "0",
"Micro": "0"
"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",

View File

@@ -15,7 +15,7 @@ __title__ = "bot.extension"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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:

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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": {

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.abc"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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")

View File

@@ -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)

View File

@@ -4,7 +4,7 @@
"Version": {
"Major": "1",
"Minor": "0",
"Micro": "0"
"Micro": "7"
},
"Author": "",
"AuthorEmail": "",

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.configuration"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.controller"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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)

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.event"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.exception"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.filter"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.logging"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.model"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.route"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.service"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.transformer"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.abc"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -2,9 +2,11 @@ from abc import ABC, abstractmethod
from datetime import datetime
from typing import Callable
import discord
from cpl_query.extension import List
from discord.ext.commands import Context
from bot_data.model.auto_role_rule import AutoRoleRule
from bot_data.model.user import User
from modules.base.configuration.base_server_settings import BaseServerSettings
@@ -59,3 +61,9 @@ class ClientUtilsABC(ABC):
@abstractmethod
def get_ontime_for_user(self, user: User) -> float:
pass
@abstractmethod
async def react_to_message_by_auto_role_rule(
self, discord_channel_id: int, discord_message_id: int, rule: AutoRoleRule, guild: discord.Guild
):
pass

View File

@@ -25,7 +25,9 @@ class MessageServiceABC(ABC):
self,
channel: discord.TextChannel,
message: Union[str, discord.Embed],
without_tracking=True,
is_persistent: bool = False,
wait_before_delete: int = None,
without_tracking=False,
):
pass

View File

@@ -4,7 +4,7 @@
"Version": {
"Major": "1",
"Minor": "0",
"Micro": "0"
"Micro": "7"
},
"Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de",

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.configuration"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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:
files = List(FileLoggingSettings)
for s in settings:
st = FileLoggingSettings()
settings[s]["Key"] = s
st.from_dict(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)
def _files_from_dict(self, settings: dict):
files = List(FileLoggingSettings)
for s in settings:
settings[s]["Key"] = s
st = JSONProcessor.process(FileLoggingSettings, settings[s])
files.append(st)
self._files = files

View File

@@ -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")
def _servers_from_dict(self, settings: dict):
servers = List(ServerSettings)
for s in settings:
settings[s]["id"] = int(s)
st = JSONProcessor.process(ServerSettings, settings[s])
servers.append(st)
self._servers = servers
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()}")
# 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()}")

View File

@@ -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"

View File

@@ -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

View File

@@ -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()}")

View File

@@ -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()}")

View File

@@ -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.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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)

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.events"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.exception"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.helper"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.logging"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.pipes"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.service"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -9,6 +9,7 @@ from cpl_core.time import TimeFormatSettings
from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List
from cpl_translation import TranslatePipe
from discord import Guild
from discord.ext.commands import Context
from bot_core.abc.client_utils_abc import ClientUtilsABC
@@ -23,6 +24,7 @@ from bot_data.abc.user_joined_voice_channel_repository_abc import (
from bot_data.abc.user_message_count_per_hour_repository_abc import (
UserMessageCountPerHourRepositoryABC,
)
from bot_data.model.auto_role_rule import AutoRoleRule
from bot_data.model.user import User
from bot_data.model.user_message_count_per_hour import UserMessageCountPerHour
from modules.base.configuration.base_server_settings import BaseServerSettings
@@ -192,3 +194,27 @@ class ClientUtilsService(ClientUtilsABC):
.sum(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600),
2,
)
async def react_to_message_by_auto_role_rule(
self, discord_channel_id: int, discord_message_id: int, rule: AutoRoleRule, guild: discord.Guild
):
try:
guild: Guild = self._bot.guilds.where(lambda g: g == guild).single()
channel = guild.get_channel(discord_channel_id)
message = await channel.fetch_message(discord_message_id)
emoji = List(discord.Emoji, guild.emojis).where(lambda x: x.name == rule.emoji_name).single()
if emoji is None:
self._logger.debug(__name__, f"Emoji {rule.emoji_name} not found")
return
await message.add_reaction(emoji)
self._logger.debug(
__name__,
f"Added reaction {rule.emoji_name} to message: {discord_message_id}",
)
except Exception as e:
self._logger.error(
__name__,
f"Cannot add reaction {rule.emoji_name} to message: {discord_message_id}",
e,
)

View 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()

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data.abc"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View 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

View File

@@ -4,7 +4,7 @@
"Version": {
"Major": "1",
"Minor": "0",
"Micro": "0"
"Micro": "7"
},
"Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de",

View File

@@ -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)

View File

@@ -1,3 +1,5 @@
import time
from cpl_core.database import DatabaseSettings
from cpl_core.database.context import DatabaseContext
@@ -9,6 +11,7 @@ class DBContext(DatabaseContext):
self._logger = logger
DatabaseContext.__init__(self)
self._fails = 0
def connect(self, database_settings: DatabaseSettings):
try:
@@ -30,5 +33,14 @@ 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)
except Exception as e:
pass
return []

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data.migration"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View 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;"""))

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data.model"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View 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};
"""
)

View 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

View File

@@ -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};
"""
)

View 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};
"""
)

View File

@@ -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

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data.service"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View 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)

View 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)

View File

@@ -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)}",

View File

@@ -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],
)

View File

@@ -15,7 +15,7 @@ __title__ = "bot_graphql"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_graphql.abc"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -135,7 +135,7 @@ class QueryABC(ObjectType):
u: User = u
guild = bot.get_guild(u.server.discord_id)
member = guild.get_member(u.discord_id)
if u.id == element.id or permissions.is_member_moderator(member):
if u.id == element.user.id or permissions.is_member_moderator(member):
access = True
break
@@ -144,7 +144,7 @@ class QueryABC(ObjectType):
u: User = u
guild = bot.get_guild(u.server.discord_id)
member = guild.get_member(u.discord_id)
if u.id == element.id or permissions.is_member_moderator(member):
if u.id == element.user.id or permissions.is_member_moderator(member):
access = True
break
@@ -153,7 +153,7 @@ class QueryABC(ObjectType):
u: User = u
guild = bot.get_guild(u.server.discord_id)
member = guild.get_member(u.discord_id)
if u.id == element.id or permissions.is_member_moderator(member):
if u.id == element.user.id or permissions.is_member_moderator(member):
access = True
break

View File

@@ -4,7 +4,7 @@
"Version": {
"Major": "1",
"Minor": "0",
"Micro": "0"
"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.0"
"cpl-core==2022.12.0"
],
"DevDependencies": [
"cpl-cli>=1.0.0"
"cpl-core==2022.12.0"
],
"PythonVersion": ">=3.10.4",
"PythonPath": {},

View File

@@ -15,7 +15,7 @@ __title__ = "bot_graphql.filter"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View 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

View File

@@ -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)

View 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
}

View File

@@ -4,4 +4,5 @@ type Mutation {
level: LevelMutation
user: UserMutation
userJoinedGameServer: UserJoinedGameServerMutation
achievement: AchievementMutation
}

View File

@@ -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]
}

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -15,7 +15,7 @@ __title__ = "bot_graphql.mutations"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View 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

View File

@@ -1,5 +1,7 @@
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.auto_role_repository_abc import AutoRoleRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.model.auto_role_rule import AutoRoleRule
@@ -10,15 +12,19 @@ from bot_graphql.abc.query_abc import QueryABC
class AutoRoleRuleMutation(QueryABC):
def __init__(
self,
bot: DiscordBotServiceABC,
servers: ServerRepositoryABC,
auto_roles: AutoRoleRepositoryABC,
db: DatabaseContextABC,
client_utils: ClientUtilsABC,
):
QueryABC.__init__(self, "AutoRoleRuleMutation")
self._bot = bot
self._servers = servers
self._auto_roles = auto_roles
self._db = db
self._client_utils = client_utils
self.set_field("createAutoRoleRule", self.resolve_create_auto_role_rule)
self.set_field("updateAutoRoleRule", self.resolve_update_auto_role_rule)
@@ -40,6 +46,14 @@ class AutoRoleRuleMutation(QueryABC):
and x.role_id == int(input["roleId"])
)
self._bot.loop.create_task(
self._client_utils.react_to_message_by_auto_role_rule(
auto_role_rule.auto_role.discord_channel_id,
auto_role_rule.auto_role.discord_message_id,
auto_role_rule,
self._bot.get_guild(auto_role_rule.auto_role.server.discord_id),
)
)
return self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role_rule.auto_role.id).where(get_new).last()
def resolve_update_auto_role_rule(self, *_, input: dict):
@@ -53,6 +67,14 @@ class AutoRoleRuleMutation(QueryABC):
self._db.save_changes()
auto_role_rule = self._auto_roles.get_auto_role_rule_by_id(input["id"])
self._bot.loop.create_task(
self._client_utils.react_to_message_by_auto_role_rule(
auto_role_rule.auto_role.discord_channel_id,
auto_role_rule.auto_role.discord_message_id,
auto_role_rule,
self._bot.get_guild(auto_role_rule.auto_role.server.discord_id),
)
)
return auto_role_rule
def resolve_delete_auto_role_rule(self, *_, id: int):

View File

@@ -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())

View File

@@ -37,11 +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"])
user.xp = level.min_xp
else:
user.xp = input["xp"] if "xp" in input else user.xp
if user.level.id != level.id:
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()

View File

@@ -15,7 +15,7 @@ __title__ = "bot_graphql.queries"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.0.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View File

@@ -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)

View 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)

View 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)

View File

@@ -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.0"
__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="0")
version_info = VersionInfo(major="1", minor="0", micro="7")

View 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)

View File

@@ -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, *_):

View File

@@ -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)

View File

@@ -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:

View File

@@ -0,0 +1 @@
# imports

Some files were not shown because too many files have changed in this diff Show More