167 Commits

Author SHA1 Message Date
42b71525bd Merge pull request '#133' (#224) from #133 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#224
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Reviewed-by: Jonas <joni.drescher@web.de>
2023-02-22 19:29:16 +01:00
b9d33c5fd0 Merge branch '1.0.0' into #133 2023-02-21 22:45:30 +01:00
9ea1b14852 Optimized code #133 2023-02-21 22:44:42 +01:00
2763f254af Merge pull request 'Fixed db null handling #219' (#229) from #219 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#229
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #219
2023-02-21 21:10:18 +01:00
f7dc8d135a Improved SQL statements #219 2023-02-21 21:08:51 +01:00
d42b76ba87 Improved SQL statements #219 2023-02-21 20:51:28 +01:00
0f26db3d74 Merge pull request 'Der Bot muss wohl zwei mal gestartet werden, damit er die DB richtig läd #214' (#231) from #214 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#231
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #214
2023-02-21 20:43:05 +01:00
d9d3f8c8b0 Merge pull request 'Fixed add xp to author of reacted message #218' (#230) from #218 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#230
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #218
2023-02-21 20:42:52 +01:00
23ee963d65 Fixed formattings #133 2023-02-21 17:29:08 +01:00
f3024d2ea5 Fixed changes of rebase #133 2023-02-21 17:24:18 +01:00
Jonas Drescher
e463b19a73 added level table 2023-02-21 17:11:56 +01:00
15214b1c99 Fixed user filter #133 2023-02-21 17:10:34 +01:00
Jonas Drescher
dfcd958965 WIP: levels table 2023-02-21 17:10:32 +01:00
9274be6bb7 Merge branch '1.0.0' into #218 2023-02-21 13:21:33 +01:00
ac1affa937 Fixed seeder and module order #214 2023-02-21 13:19:34 +01:00
4e722d9c47 Fixed add xp to author of reacted message #218 2023-02-21 12:47:20 +01:00
6585576266 Merge branch '1.0.0' into #219 2023-02-21 12:43:15 +01:00
8937243725 Fixed db null handling #219 2023-02-21 12:42:47 +01:00
c841f39a03 Merge pull request 'Added confirm dialog on first discord login #210' (#228) from #210 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#228
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #210
2023-02-21 12:12:30 +01:00
a3fa7cb7b9 Merge pull request 'Improved server loading by route #216' (#227) from #216 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#227
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #216
2023-02-21 12:12:20 +01:00
f38b517b98 Added confirm dialog on first discord login #210 2023-02-21 12:09:29 +01:00
7d450a12ac Improved server loading by route #216 2023-02-21 11:50:30 +01:00
0ea1edff4d Merge pull request 'Removed api url from env #217' (#226) from #217 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#226
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #217
2023-02-21 11:34:09 +01:00
70775111c5 Removed api url from env #217 2023-02-21 11:33:49 +01:00
f42f2086e7 Merge pull request 'Fixed notification on OnMemberJoin #191' (#225) from #191 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#225
2023-02-21 10:17:47 +01:00
1f3b12501b Fixed notification on OnMemberJoin #191 2023-02-21 10:16:16 +01:00
c0882a8ad3 Merge pull request 'AutoRole #134' (#222) from #134 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#222
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #134
2023-02-21 09:54:35 +01:00
75ab159539 Added typing #134 2023-02-20 22:46:18 +01:00
ec9bc80392 Finished auto role rules #134 2023-02-20 22:30:25 +01:00
02d04725bd Added auto role rule list logic #134 2023-02-20 21:32:46 +01:00
10d79f8c2c Prepared auto role rules #134 2023-02-20 21:32:46 +01:00
a2dcbbc465 Finished auto role list #134 2023-02-20 21:32:46 +01:00
81fe7433bd Improved settings #134 2023-02-20 21:32:46 +01:00
ed5564dc7c [WIP] Improved auto roles #134 2023-02-20 21:32:46 +01:00
e0ca057399 [WIP] Added auto roles list #134 2023-02-20 21:32:46 +01:00
8f95e196ec Merge pull request 'Removed statistic module #190' (#213) from #190 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#213
Reviewed-by: Sven Heidemann <sven.heidemann@sh-edraft.de>
Closes #190
2023-02-20 14:17:51 +01:00
16b2deec6b Added requested changes #190 2023-02-19 21:33:08 +01:00
85e664e642 Removed statistic module #190 2023-02-19 19:46:13 +01:00
64985f5983 Merge pull request 'Client in Webinterface anzeigen #80' (#211) from #80_show_info_of_client into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#211
Reviewed-by: Sven Heidemann <sven.heidemann@sh-edraft.de>
Closes #80
2023-02-19 18:02:45 +01:00
Jonas Drescher
02ed6eb75b deleted unused comments #80 2023-02-19 18:01:13 +01:00
Jonas Drescher
b615f2608f added translation #80 2023-02-19 17:59:59 +01:00
Jonas Drescher
bf776177d4 added clients to server-dashboard #80 2023-02-19 17:45:50 +01:00
Jonas Drescher
a2a0056873 min = 0 fix on xp inputfield 2023-02-19 14:49:53 +01:00
Jonas Drescher
eb18fdea46 added Jonas to settings 2023-02-19 14:36:07 +01:00
Jonas Drescher
6945cd2eac added Jonas to settings 2023-02-19 14:31:00 +01:00
ef040f2b91 Fixed permission check 2023-02-19 14:25:41 +01:00
ba4ef693da Merge pull request '#130' (#209) from #130 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#209
2023-02-19 12:00:14 +01:00
07f2c4921c Merge branch '1.0.0' into #130 2023-02-19 12:00:09 +01:00
96339ed168 Fixed some stuff for deployment #130 2023-02-19 11:59:02 +01:00
9667f40730 Merge pull request 'Set version for stage build #130' (#208) from #130 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#208
2023-02-19 11:10:59 +01:00
5a9ad77761 Updated config #130 2023-02-19 11:09:34 +01:00
e4d1e229eb Set version for stage build #130 2023-02-19 10:59:40 +01:00
299fc65d1f Merge pull request 'Set version to build for staging' (#207) from #130 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#207
2023-02-19 10:39:45 +01:00
aa38623633 Set version to build for staging 2023-02-19 10:37:56 +01:00
fd9d938b8a Set version to build for staging 2023-02-19 10:29:29 +01:00
efbe6efc20 Merge pull request 'Mitglieder auf einem Server anzeigen #130' (#206) from #130 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#206
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #130
2023-02-18 14:56:38 +01:00
da3680a83e Improved imports #130 2023-02-18 14:45:51 +01:00
610ce42fa2 Fixed styling & added game server to profile #130 2023-02-18 13:37:03 +01:00
6149825101 Fixed sorting with null values #130 2023-02-18 13:05:45 +01:00
7193e58ba1 Fixed dashboard server filter #130 2023-02-18 12:54:56 +01:00
38417bd712 Fixed auth user confirmed check #130 2023-02-18 12:49:14 +01:00
43b6df2ba3 Improved spinner logic and table design #130 2023-02-18 12:42:51 +01:00
7d67b08ce6 Added leftServer handling to members list #130 2023-02-18 12:14:04 +01:00
afff27b273 Improved db updates #130 2023-02-18 11:44:13 +01:00
de8262dae1 Improved sidebar handling & added minecraftId to profile #130 2023-02-18 11:34:33 +01:00
b96288f4a3 Added member profile #130 2023-02-18 10:44:19 +01:00
1ca6debc59 Fixed server view in sidebar #130 2023-02-18 10:22:31 +01:00
dfe4f28e24 Improved sorting #130 2023-02-18 10:22:31 +01:00
fea259fa3b Renamed type_id to id for sorting #130 2023-02-18 10:22:31 +01:00
85452c9a74 Added members view #130 2023-02-18 10:22:30 +01:00
f44f77d7e5 Improved sidebar #130 2023-02-18 10:20:15 +01:00
b15bcec20a Updated config #130 2023-02-18 10:19:47 +01:00
ee351ee749 Improved routing #130 2023-02-18 10:19:47 +01:00
f847841582 Added routing by permissions #130 2023-02-18 10:19:45 +01:00
e2ef4f3bde Merge pull request 'Login in WI möglich trotz nicht bestätigter mail #77' (#205) from #77 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#205
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #77
2023-02-16 22:18:20 +01:00
3456c5f021 Merge pull request 'Bonus XP wenn man an einem Event teilnimmt #167' (#202) from #167 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#202
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #167
2023-02-16 22:18:10 +01:00
065e8b0645 Merge branch '1.0.0' into #77 2023-02-16 22:02:59 +01:00
f04a6066a1 Merge branch '1.0.0' into #167 2023-02-16 22:01:38 +01:00
c0d1288aef Merge pull request 'Erstellt am & Zuletzt bearbeitet am in Benutzertabellen #78' (#204) from #78 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#204
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #78
2023-02-16 22:01:24 +01:00
c4507d3aa1 Merge branch '1.0.0' into #167 2023-02-16 21:45:10 +01:00
1039a58d4f Merge branch '1.0.0' into #77 2023-02-16 21:44:53 +01:00
ed4d41d424 Merge branch '1.0.0' into #78 2023-02-16 21:44:32 +01:00
645e84a8fa Merge pull request 'Externe ontime Quelle: Minecraft #181' (#200) from #181 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#200
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #181
2023-02-16 21:44:20 +01:00
b9087dccb3 Fixed copy&paste error #181 2023-02-16 21:43:47 +01:00
4bb486f1d5 Merge branch '1.0.0' into #181 2023-02-16 21:08:48 +01:00
8efd0fc993 Added logic to prevent login when email not confirmed #77 2023-02-16 17:12:41 +01:00
6c0b48a941 Added logic to show createdAt & modifiedAt in auth user list #78 2023-02-16 17:00:55 +01:00
77946cb3a8 Added logic to add bonus xp when joining the event channel #167 2023-02-13 23:15:04 +01:00
5953c82a9b Fixed formatting #167 2023-02-13 23:14:57 +01:00
6bf73fcf91 Added logic to save active events locally #167 2023-02-13 23:14:49 +01:00
3844240930 Fixed filter error #181 2023-02-13 22:21:18 +01:00
efa18944fe Edited my API config 2023-02-13 20:47:32 +01:00
f435d779a7 Merge branch '1.0.0' into #181 2023-02-12 21:44:42 +01:00
cd34d18205 Merge pull request 'Als Mitglied möchte ich anhand meiner Rechte Daten ändern können oder daran gehindert werden #198' (#199) from #198 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#199
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #198
2023-02-12 21:44:27 +01:00
9e2a0441d3 Merge branch '1.0.0' into #198 2023-02-12 20:36:05 +01:00
898e27550e Merge pull request 'Added logic to check if user is allowed to see requested data #89' (#197) from #89 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#197
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #89
2023-02-12 20:35:54 +01:00
60990db88d Fixed collection building #89 2023-02-12 20:33:28 +01:00
ce1cdd4017 Added user joined game server validation checks on start #181 2023-02-12 20:30:42 +01:00
9a8f8a13f6 Improved user joined game server mutation #181 2023-02-12 20:00:47 +01:00
667bb708d9 Improved user joined game server mutation #181 2023-02-12 19:47:27 +01:00
54cb6cf8a0 Fixed user filter #181 2023-02-12 17:42:59 +01:00
aa16847fbf Added minecraft register commands #181 2023-02-12 17:22:58 +01:00
2ef4d079ed Added minecraft id #181 2023-02-12 16:55:35 +01:00
bd4e088032 Added mutations for user joined game server #181 2023-02-12 16:39:26 +01:00
1e74584e71 Added user joined game server gql query #181 2023-02-12 16:16:17 +01:00
0b5acdea58 Added user joined game server model #181 2023-02-12 15:42:02 +01:00
91bbb2f2e9 Added permission check on data mutation #198 2023-02-12 14:59:20 +01:00
dd64435c65 Added logic to check if user is allowed to see requested data #89 2023-02-11 13:11:55 +01:00
84937dde0a Merge pull request 'Ausgewählter Server besser darstellen #131' (#196) from #131 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#196
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #131
2023-02-11 10:42:03 +01:00
ca5744ea39 Removed theme.css #131 2023-02-11 10:41:44 +01:00
f68bd875b5 Merge branch '1.0.0' into #131 2023-02-11 10:40:10 +01:00
429f8b2819 Merge pull request 'graphql part3/3 #162-3' (#194) from #162-3 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#194
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #162
2023-02-11 10:39:49 +01:00
7fb8b521e4 Merge branch '1.0.0' into #162-3 2023-02-11 10:38:51 +01:00
936b8e9cb6 Merge pull request 'graphql part2/3 #162-2' (#193) from #162-2 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#193
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-02-11 10:38:28 +01:00
1fa6f44f76 Merge branch '1.0.0' into #162-2 2023-02-11 10:38:20 +01:00
f04d40ce75 Readded browserlist #162-2 2023-02-11 10:37:09 +01:00
45a6b49cf5 Improved way to load and show server in sidebar #131 2023-02-11 10:34:46 +01:00
4822348e01 Improved way to load server for server dashboard #131 2023-02-11 10:34:35 +01:00
1d1fc8a876 Merge pull request 'GraphQL Part1 (gql endpoint only) #162' (#192) from #162 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#192
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-02-11 10:30:41 +01:00
a6df06f13a Added logic to create default api-key for frontend #162-3 2023-02-09 22:09:02 +01:00
7f14aff1bd Added api-key commands #162-3 2023-02-09 20:22:46 +01:00
d03ea1d970 Added ApiKeys to db #162-3 2023-02-09 19:29:25 +01:00
f144564806 Secured graphql playground #162-2 2023-02-09 18:29:19 +01:00
f7c27b77ee Added graphql support #162-2 2023-02-09 16:36:50 +01:00
6aca981fd1 [WIP] Switched from rest to GraphQL #162-2 2023-02-09 16:09:34 +01:00
4266db7e35 [WIP] Updated packages #162-2 2023-02-09 15:27:39 +01:00
667b9fa87e [WIP] Switched to gql #162-2 2023-02-09 15:19:31 +01:00
79837afdfb Removed server route #162-2 2023-02-09 14:32:38 +01:00
8273b2b98e Build frontend & fixed oauth scopes #162 2023-02-09 14:30:51 +01:00
eaa22efd08 Merge branch '1.0.0' into #162 2023-02-08 19:26:21 +01:00
b33c5dc9bf Fixed mutations #162 2023-02-08 19:24:07 +01:00
e9559dec08 Fixed queries #162 2023-02-08 19:10:56 +01:00
5d470be583 Changed from snake to camel case #162 2023-02-08 19:05:32 +01:00
1dfe7edcba Added services to di #162 2023-02-08 17:50:43 +01:00
af8c2dea60 Added mutations #162 2023-02-08 17:48:54 +01:00
23e238b7d5 Removed server from queries where user set #162 2023-02-08 12:34:47 +01:00
fde318b85d Improved filters & queries #162 2023-02-08 12:32:16 +01:00
93c60b9176 Improved filters #162 2023-02-08 12:05:02 +01:00
12f8f669ed Improved filters #162 2023-02-07 19:09:27 +01:00
36fd3c73b9 Added client filter #162 2023-02-07 18:58:09 +01:00
3f7cfc47af Finished auto role filter #162 2023-02-07 18:53:28 +01:00
eb58c34c4d Added auto role filter #162 2023-02-07 17:52:38 +01:00
e3c0a0dea3 Reformatted files with black #162 2023-02-07 17:07:25 +01:00
dbfae8d8a4 Added more gql filters #162 2023-02-07 17:07:14 +01:00
16066864ed Improved queries & filtering #162 2023-01-16 19:18:23 +01:00
807827e30f Improved queries & filtering #162 2023-01-16 15:13:45 +01:00
c75cc54d16 Improved queries #162 2023-01-15 17:47:40 +01:00
6a1ad1ec9f Added filters #162 2023-01-15 17:06:04 +01:00
8256ebed71 Added auto role query #162 2023-01-15 16:24:16 +01:00
eb7fce140a Added more queries #162 2023-01-15 11:00:00 +01:00
ebcf876457 Added more queries #162 2023-01-15 10:59:54 +01:00
5efb1da0b8 Added more queries #162 2023-01-15 10:59:25 +01:00
b9e66bba9d Added more queries #162 2023-01-15 10:36:09 +01:00
b8484185e9 Improved level stuff #162 2023-01-15 09:51:40 +01:00
552e686aeb Updated model #162 2023-01-15 02:37:35 +01:00
efb772094b Updated cpl-core #162 2023-01-15 02:35:39 +01:00
95b9eea236 Added graphql from prototype #162 2023-01-15 02:28:28 +01:00
b95a951a1b Merge branch 'prototype/graphql/ariadne' into #162
# Conflicts:
#	kdb-bot/cpl-workspace.json
#	kdb-bot/src/bot/config
#	kdb-bot/src/bot/module_list.py
#	kdb-bot/src/bot_api/api.py
#	kdb-bot/src/bot_data/service/client_repository_service.py
#	kdb-bot/src/bot_data/service/server_repository_service.py
2023-01-15 02:25:05 +01:00
df42acec26 Added mutations without saving data 2023-01-07 16:31:28 +01:00
44204f5b94 Improved query & filtering 2023-01-07 15:53:53 +01:00
ce85bb332a Improved query & filtering 2023-01-07 15:53:44 +01:00
7a836a7f59 Added filtering 2023-01-07 15:17:11 +01:00
dacb429d9b Moved graphql stuff to own lib 2023-01-07 12:41:22 +01:00
77e18027a0 Improved ariadne with DI 2023-01-06 23:18:40 +01:00
b13695b018 Moved to ariadne 2023-01-06 16:21:21 +01:00
75500076a7 Improved gql data layer 2023-01-06 14:47:45 +01:00
5455a6b359 Added first graphene models 2023-01-06 14:14:37 +01:00
330 changed files with 14708 additions and 9394 deletions

View File

@@ -0,0 +1,34 @@
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class query(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
def get_code(self) -> str:
import textwrap
code = textwrap.dedent(
"""\
from bot_graphql.abc.data_query_abc import DataQueryABC
class $ClassName(DataQueryABC):
def __init__(self):
DataQueryABC.__init__(self, "Name")
self.set_field("id", self.resolve_id)
@staticmethod
def resolve_id(x, *_):
return x.id
"""
)
return self.build_code_str(
code,
ClassName=self._class_name,
)
@classmethod
def register(cls):
GenerateSchematicABC.register(cls, "query", [])

View File

@@ -6,13 +6,13 @@
"bot-api": "src/bot_api/bot-api.json", "bot-api": "src/bot_api/bot-api.json",
"bot-core": "src/bot_core/bot-core.json", "bot-core": "src/bot_core/bot-core.json",
"bot-data": "src/bot_data/bot-data.json", "bot-data": "src/bot_data/bot-data.json",
"bot-graphql": "src/bot_graphql/bot-graphql.json",
"auto-role": "src/modules/auto_role/auto-role.json", "auto-role": "src/modules/auto_role/auto-role.json",
"base": "src/modules/base/base.json", "base": "src/modules/base/base.json",
"boot-log": "src/modules/boot_log/boot-log.json", "boot-log": "src/modules/boot_log/boot-log.json",
"database": "src/modules/database/database.json", "database": "src/modules/database/database.json",
"level": "src/modules/level/level.json", "level": "src/modules/level/level.json",
"permission": "src/modules/permission/permission.json", "permission": "src/modules/permission/permission.json",
"stats": "src/modules/stats/stats.json",
"technician": "src/modules/technician/technician.json", "technician": "src/modules/technician/technician.json",
"get-version": "tools/get_version/get-version.json", "get-version": "tools/get_version/get-version.json",
"post-build": "tools/post_build/post-build.json", "post-build": "tools/post_build/post-build.json",

View File

@@ -15,7 +15,7 @@ __title__ = "bot"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -2,9 +2,9 @@
"ProjectSettings": { "ProjectSettings": {
"Name": "bot", "Name": "bot",
"Version": { "Version": {
"Major": "0", "Major": "1",
"Minor": "3", "Minor": "0",
"Micro": "1" "Micro": "dev130"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de", "AuthorEmail": "sven.heidemann@sh-edraft.de",
@@ -16,22 +16,24 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"cpl-core==2022.12.1.post2", "cpl-core==2022.12.1.post3",
"cpl-translation==2022.12.1", "cpl-translation==2022.12.1",
"cpl-query==2022.12.2.post1", "cpl-query==2022.12.2.post1",
"cpl-discord==2022.12.1.post2",
"Flask==2.2.2", "Flask==2.2.2",
"Flask-Classful==0.14.2", "Flask-Classful==0.14.2",
"Flask-Cors==3.0.10", "Flask-Cors==3.0.10",
"PyJWT==2.6.0", "PyJWT==2.6.0",
"waitress==2.1.2", "waitress==2.1.2",
"Flask-SocketIO==5.3.2", "Flask-SocketIO==5.3.2",
"eventlet==0.33.2", "eventlet==0.33.3",
"requests-oauthlib==1.3.1", "requests-oauthlib==1.3.1",
"icmplib==3.0.3" "icmplib==3.0.3",
"ariadne==0.17.1",
"cpl-discord==2022.12.2"
], ],
"DevDependencies": [ "DevDependencies": [
"cpl-cli==2022.12.1.post2" "cpl-cli==2022.12.1.post3",
"pygount==1.5.1"
], ],
"PythonVersion": ">=3.10.4", "PythonVersion": ">=3.10.4",
"PythonPath": {}, "PythonPath": {},
@@ -55,13 +57,13 @@
"../bot_api/bot-api.json", "../bot_api/bot-api.json",
"../bot_core/bot-core.json", "../bot_core/bot-core.json",
"../bot_data/bot-data.json", "../bot_data/bot-data.json",
"../bot_graphql/bot-graphql.json",
"../modules/auto_role/auto-role.json", "../modules/auto_role/auto-role.json",
"../modules/base/base.json", "../modules/base/base.json",
"../modules/boot_log/boot-log.json", "../modules/boot_log/boot-log.json",
"../modules/database/database.json", "../modules/database/database.json",
"../modules/level/level.json", "../modules/level/level.json",
"../modules/permission/permission.json", "../modules/permission/permission.json",
"../modules/stats/stats.json",
"../modules/technician/technician.json" "../modules/technician/technician.json"
] ]
} }

View File

@@ -15,7 +15,7 @@ __title__ = "bot.extension"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -4,13 +4,13 @@ from bot_api.api_module import ApiModule
from bot_core.core_extension.core_extension_module import CoreExtensionModule from bot_core.core_extension.core_extension_module import CoreExtensionModule
from bot_core.core_module import CoreModule from bot_core.core_module import CoreModule
from bot_data.data_module import DataModule from bot_data.data_module import DataModule
from bot_graphql.graphql_module import GraphQLModule
from modules.auto_role.auto_role_module import AutoRoleModule from modules.auto_role.auto_role_module import AutoRoleModule
from modules.base.base_module import BaseModule from modules.base.base_module import BaseModule
from modules.boot_log.boot_log_module import BootLogModule from modules.boot_log.boot_log_module import BootLogModule
from modules.database.database_module import DatabaseModule from modules.database.database_module import DatabaseModule
from modules.level.level_module import LevelModule from modules.level.level_module import LevelModule
from modules.permission.permission_module import PermissionModule from modules.permission.permission_module import PermissionModule
from modules.stats.stats_module import StatsModule
from modules.technician.technician_module import TechnicianModule from modules.technician.technician_module import TechnicianModule
@@ -23,13 +23,13 @@ class ModuleList:
[ [
CoreModule, # has to be first! CoreModule, # has to be first!
DataModule, DataModule,
GraphQLModule,
PermissionModule, PermissionModule,
LevelModule,
DatabaseModule, DatabaseModule,
AutoRoleModule, AutoRoleModule,
BaseModule, BaseModule,
LevelModule,
ApiModule, ApiModule,
StatsModule,
TechnicianModule, TechnicianModule,
# has to be last! # has to be last!
BootLogModule, BootLogModule,

View File

@@ -4,12 +4,15 @@ from cpl_core.dependency_injection import ServiceCollectionABC
from cpl_core.environment import ApplicationEnvironmentABC from cpl_core.environment import ApplicationEnvironmentABC
from bot_data.abc.migration_abc import MigrationABC from bot_data.abc.migration_abc import MigrationABC
from bot_data.migration.api_key_migration import ApiKeyMigration
from bot_data.migration.api_migration import ApiMigration from bot_data.migration.api_migration import ApiMigration
from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration
from bot_data.migration.auto_role_migration import AutoRoleMigration from bot_data.migration.auto_role_migration import AutoRoleMigration
from bot_data.migration.initial_migration import InitialMigration from bot_data.migration.initial_migration import InitialMigration
from bot_data.migration.level_migration import LevelMigration from bot_data.migration.level_migration import LevelMigration
from bot_data.migration.remove_stats_migration import RemoveStatsMigration
from bot_data.migration.stats_migration import StatsMigration from bot_data.migration.stats_migration import StatsMigration
from bot_data.migration.user_joined_game_server_migration import UserJoinedGameServerMigration
from bot_data.migration.user_message_count_per_hour_migration import ( from bot_data.migration.user_message_count_per_hour_migration import (
UserMessageCountPerHourMigration, UserMessageCountPerHourMigration,
) )
@@ -32,3 +35,6 @@ class StartupMigrationExtension(StartupExtensionABC):
services.add_transient(MigrationABC, StatsMigration) # 09.11.2022 #46 - 0.3.0 services.add_transient(MigrationABC, StatsMigration) # 09.11.2022 #46 - 0.3.0
services.add_transient(MigrationABC, AutoRoleFix1Migration) # 30.12.2022 #151 - 0.3.0 services.add_transient(MigrationABC, AutoRoleFix1Migration) # 30.12.2022 #151 - 0.3.0
services.add_transient(MigrationABC, UserMessageCountPerHourMigration) # 11.01.2023 #168 - 0.3.1 services.add_transient(MigrationABC, UserMessageCountPerHourMigration) # 11.01.2023 #168 - 0.3.1
services.add_transient(MigrationABC, ApiKeyMigration) # 09.02.2023 #162 - 1.0.0
services.add_transient(MigrationABC, UserJoinedGameServerMigration) # 12.02.2023 #181 - 1.0.0
services.add_transient(MigrationABC, RemoveStatsMigration) # 19.02.2023 #190 - 1.0.0

View File

@@ -200,6 +200,13 @@
"error": { "error": {
"atr_not_found": "Das Attribut {} konnte nicht gefunden werden :(" "atr_not_found": "Das Attribut {} konnte nicht gefunden werden :("
} }
},
"register": {
"success": "Spieler wurde mit dem Mitglied verlinkt :D",
"not_found": "Benutzer nicht gefunden!"
},
"unregister": {
"success": "Verlinkung wurde entfernt :D"
} }
}, },
"boot_log": { "boot_log": {
@@ -256,34 +263,20 @@
}, },
"database": {}, "database": {},
"permission": {}, "permission": {},
"stats": {
"list": {
"statistic": "Statistik",
"description": "Beschreibung",
"nothing_found": "Keine Statistiken gefunden."
},
"view": {
"statistic": "Statistik",
"description": "Beschreibung",
"failed": "Statistik kann nicht gezeigt werden :("
},
"add": {
"failed": "Statistik kann nicht hinzugefügt werden :(",
"success": "Statistik wurde hinzugefügt :D"
},
"edit": {
"failed": "Statistik kann nicht bearbeitet werden :(",
"success": "Statistik wurde gespeichert :D"
},
"remove": {
"failed": "Statistik kann nicht gelöscht werden :(",
"success": "Statistik wurde gelöscht :D"
}
},
"technician": { "technician": {
"restart_message": "Bin gleich wieder da :D", "restart_message": "Bin gleich wieder da :D",
"shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, Euer Freund. Lebt lange und in Frieden :)", "shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, Euer Freund. Lebt lange und in Frieden :)",
"log_message": "Hier sind deine Logdateien! :)" "log_message": "Hier sind deine Logdateien! :)",
"api_key": {
"get": "API-Schlüssel für {}: {}",
"add": {
"success": "API-Schlüssel für {} wurde erstellt: {}"
},
"remove": {
"not_found": "API-Schlüssel konnte nicht gefunden werden!",
"success": "API-Schlüssel wurde entfernt :D"
}
}
} }
}, },
"api": { "api": {

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.abc"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -52,17 +52,13 @@ class AuthServiceABC(ABC):
pass pass
@abstractmethod @abstractmethod
async def add_auth_user_async(self, user_dto: AuthUserDTO): def add_auth_user(self, user_dto: AuthUserDTO):
pass pass
@abstractmethod @abstractmethod
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO): async def add_auth_user_by_oauth_async(self, dto: OAuthDTO):
pass pass
@abstractmethod
async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO:
pass
@abstractmethod @abstractmethod
async def update_user_async(self, update_user_dto: UpdateAuthUserDTO): async def update_user_async(self, update_user_dto: UpdateAuthUserDTO):
pass pass
@@ -83,12 +79,16 @@ class AuthServiceABC(ABC):
async def verify_login(self, token_str: str) -> bool: async def verify_login(self, token_str: str) -> bool:
pass pass
@abstractmethod
def verify_api_key(self, api_key: str) -> bool:
pass
@abstractmethod @abstractmethod
async def login_async(self, user_dto: AuthUserDTO) -> TokenDTO: async def login_async(self, user_dto: AuthUserDTO) -> TokenDTO:
pass pass
@abstractmethod @abstractmethod
async def login_discord_async(self, oauth_dto: AuthUserDTO) -> TokenDTO: async def login_discord_async(self, oauth_dto: AuthUserDTO, dc_id: int) -> TokenDTO:
pass pass
@abstractmethod @abstractmethod

View File

@@ -1,4 +1,3 @@
import re
import sys import sys
import textwrap import textwrap
import uuid import uuid
@@ -16,7 +15,6 @@ from werkzeug.exceptions import NotFound
from bot_api.configuration.api_settings import ApiSettings from bot_api.configuration.api_settings import ApiSettings
from bot_api.configuration.authentication_settings import AuthenticationSettings from bot_api.configuration.authentication_settings import AuthenticationSettings
from bot_api.configuration.frontend_settings import FrontendSettings
from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_api.exception.service_error_code_enum import ServiceErrorCode
from bot_api.exception.service_exception import ServiceException from bot_api.exception.service_exception import ServiceException
from bot_api.logging.api_logger import ApiLogger from bot_api.logging.api_logger import ApiLogger
@@ -30,7 +28,6 @@ class Api(Flask):
logger: ApiLogger, logger: ApiLogger,
services: ServiceProviderABC, services: ServiceProviderABC,
api_settings: ApiSettings, api_settings: ApiSettings,
frontend_settings: FrontendSettings,
auth_settings: AuthenticationSettings, auth_settings: AuthenticationSettings,
*args, *args,
**kwargs, **kwargs,
@@ -146,20 +143,13 @@ class Api(Flask):
return response return response
def start(self): def start(self):
self._logger.info( self._logger.info(__name__, f"Starting API {self._api_settings.host}:{self._api_settings.port}")
__name__,
f"Starting API {self._api_settings.host}:{self._api_settings.port}",
)
self._register_routes() self._register_routes()
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key) self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
# from waitress import serve # from waitress import serve
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html # 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) # serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10)
wsgi.server( wsgi.server(eventlet.listen((self._api_settings.host, self._api_settings.port)), self, log_output=False)
eventlet.listen((self._api_settings.host, self._api_settings.port)),
self,
log_output=False,
)
def on_connect(self): def on_connect(self):
self._logger.info(__name__, f"Client connected") self._logger.info(__name__, f"Client connected")

View File

@@ -13,7 +13,7 @@ from bot_api.api import Api
from bot_api.api_thread import ApiThread from bot_api.api_thread import ApiThread
from bot_api.controller.auth_controller import AuthController from bot_api.controller.auth_controller import AuthController
from bot_api.controller.auth_discord_controller import AuthDiscordController from bot_api.controller.auth_discord_controller import AuthDiscordController
from bot_api.controller.discord.server_controller import ServerController from bot_api.controller.graphql_controller import GraphQLController
from bot_api.controller.gui_controller import GuiController from bot_api.controller.gui_controller import GuiController
from bot_api.event.bot_api_on_ready_event import BotApiOnReadyEvent from bot_api.event.bot_api_on_ready_event import BotApiOnReadyEvent
from bot_api.service.auth_service import AuthService from bot_api.service.auth_service import AuthService
@@ -45,7 +45,7 @@ class ApiModule(ModuleABC):
services.add_transient(AuthDiscordController) services.add_transient(AuthDiscordController)
services.add_transient(GuiController) services.add_transient(GuiController)
services.add_transient(DiscordService) services.add_transient(DiscordService)
services.add_transient(ServerController) services.add_transient(GraphQLController)
# cpl-discord # cpl-discord
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent) self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)

View File

@@ -2,12 +2,9 @@ from cpl_core.application import ApplicationExtensionABC
from cpl_core.configuration import ConfigurationABC from cpl_core.configuration import ConfigurationABC
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
from bot_api.abc.auth_service_abc import AuthServiceABC
from bot_api.configuration.authentication_settings import AuthenticationSettings
from bot_api.route.route import Route from bot_api.route.route import Route
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
class AppApiExtension(ApplicationExtensionABC): class AppApiExtension(ApplicationExtensionABC):
@@ -19,7 +16,4 @@ class AppApiExtension(ApplicationExtensionABC):
if not feature_flags.get_flag(FeatureFlagsEnum.api_module): if not feature_flags.get_flag(FeatureFlagsEnum.api_module):
return return
auth_settings: AuthenticationSettings = config.get_configuration(AuthenticationSettings) Route.init_authorize()
auth_users: AuthUserRepositoryABC = services.get_service(AuthUserRepositoryABC)
auth: AuthServiceABC = services.get_service(AuthServiceABC)
Route.init_authorize(auth_users, auth)

View File

@@ -2,9 +2,9 @@
"ProjectSettings": { "ProjectSettings": {
"Name": "bot-api", "Name": "bot-api",
"Version": { "Version": {
"Major": "0", "Major": "1",
"Minor": "3", "Minor": "0",
"Micro": "1" "Micro": "dev130"
}, },
"Author": "", "Author": "",
"AuthorEmail": "", "AuthorEmail": "",

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.configuration"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.controller"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -6,8 +6,6 @@ from flask import request, jsonify, Response
from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.abc.auth_service_abc import AuthServiceABC
from bot_api.api import Api from bot_api.api import Api
from bot_api.exception.service_error_code_enum import ServiceErrorCode
from bot_api.exception.service_exception import ServiceException
from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria
from bot_api.json_processor import JSONProcessor from bot_api.json_processor import JSONProcessor
from bot_api.logging.api_logger import ApiLogger from bot_api.logging.api_logger import ApiLogger
@@ -73,7 +71,7 @@ class AuthController:
@Route.post(f"{BasePath}/register") @Route.post(f"{BasePath}/register")
async def register(self): async def register(self):
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
await self._auth_service.add_auth_user_async(dto) await self._auth_service.add_auth_user(dto)
return "", 200 return "", 200
@Route.post(f"{BasePath}/register-by-id/<id>") @Route.post(f"{BasePath}/register-by-id/<id>")

View File

@@ -8,7 +8,7 @@ from cpl_core.utils import CredentialManager
from cpl_discord.service import DiscordBotServiceABC from cpl_discord.service import DiscordBotServiceABC
from cpl_translation import TranslatePipe from cpl_translation import TranslatePipe
from flask import jsonify, Response from flask import jsonify, Response
from flask import request, session from flask import request
from requests_oauthlib import OAuth2Session from requests_oauthlib import OAuth2Session
from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.abc.auth_service_abc import AuthServiceABC
@@ -16,10 +16,8 @@ from bot_api.api import Api
from bot_api.configuration.discord_authentication_settings import ( from bot_api.configuration.discord_authentication_settings import (
DiscordAuthenticationSettings, DiscordAuthenticationSettings,
) )
from bot_api.json_processor import JSONProcessor
from bot_api.logging.api_logger import ApiLogger from bot_api.logging.api_logger import ApiLogger
from bot_api.model.auth_user_dto import AuthUserDTO from bot_api.model.auth_user_dto import AuthUserDTO
from bot_api.model.o_auth_dto import OAuthDTO
from bot_api.route.route import Route from bot_api.route.route import Route
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum
@@ -59,7 +57,7 @@ class AuthDiscordController:
self._bot.user.id, self._bot.user.id,
redirect_uri=self._auth_settings.redirect_url, redirect_uri=self._auth_settings.redirect_url,
state=request.args.get("state"), state=request.args.get("state"),
scope=self._auth_settings.scope, scope=self._auth_settings.scope.to_list(),
) )
token = discord.fetch_token( token = discord.fetch_token(
self._auth_settings.token_url, self._auth_settings.token_url,
@@ -74,28 +72,11 @@ class AuthDiscordController:
oauth = OAuth2Session( oauth = OAuth2Session(
self._bot.user.id, self._bot.user.id,
redirect_uri=self._auth_settings.redirect_url, redirect_uri=self._auth_settings.redirect_url,
scope=self._auth_settings.scope, scope=self._auth_settings.scope.to_list(),
) )
login_url, state = oauth.authorization_url(self._auth_settings.auth_url) login_url, state = oauth.authorization_url(self._auth_settings.auth_url)
return jsonify({"loginUrl": login_url}) return jsonify({"loginUrl": login_url})
@Route.get(f"{BasePath}/create-user")
async def discord_create_user(self) -> Response:
response = self._get_user_from_discord_response()
result = await self._auth_service.add_auth_user_by_discord_async(
AuthUserDTO(
0,
response["username"],
response["discriminator"],
response["email"],
str(uuid.uuid4()),
None,
AuthRoleEnum.normal,
),
response["id"],
)
return jsonify(result.to_dict())
@Route.get(f"{BasePath}/login") @Route.get(f"{BasePath}/login")
async def discord_login(self) -> Response: async def discord_login(self) -> Response:
response = self._get_user_from_discord_response() response = self._get_user_from_discord_response()
@@ -109,5 +90,5 @@ class AuthDiscordController:
AuthRoleEnum.normal, AuthRoleEnum.normal,
) )
result = await self._auth_service.login_discord_async(dto) result = await self._auth_service.login_discord_async(dto, response["id"])
return jsonify(result.to_dict()) return jsonify(result.to_dict())

View File

@@ -1,67 +0,0 @@
from cpl_core.configuration import ConfigurationABC
from cpl_core.environment import ApplicationEnvironmentABC
from cpl_core.mailing import EMailClientABC, EMailClientSettings
from cpl_translation import TranslatePipe
from flask import Response, jsonify, request
from bot_api.api import Api
from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria
from bot_api.json_processor import JSONProcessor
from bot_api.logging.api_logger import ApiLogger
from bot_api.route.route import Route
from bot_api.service.discord_service import DiscordService
from bot_data.model.auth_role_enum import AuthRoleEnum
class ServerController:
BasePath = f"/api/discord/server"
def __init__(
self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
logger: ApiLogger,
t: TranslatePipe,
api: Api,
mail_settings: EMailClientSettings,
mailer: EMailClientABC,
discord_service: DiscordService,
):
self._config = config
self._env = env
self._logger = logger
self._t = t
self._api = api
self._mail_settings = mail_settings
self._mailer = mailer
self._discord_service = discord_service
@Route.get(f"{BasePath}/get/servers")
@Route.authorize(role=AuthRoleEnum.admin)
async def get_all_servers(self) -> Response:
result = await self._discord_service.get_all_servers()
result = result.select(lambda x: x.to_dict()).to_list()
return jsonify(result)
@Route.get(f"{BasePath}/get/servers-by-user")
@Route.authorize
async def get_all_servers_by_user(self) -> Response:
result = await self._discord_service.get_all_servers_by_user()
result = result.select(lambda x: x.to_dict()).to_list()
return jsonify(result)
@Route.post(f"{BasePath}/get/filtered")
@Route.authorize
async def get_filtered_servers(self) -> Response:
dto: ServerSelectCriteria = JSONProcessor.process(
ServerSelectCriteria, request.get_json(force=True, silent=True)
)
result = await self._discord_service.get_filtered_servers_async(dto)
result.result = result.result.select(lambda x: x.to_dict()).to_list()
return jsonify(result.to_dict())
@Route.get(f"{BasePath}/get/<id>")
@Route.authorize
async def get_server_by_id(self, id: int) -> Response:
result = await self._discord_service.get_server_by_id_async(id).to_list()
return jsonify(result.to_dict())

View File

@@ -0,0 +1,44 @@
from ariadne import graphql_sync
from ariadne.constants import PLAYGROUND_HTML
from cpl_core.configuration import ConfigurationABC
from cpl_core.environment import ApplicationEnvironmentABC
from flask import request, jsonify
from bot_api.logging.api_logger import ApiLogger
from bot_api.route.route import Route
from bot_graphql.schema import Schema
class GraphQLController:
BasePath = f"/api/graphql"
def __init__(
self,
config: ConfigurationABC,
env: ApplicationEnvironmentABC,
logger: ApiLogger,
schema: Schema,
):
self._config = config
self._env = env
self._logger = logger
self._schema = schema
@Route.get(f"{BasePath}/playground")
@Route.authorize(skip_in_dev=True)
async def playground(self):
if self._env.environment_name != "development":
return "", 403
return PLAYGROUND_HTML, 200
@Route.post(f"{BasePath}")
@Route.authorize(by_api_key=True)
async def graphql(self):
data = request.get_json()
# Note: Passing the request to the context is optional.
# In Flask, the current request is always accessible as flask.request
success, result = graphql_sync(self._schema.schema, data, context_value=request)
return jsonify(result), 200 if success else 400

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.event"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.exception"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -4,7 +4,6 @@ from werkzeug.exceptions import Unauthorized
class ServiceErrorCode(Enum): class ServiceErrorCode(Enum):
Unknown = 0 Unknown = 0
InvalidDependencies = 1 InvalidDependencies = 1

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.filter"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.filter.discord"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.logging"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.model"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -1,6 +1,10 @@
from datetime import datetime
from typing import Optional from typing import Optional
from cpl_query.extension import List
from bot_api.abc.dto_abc import DtoABC from bot_api.abc.dto_abc import DtoABC
from bot_api.model.user_dto import UserDTO
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum
@@ -14,6 +18,9 @@ class AuthUserDTO(DtoABC):
password: str = None, password: str = None,
confirmation_id: Optional[str] = None, confirmation_id: Optional[str] = None,
auth_role: AuthRoleEnum = None, auth_role: AuthRoleEnum = None,
users: List[UserDTO] = None,
created_at: datetime = None,
modified_at: datetime = None,
): ):
DtoABC.__init__(self) DtoABC.__init__(self)
@@ -24,6 +31,13 @@ class AuthUserDTO(DtoABC):
self._password = password self._password = password
self._is_confirmed = confirmation_id is None self._is_confirmed = confirmation_id is None
self._auth_role = auth_role self._auth_role = auth_role
self._created_at = created_at
self._modified_at = modified_at
if users is None:
self._users = List(UserDTO)
else:
self._users = users
@property @property
def id(self) -> int: def id(self) -> int:
@@ -77,6 +91,18 @@ class AuthUserDTO(DtoABC):
def auth_role(self, value: AuthRoleEnum): def auth_role(self, value: AuthRoleEnum):
self._auth_role = value self._auth_role = value
@property
def users(self) -> List[UserDTO]:
return self._users
@property
def created_at(self) -> datetime:
return self._created_at
@property
def modified_at(self) -> datetime:
return self._modified_at
def from_dict(self, values: dict): def from_dict(self, values: dict):
self._id = values["id"] self._id = values["id"]
self._first_name = values["firstName"] self._first_name = values["firstName"]
@@ -85,6 +111,15 @@ class AuthUserDTO(DtoABC):
self._password = values["password"] self._password = values["password"]
self._is_confirmed = values["isConfirmed"] self._is_confirmed = values["isConfirmed"]
self._auth_role = AuthRoleEnum(values["authRole"]) self._auth_role = AuthRoleEnum(values["authRole"])
if "users" in values:
self._users = List(UserDTO)
for u in values["users"]:
user = UserDTO()
user.from_dict(u)
self._users.add(user)
self._created_at = values["createdAt"]
self._modified_at = values["modifiedAt"]
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {
@@ -95,4 +130,7 @@ class AuthUserDTO(DtoABC):
"password": self._password, "password": self._password,
"isConfirmed": self._is_confirmed, "isConfirmed": self._is_confirmed,
"authRole": self._auth_role.value, "authRole": self._auth_role.value,
"users": self._users.select(lambda u: u.to_dict()).to_list(),
"createdAt": self._created_at,
"modifiedAt": self._modified_at,
} }

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.model.discord"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -1,16 +1,13 @@
import traceback
from cpl_core.console import Console
from bot_api.abc.dto_abc import DtoABC from bot_api.abc.dto_abc import DtoABC
class TokenDTO(DtoABC): class TokenDTO(DtoABC):
def __init__(self, token: str, refresh_token: str): def __init__(self, token: str, refresh_token: str, first_login: bool = False):
DtoABC.__init__(self) DtoABC.__init__(self)
self._token = token self._token = token
self._refresh_token = refresh_token self._refresh_token = refresh_token
self._first_login = first_login
@property @property
def token(self) -> str: def token(self) -> str:
@@ -20,9 +17,14 @@ class TokenDTO(DtoABC):
def refresh_token(self) -> str: def refresh_token(self) -> str:
return self._refresh_token return self._refresh_token
@property
def first_login(self) -> bool:
return self._first_login
def from_dict(self, values: dict): def from_dict(self, values: dict):
self._token = values["token"] self._token = values["token"]
self._refresh_token = values["refreshToken"] self._refresh_token = values["refreshToken"]
self._first_login = values["firstLogin"]
def to_dict(self) -> dict: def to_dict(self) -> dict:
return {"token": self._token, "refreshToken": self._refresh_token} return {"token": self._token, "refreshToken": self._refresh_token, "firstLogin": self._first_login}

View File

@@ -0,0 +1,88 @@
from typing import Optional
from bot_api.abc.dto_abc import DtoABC
from bot_data.model.server import Server
class UserDTO(DtoABC):
def __init__(
self,
id: int = None,
dc_id: int = None,
xp: int = None,
minecraft_id: Optional[str] = None,
server: Optional[Server] = None,
is_technician: Optional[bool] = None,
is_admin: Optional[bool] = None,
is_moderator: Optional[bool] = None,
):
DtoABC.__init__(self)
self._user_id = id
self._discord_id = dc_id
self._xp = xp
self._minecraft_id = minecraft_id
self._server = server
self._is_technician = is_technician
self._is_admin = is_admin
self._is_moderator = is_moderator
@property
def user_id(self) -> int:
return self._user_id
@property
def discord_id(self) -> int:
return self._discord_id
@property
def xp(self) -> int:
return self._xp
@xp.setter
def xp(self, value: int):
self._xp = value
@property
def minecraft_id(self) -> Optional[str]:
return self._minecraft_id
@minecraft_id.setter
def minecraft_id(self, value: str):
self._minecraft_id = value
@property
def server(self) -> Optional[Server]:
return self._server
@property
def is_technician(self) -> bool:
return self._is_technician if self._is_technician is not None else False
@property
def is_admin(self) -> bool:
return self._is_admin if self._is_admin is not None else False
@property
def is_moderator(self) -> bool:
return self._is_moderator if self._is_moderator is not None else False
def from_dict(self, values: dict):
self._user_id = values["id"]
self._discord_id = values["dcId"]
self._xp = values["xp"]
self._minecraft_id = values["minecraftId"]
self._server = values["server"]
def to_dict(self) -> dict:
return {
"id": self._user_id,
"dcId": self._discord_id,
"xp": self._xp,
"minecraftId": self._minecraft_id,
"server": self._server.id,
"isTechnician": self.is_technician,
"isAdmin": self.is_admin,
"isModerator": self.is_moderator,
}

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.route"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -1,7 +1,9 @@
import functools import functools
from functools import wraps from functools import wraps
from typing import Optional, Callable from typing import Optional, Callable, Union
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_core.environment import ApplicationEnvironmentABC
from flask import request, jsonify from flask import request, jsonify
from flask_cors import cross_origin from flask_cors import cross_origin
@@ -11,6 +13,7 @@ from bot_api.exception.service_exception import ServiceException
from bot_api.model.error_dto import ErrorDTO from bot_api.model.error_dto import ErrorDTO
from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum
from bot_data.model.auth_user import AuthUser
class Route: class Route:
@@ -18,23 +21,77 @@ class Route:
_auth_users: Optional[AuthUserRepositoryABC] = None _auth_users: Optional[AuthUserRepositoryABC] = None
_auth: Optional[AuthServiceABC] = None _auth: Optional[AuthServiceABC] = None
_env = "production"
@classmethod @classmethod
def init_authorize(cls, auth_users: AuthUserRepositoryABC, auth: AuthServiceABC): @ServiceProviderABC.inject
def init_authorize(cls, env: ApplicationEnvironmentABC, auth_users: AuthUserRepositoryABC, auth: AuthServiceABC):
cls._auth_users = auth_users cls._auth_users = auth_users
cls._auth = auth cls._auth = auth
cls._env = env.environment_name
@classmethod @classmethod
def authorize(cls, f: Callable = None, role: AuthRoleEnum = None): def get_user(cls) -> Optional[Union[str, AuthUser]]:
token = None
api_key = None
authorization = request.headers.get("Authorization").split()
match authorization[0]:
case "Bearer":
token = authorization[1]
case "API-Key":
api_key = authorization[1]
if api_key is not None:
return "system"
if token is None:
return None
jwt = cls._auth.decode_token(token)
user = cls._auth_users.get_auth_user_by_email(jwt["email"])
return user
@classmethod
def authorize(cls, f: Callable = None, role: AuthRoleEnum = None, skip_in_dev=False, by_api_key=False):
if f is None: if f is None:
return functools.partial(cls.authorize, role=role) return functools.partial(cls.authorize, role=role, skip_in_dev=skip_in_dev, by_api_key=by_api_key)
@wraps(f) @wraps(f)
async def decorator(*args, **kwargs): async def decorator(*args, **kwargs):
if skip_in_dev and cls._env == "development":
return await f(*args, **kwargs)
token = None token = None
api_key = None
if "Authorization" in request.headers: if "Authorization" in request.headers:
bearer = request.headers.get("Authorization") if " " not in request.headers.get("Authorization"):
token = bearer.split()[1] ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set")
error = ErrorDTO(ex.error_code, ex.message)
return jsonify(error.to_dict()), 401
authorization = request.headers.get("Authorization").split()
match authorization[0]:
case "Bearer":
token = authorization[1]
case "API-Key":
api_key = authorization[1]
if api_key is not None:
valid = False
try:
valid = cls._auth.verify_api_key(api_key)
except ServiceException as e:
error = ErrorDTO(e.error_code, e.message)
return jsonify(error.to_dict()), 403
except Exception as e:
return jsonify(e), 500
if not valid:
ex = ServiceException(ServiceErrorCode.Unauthorized, f"API-Key invalid")
error = ErrorDTO(ex.error_code, ex.message)
return jsonify(error.to_dict()), 401
return await f(*args, **kwargs)
if token is None: if token is None:
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set") ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.service"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -31,9 +31,11 @@ from bot_api.model.reset_password_dto import ResetPasswordDTO
from bot_api.model.token_dto import TokenDTO from bot_api.model.token_dto import TokenDTO
from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO
from bot_api.transformer.auth_user_transformer import AuthUserTransformer as AUT from bot_api.transformer.auth_user_transformer import AuthUserTransformer as AUT
from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC
from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC
from bot_data.model.api_key import ApiKey
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum
from bot_data.model.auth_user import AuthUser from bot_data.model.auth_user import AuthUser
from bot_data.model.auth_user_users_relation import AuthUserUsersRelation from bot_data.model.auth_user_users_relation import AuthUserUsersRelation
@@ -49,9 +51,9 @@ class AuthService(AuthServiceABC):
bot: DiscordBotServiceABC, bot: DiscordBotServiceABC,
db: DatabaseContextABC, db: DatabaseContextABC,
auth_users: AuthUserRepositoryABC, auth_users: AuthUserRepositoryABC,
api_keys: ApiKeyRepositoryABC,
users: UserRepositoryABC, users: UserRepositoryABC,
servers: ServerRepositoryABC, servers: ServerRepositoryABC,
# mailer: MailThread,
mailer: EMailClientABC, mailer: EMailClientABC,
t: TranslatePipe, t: TranslatePipe,
auth_settings: AuthenticationSettings, auth_settings: AuthenticationSettings,
@@ -64,6 +66,7 @@ class AuthService(AuthServiceABC):
self._bot = bot self._bot = bot
self._db = db self._db = db
self._auth_users = auth_users self._auth_users = auth_users
self._api_keys = api_keys
self._users = users self._users = users
self._servers = servers self._servers = servers
self._mailer = mailer self._mailer = mailer
@@ -82,6 +85,11 @@ class AuthService(AuthServiceABC):
return False return False
def _get_api_key_str(self, api_key: ApiKey) -> str:
return hashlib.sha256(
f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode("utf-8")
).hexdigest()
def generate_token(self, user: AuthUser) -> str: def generate_token(self, user: AuthUser) -> str:
token = jwt.encode( token = jwt.encode(
payload={ payload={
@@ -215,7 +223,7 @@ class AuthService(AuthServiceABC):
user = self._auth_users.find_auth_user_by_email(email) user = self._auth_users.find_auth_user_by_email(email)
return AUT.to_dto(user) if user is not None else None return AUT.to_dto(user) if user is not None else None
async def add_auth_user_async(self, user_dto: AuthUserDTO): def add_auth_user(self, user_dto: AuthUserDTO):
db_user = self._auth_users.find_auth_user_by_email(user_dto.email) db_user = self._auth_users.find_auth_user_by_email(user_dto.email)
if db_user is not None: if db_user is not None:
raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists") raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists")
@@ -264,51 +272,6 @@ class AuthService(AuthServiceABC):
self._db.save_changes() self._db.save_changes()
async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO:
db_auth_user = self._auth_users.find_auth_user_by_email(user_dto.email)
# user exists
if db_auth_user is not None and db_auth_user.users.count() > 0:
# raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists')
self._logger.debug(__name__, f"Discord user already exists")
return OAuthDTO(AUT.to_dto(db_auth_user), None)
# user exists but discord user id not set
elif db_auth_user is not None and db_auth_user.users.count() == 0:
self._logger.debug(__name__, f"Auth user exists but not linked with discord")
# users = self._users.get_users_by_discord_id(user_dto.user_id)
# add auth_user to user refs
db_auth_user.oauth_id = None
else:
# user does not exists
self._logger.debug(__name__, f"Auth user does not exist")
try:
user_dto.user_id = self._users.get_users_by_discord_id(user_dto.user_id).single().user_id
except Exception as e:
self._logger.error(__name__, f"User not found")
user_dto.user_id = None
await self.add_auth_user_async(user_dto)
db_auth_user = self._auth_users.get_auth_user_by_email(user_dto.email)
db_auth_user.oauth_id = uuid.uuid4()
for g in self._bot.guilds:
member = g.get_member(int(dc_id))
if member is None:
continue
server = self._servers.get_server_by_discord_id(g.id)
users = self._users.get_users_by_discord_id(dc_id)
for user in users:
if user.server.server_id != server.server_id:
continue
self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_auth_user, user))
self._auth_users.update_auth_user(db_auth_user)
self._db.save_changes()
return OAuthDTO(AUT.to_dto(db_auth_user), db_auth_user.oauth_id)
async def update_user_async(self, update_user_dto: UpdateAuthUserDTO): async def update_user_async(self, update_user_dto: UpdateAuthUserDTO):
if update_user_dto is None: if update_user_dto is None:
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty") raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
@@ -478,6 +441,18 @@ class AuthService(AuthServiceABC):
return True return True
def verify_api_key(self, api_key: str) -> bool:
try:
keys = self._api_keys.get_api_keys().select(self._get_api_key_str)
if not keys.contains(api_key):
raise ServiceException(ServiceErrorCode.InvalidData, "API-Key invalid")
except Exception as e:
self._logger.error(__name__, f"API-Key invalid", e)
return False
return True
async def login_async(self, user_dto: AuthUser) -> TokenDTO: async def login_async(self, user_dto: AuthUser) -> TokenDTO:
if user_dto is None: if user_dto is None:
raise ServiceException(ServiceErrorCode.InvalidData, "User not set") raise ServiceException(ServiceErrorCode.InvalidData, "User not set")
@@ -490,6 +465,9 @@ class AuthService(AuthServiceABC):
if db_user.password != user_dto.password: if db_user.password != user_dto.password:
raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password") raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password")
if db_user.confirmation_id is not None:
raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified")
token = self.generate_token(db_user) token = self.generate_token(db_user)
refresh_token = self._create_and_save_refresh_token(db_user) refresh_token = self._create_and_save_refresh_token(db_user)
if db_user.forgot_password_id is not None: if db_user.forgot_password_id is not None:
@@ -498,23 +476,33 @@ class AuthService(AuthServiceABC):
self._db.save_changes() self._db.save_changes()
return TokenDTO(token, refresh_token) return TokenDTO(token, refresh_token)
async def login_discord_async(self, user_dto: AuthUserDTO) -> TokenDTO: async def login_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> TokenDTO:
if user_dto is None: if user_dto is None:
raise ServiceException(ServiceErrorCode.InvalidData, "User not set") raise ServiceException(ServiceErrorCode.InvalidData, "User not set")
added_user = False
db_user = self._auth_users.find_auth_user_by_email(user_dto.email) db_user = self._auth_users.find_auth_user_by_email(user_dto.email)
if db_user is None: if db_user is None:
await self.add_auth_user_async(user_dto) self.add_auth_user(user_dto)
added_user = True
# raise ServiceException(ServiceErrorCode.InvalidUser, f'User not found') # raise ServiceException(ServiceErrorCode.InvalidUser, f'User not found')
db_user = self._auth_users.get_auth_user_by_email(user_dto.email) db_user = self._auth_users.get_auth_user_by_email(user_dto.email)
if db_user.users.count() == 0:
self._users.get_users_by_discord_id(dc_id).for_each(
lambda x: self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_user, x))
)
if db_user.confirmation_id is not None and not added_user:
raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified")
token = self.generate_token(db_user) token = self.generate_token(db_user)
refresh_token = self._create_and_save_refresh_token(db_user) refresh_token = self._create_and_save_refresh_token(db_user)
if db_user.forgot_password_id is not None: if db_user.forgot_password_id is not None:
db_user.forgot_password_id = None db_user.forgot_password_id = None
self._db.save_changes() self._db.save_changes()
return TokenDTO(token, refresh_token) return TokenDTO(token, refresh_token, first_login=added_user)
async def refresh_async(self, token_dto: TokenDTO) -> TokenDTO: async def refresh_async(self, token_dto: TokenDTO) -> TokenDTO:
if token_dto is None: if token_dto is None:

View File

@@ -2,7 +2,6 @@ from typing import Optional
from cpl_discord.service import DiscordBotServiceABC from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List from cpl_query.extension import List
from flask import jsonify
from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.abc.auth_service_abc import AuthServiceABC
from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_api.exception.service_error_code_enum import ServiceErrorCode
@@ -10,7 +9,6 @@ from bot_api.exception.service_exception import ServiceException
from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria
from bot_api.model.discord.server_dto import ServerDTO from bot_api.model.discord.server_dto import ServerDTO
from bot_api.model.discord.server_filtered_result_dto import ServerFilteredResultDTO from bot_api.model.discord.server_filtered_result_dto import ServerFilteredResultDTO
from bot_api.model.error_dto import ErrorDTO
from bot_api.transformer.server_transformer import ServerTransformer from bot_api.transformer.server_transformer import ServerTransformer
from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC
@@ -35,7 +33,7 @@ class DiscordService:
self._users = users self._users = users
def _to_dto(self, x: Server) -> Optional[ServerDTO]: def _to_dto(self, x: Server) -> Optional[ServerDTO]:
guild = self._bot.get_guild(x.discord_server_id) guild = self._bot.get_guild(x.discord_id)
if guild is None: if guild is None:
return ServerTransformer.to_dto(x, "", 0, None) return ServerTransformer.to_dto(x, "", 0, None)
@@ -55,8 +53,8 @@ class DiscordService:
if role != AuthRoleEnum.admin: if role != AuthRoleEnum.admin:
auth_user = self._auth_users.find_auth_user_by_email(token["email"]) auth_user = self._auth_users.find_auth_user_by_email(token["email"])
if auth_user is not None: if auth_user is not None:
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id) user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id)
servers = servers.where(lambda x: x.server_id in user_ids) servers = servers.where(lambda x: x.id in user_ids)
servers = List(ServerDTO, servers) servers = List(ServerDTO, servers)
return servers.select(self._to_dto).where(lambda x: x.name != "") return servers.select(self._to_dto).where(lambda x: x.name != "")
@@ -72,8 +70,8 @@ class DiscordService:
if role != AuthRoleEnum.admin: if role != AuthRoleEnum.admin:
auth_user = self._auth_users.find_auth_user_by_email(token["email"]) auth_user = self._auth_users.find_auth_user_by_email(token["email"])
if auth_user is not None: if auth_user is not None:
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id) user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id)
filtered_result.result = filtered_result.result.where(lambda x: x.server_id in user_ids) filtered_result.result = filtered_result.result.where(lambda x: x.id in user_ids)
servers: List = filtered_result.result.select(self._to_dto).where(lambda x: x.name != "") servers: List = filtered_result.result.select(self._to_dto).where(lambda x: x.name != "")
result = List(ServerDTO, servers) result = List(ServerDTO, servers)
@@ -87,7 +85,7 @@ class DiscordService:
async def get_server_by_id_async(self, id: int) -> ServerDTO: async def get_server_by_id_async(self, id: int) -> ServerDTO:
server = self._servers.get_server_by_id(id) server = self._servers.get_server_by_id(id)
guild = self._bot.get_guild(server.discord_server_id) guild = self._bot.get_guild(server.discord_id)
server_dto = ServerTransformer.to_dto(server, guild.name, guild.member_count, guild.icon) server_dto = ServerTransformer.to_dto(server, guild.name, guild.member_count, guild.icon)
return server_dto return server_dto

View File

@@ -15,7 +15,7 @@ __title__ = "bot_api.transformer"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -1,9 +1,16 @@
from datetime import datetime, timezone from datetime import datetime
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List
from bot_api.abc.transformer_abc import TransformerABC from bot_api.abc.transformer_abc import TransformerABC
from bot_api.model.auth_user_dto import AuthUserDTO from bot_api.model.auth_user_dto import AuthUserDTO
from bot_api.model.user_dto import UserDTO
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum
from bot_data.model.auth_user import AuthUser from bot_data.model.auth_user import AuthUser
from bot_data.model.user import User
from modules.permission.abc.permission_service_abc import PermissionServiceABC
class AuthUserTransformer(TransformerABC): class AuthUserTransformer(TransformerABC):
@@ -25,7 +32,28 @@ class AuthUserTransformer(TransformerABC):
) )
@staticmethod @staticmethod
def to_dto(db: AuthUser, password: str = None) -> AuthUserDTO: @ServiceProviderABC.inject
def _is_technician(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
guild = bot.get_guild(user.server.discord_id)
member = guild.get_member(user.discord_id)
return permissions.is_member_technician(member)
@staticmethod
@ServiceProviderABC.inject
def _is_admin(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
guild = bot.get_guild(user.server.discord_id)
member = guild.get_member(user.discord_id)
return permissions.is_member_admin(member)
@staticmethod
@ServiceProviderABC.inject
def _is_moderator(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
guild = bot.get_guild(user.server.discord_id)
member = guild.get_member(user.discord_id)
return permissions.is_member_moderator(member)
@classmethod
def to_dto(cls, db: AuthUser, password: str = None) -> AuthUserDTO:
return AuthUserDTO( return AuthUserDTO(
db.id, db.id,
db.first_name, db.first_name,
@@ -34,4 +62,21 @@ class AuthUserTransformer(TransformerABC):
"" if password is None else password, "" if password is None else password,
db.confirmation_id, db.confirmation_id,
db.auth_role, db.auth_role,
List(
UserDTO,
db.users.select(
lambda u: UserDTO(
u.id,
u.discord_id,
u.xp,
u.minecraft_id,
u.server,
cls._is_technician(u),
cls._is_admin(u),
cls._is_moderator(u),
)
),
),
db.created_at,
db.modified_at,
) )

View File

@@ -15,8 +15,8 @@ class ServerTransformer(TransformerABC):
@staticmethod @staticmethod
def to_dto(db: Server, name: str, member_count: int, icon_url: Optional[discord.Asset]) -> ServerDTO: def to_dto(db: Server, name: str, member_count: int, icon_url: Optional[discord.Asset]) -> ServerDTO:
return ServerDTO( return ServerDTO(
db.server_id, db.id,
db.discord_server_id, db.discord_id,
name, name,
member_count, member_count,
icon_url.url if icon_url is not None else None, icon_url.url if icon_url is not None else None,

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.abc"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -2,9 +2,9 @@
"ProjectSettings": { "ProjectSettings": {
"Name": "bot-core", "Name": "bot-core",
"Version": { "Version": {
"Major": "0", "Major": "1",
"Minor": "3", "Minor": "0",
"Micro": "1" "Micro": "dev130"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de", "AuthorEmail": "sven.heidemann@sh-edraft.de",

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.configuration"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,6 @@ class FeatureFlagsEnum(Enum):
level_module = "LevelModule" level_module = "LevelModule"
moderator_module = "ModeratorModule" moderator_module = "ModeratorModule"
permission_module = "PermissionModule" permission_module = "PermissionModule"
stats_module = "StatsModule"
# features # features
api_only = "ApiOnly" api_only = "ApiOnly"
presence = "Presence" presence = "Presence"

View File

@@ -24,7 +24,6 @@ class FeatureFlagsSettings(ConfigurationModelABC):
FeatureFlagsEnum.database_module.value: True, # 02.10.2022 #48 FeatureFlagsEnum.database_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48 FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48
FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48 FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.stats_module.value: True, # 08.11.2022 #46
# features # features
FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70 FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70
FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56 FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.core_extension"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.events"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.exception"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.helper"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.logging"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.pipes"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_core.service"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -60,28 +60,28 @@ class ClientUtilsService(ClientUtilsABC):
def received_command(self, guild_id: int): def received_command(self, guild_id: int):
server = self._servers.get_server_by_discord_id(guild_id) server = self._servers.get_server_by_discord_id(guild_id)
client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id)
client.received_command_count += 1 client.received_command_count += 1
self._clients.update_client(client) self._clients.update_client(client)
self._db.save_changes() self._db.save_changes()
def moved_user(self, guild_id: int): def moved_user(self, guild_id: int):
server = self._servers.get_server_by_discord_id(guild_id) server = self._servers.get_server_by_discord_id(guild_id)
client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id)
client.moved_users_count += 1 client.moved_users_count += 1
self._clients.update_client(client) self._clients.update_client(client)
self._db.save_changes() self._db.save_changes()
def moved_users(self, guild_id: int, count: int): def moved_users(self, guild_id: int, count: int):
server = self._servers.get_server_by_discord_id(guild_id) server = self._servers.get_server_by_discord_id(guild_id)
client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id)
client.moved_users_count += count client.moved_users_count += count
self._clients.update_client(client) self._clients.update_client(client)
self._db.save_changes() self._db.save_changes()
def get_client(self, dc_ic: int, guild_id: int): def get_client(self, dc_ic: int, guild_id: int):
server = self._servers.get_server_by_discord_id(guild_id) server = self._servers.get_server_by_discord_id(guild_id)
client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id)
return client return client
async def check_if_bot_is_ready_yet(self) -> bool: async def check_if_bot_is_ready_yet(self) -> bool:
@@ -138,7 +138,7 @@ class ClientUtilsService(ClientUtilsABC):
) -> bool: ) -> bool:
umcph = None umcph = None
try: try:
umcph = self._umcphs.find_user_message_count_per_hour_by_user_id_and_date(user.user_id, created_at) umcph = self._umcphs.find_user_message_count_per_hour_by_user_id_and_date(user.id, created_at)
if umcph is None: if umcph is None:
self._umcphs.add_user_message_count_per_hour( self._umcphs.add_user_message_count_per_hour(
UserMessageCountPerHour( UserMessageCountPerHour(
@@ -151,7 +151,7 @@ class ClientUtilsService(ClientUtilsABC):
self._db.save_changes() self._db.save_changes()
umcph = self._umcphs.get_user_message_count_per_hour_by_user_id_and_date(user.user_id, created_at) umcph = self._umcphs.get_user_message_count_per_hour_by_user_id_and_date(user.id, created_at)
except Exception as e: except Exception as e:
self._logger.error( self._logger.error(
__name__, __name__,
@@ -183,7 +183,7 @@ class ClientUtilsService(ClientUtilsABC):
def get_ontime_for_user(self, user: User) -> float: def get_ontime_for_user(self, user: User) -> float:
return round( return round(
self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.user_id) self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.id)
.where(lambda x: x.leaved_on is not None and x.joined_on is not None) .where(lambda x: x.leaved_on is not None and x.joined_on is not None)
.sum(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600), .sum(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600),
2, 2,

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data.abc"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -0,0 +1,35 @@
from abc import ABC, abstractmethod
from cpl_query.extension import List
from bot_data.model.api_key import ApiKey
class ApiKeyRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def get_api_keys(self) -> List[ApiKey]:
pass
@abstractmethod
def get_api_key(self, identifier: str, key: str) -> ApiKey:
pass
@abstractmethod
def get_api_key_by_key(self, key: str) -> ApiKey:
pass
@abstractmethod
def add_api_key(self, api_key: ApiKey):
pass
@abstractmethod
def update_api_key(self, api_key: ApiKey):
pass
@abstractmethod
def delete_api_key(self, api_key: ApiKey):
pass

View File

@@ -2,6 +2,7 @@ from abc import ABC, abstractmethod
from typing import Optional from typing import Optional
from cpl_query.extension import List from cpl_query.extension import List
from bot_data.model.client import Client from bot_data.model.client import Client
@@ -22,6 +23,10 @@ class ClientRepositoryABC(ABC):
def get_client_by_discord_id(self, discord_id: int) -> Client: def get_client_by_discord_id(self, discord_id: int) -> Client:
pass pass
@abstractmethod
def get_clients_by_server_id(self, server_id: int) -> List[Client]:
pass
@abstractmethod @abstractmethod
def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]:
pass pass

View File

@@ -1,44 +0,0 @@
from abc import ABC, abstractmethod
from typing import Optional
from cpl_query.extension import List
from bot_data.model.statistic import Statistic
class StatisticRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def get_statistics(self) -> List[Statistic]:
pass
@abstractmethod
def get_statistics_by_server_id(self, server_id: int) -> List[Statistic]:
pass
@abstractmethod
def get_statistic_by_id(self, id: int) -> Statistic:
pass
@abstractmethod
def get_statistic_by_name(self, name: str, server_id: int) -> Statistic:
pass
@abstractmethod
def find_statistic_by_name(self, name: str, server_id: int) -> Optional[Statistic]:
pass
@abstractmethod
def add_statistic(self, statistic: Statistic):
pass
@abstractmethod
def update_statistic(self, statistic: Statistic):
pass
@abstractmethod
def delete_statistic(self, statistic: Statistic):
pass

View File

@@ -0,0 +1,52 @@
from abc import ABC, abstractmethod
from typing import Optional
from cpl_query.extension import List
from bot_data.model.user_joined_game_server import UserJoinedGameServer
class UserJoinedGameServerRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def get_user_joined_game_servers(self) -> List[UserJoinedGameServer]:
pass
@abstractmethod
def get_user_joined_game_server_by_id(self, id: int) -> UserJoinedGameServer:
pass
@abstractmethod
def get_user_joined_game_servers_by_user_id(self, user_id: int) -> List[UserJoinedGameServer]:
pass
@abstractmethod
def get_active_user_joined_game_server_by_user_id(self, user_id: int) -> UserJoinedGameServer:
pass
@abstractmethod
def find_active_user_joined_game_server_by_user_id(self, user_id: int) -> Optional[UserJoinedGameServer]:
pass
@abstractmethod
def find_active_user_joined_game_servers_by_user_id(self, user_id: int) -> List[Optional[UserJoinedGameServer]]:
pass
@abstractmethod
def add_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer):
pass
@abstractmethod
def update_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer):
pass
@abstractmethod
def delete_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer):
pass
@abstractmethod
def delete_user_joined_game_server_by_user_id(self, user_id: int):
pass

View File

@@ -2,6 +2,7 @@ from abc import ABC, abstractmethod
from typing import Optional from typing import Optional
from cpl_query.extension import List from cpl_query.extension import List
from bot_data.model.user_joined_server import UserJoinedServer from bot_data.model.user_joined_server import UserJoinedServer
@@ -18,6 +19,10 @@ class UserJoinedServerRepositoryABC(ABC):
def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer: def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer:
pass pass
@abstractmethod
def get_user_joined_server_by_server_id(self, server_id: int) -> UserJoinedServer:
pass
@abstractmethod @abstractmethod
def get_user_joined_servers_by_user_id(self, user_id: int) -> list[UserJoinedServer]: def get_user_joined_servers_by_user_id(self, user_id: int) -> list[UserJoinedServer]:
pass pass

View File

@@ -27,6 +27,10 @@ class UserRepositoryABC(ABC):
def get_users_by_discord_id(self, discord_id: int) -> List[User]: def get_users_by_discord_id(self, discord_id: int) -> List[User]:
pass pass
@abstractmethod
def get_users_by_server_id(self, server_id: int) -> List[User]:
pass
@abstractmethod @abstractmethod
def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User: def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User:
pass pass

View File

@@ -2,9 +2,9 @@
"ProjectSettings": { "ProjectSettings": {
"Name": "bot-data", "Name": "bot-data",
"Version": { "Version": {
"Major": "0", "Major": "1",
"Minor": "3", "Minor": "0",
"Micro": "1" "Micro": "dev130"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de", "AuthorEmail": "sven.heidemann@sh-edraft.de",

View File

@@ -5,13 +5,14 @@ from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
from bot_core.abc.module_abc import ModuleABC from bot_core.abc.module_abc import ModuleABC
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC
from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC
from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC
from bot_data.abc.level_repository_abc import LevelRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.abc.statistic_repository_abc import StatisticRepositoryABC 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_server_repository_abc import UserJoinedServerRepositoryABC
from bot_data.abc.user_joined_voice_channel_repository_abc import ( from bot_data.abc.user_joined_voice_channel_repository_abc import (
UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryABC,
@@ -20,6 +21,7 @@ from bot_data.abc.user_message_count_per_hour_repository_abc import (
UserMessageCountPerHourRepositoryABC, UserMessageCountPerHourRepositoryABC,
) )
from bot_data.abc.user_repository_abc import UserRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC
from bot_data.service.api_key_repository_service import ApiKeyRepositoryService
from bot_data.service.auth_user_repository_service import AuthUserRepositoryService from bot_data.service.auth_user_repository_service import AuthUserRepositoryService
from bot_data.service.auto_role_repository_service import AutoRoleRepositoryService from bot_data.service.auto_role_repository_service import AutoRoleRepositoryService
from bot_data.service.client_repository_service import ClientRepositoryService from bot_data.service.client_repository_service import ClientRepositoryService
@@ -27,7 +29,7 @@ from bot_data.service.known_user_repository_service import KnownUserRepositorySe
from bot_data.service.level_repository_service import LevelRepositoryService from bot_data.service.level_repository_service import LevelRepositoryService
from bot_data.service.seeder_service import SeederService from bot_data.service.seeder_service import SeederService
from bot_data.service.server_repository_service import ServerRepositoryService from bot_data.service.server_repository_service import ServerRepositoryService
from bot_data.service.statistic_repository_service import StatisticRepositoryService from bot_data.service.user_joined_game_server_repository_service import UserJoinedGameServerRepositoryService
from bot_data.service.user_joined_server_repository_service import ( from bot_data.service.user_joined_server_repository_service import (
UserJoinedServerRepositoryService, UserJoinedServerRepositoryService,
) )
@@ -48,6 +50,7 @@ class DataModule(ModuleABC):
pass pass
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
services.add_transient(ApiKeyRepositoryABC, ApiKeyRepositoryService)
services.add_transient(AuthUserRepositoryABC, AuthUserRepositoryService) services.add_transient(AuthUserRepositoryABC, AuthUserRepositoryService)
services.add_transient(ServerRepositoryABC, ServerRepositoryService) services.add_transient(ServerRepositoryABC, ServerRepositoryService)
services.add_transient(UserRepositoryABC, UserRepositoryService) services.add_transient(UserRepositoryABC, UserRepositoryService)
@@ -55,9 +58,9 @@ class DataModule(ModuleABC):
services.add_transient(KnownUserRepositoryABC, KnownUserRepositoryService) services.add_transient(KnownUserRepositoryABC, KnownUserRepositoryService)
services.add_transient(UserJoinedServerRepositoryABC, UserJoinedServerRepositoryService) services.add_transient(UserJoinedServerRepositoryABC, UserJoinedServerRepositoryService)
services.add_transient(UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryService) services.add_transient(UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryService)
services.add_transient(UserJoinedGameServerRepositoryABC, UserJoinedGameServerRepositoryService)
services.add_transient(AutoRoleRepositoryABC, AutoRoleRepositoryService) services.add_transient(AutoRoleRepositoryABC, AutoRoleRepositoryService)
services.add_transient(LevelRepositoryABC, LevelRepositoryService) services.add_transient(LevelRepositoryABC, LevelRepositoryService)
services.add_transient(StatisticRepositoryABC, StatisticRepositoryService)
services.add_transient( services.add_transient(
UserMessageCountPerHourRepositoryABC, UserMessageCountPerHourRepositoryABC,
UserMessageCountPerHourRepositoryService, UserMessageCountPerHourRepositoryService,

View File

@@ -6,7 +6,6 @@ from bot_core.logging.database_logger import DatabaseLogger
class DBContext(DatabaseContext): class DBContext(DatabaseContext):
def __init__(self, logger: DatabaseLogger): def __init__(self, logger: DatabaseLogger):
self._logger = logger self._logger = logger
DatabaseContext.__init__(self) DatabaseContext.__init__(self)

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data.migration"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -0,0 +1,38 @@
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.migration_abc import MigrationABC
from bot_data.db_context import DBContext
class ApiKeyMigration(MigrationABC):
name = "1.0_ApiKeyMigration"
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 `ApiKeys` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`Identifier` VARCHAR(255) NOT NULL,
`Key` VARCHAR(255) NOT NULL,
`CreatorId` BIGINT NULL,
`CreatedAt` DATETIME(6),
`LastModifiedAt` DATETIME(6),
PRIMARY KEY(`Id`),
FOREIGN KEY (`CreatorId`) REFERENCES `Users`(`UserId`),
CONSTRAINT UC_Identifier_Key UNIQUE (`Identifier`,`Key`),
CONSTRAINT UC_Key UNIQUE (`Key`)
);
"""
)
)
def downgrade(self):
self._cursor.execute("DROP TABLE `ApiKeys`;")

View File

@@ -4,7 +4,7 @@ from bot_data.db_context import DBContext
class AutoRoleFix1Migration(MigrationABC): class AutoRoleFix1Migration(MigrationABC):
name = "0.3.0_AutoRoleMigration" name = "0.3.0_AutoRoleFixMigration"
def __init__(self, logger: DatabaseLogger, db: DBContext): def __init__(self, logger: DatabaseLogger, db: DBContext):
MigrationABC.__init__(self) MigrationABC.__init__(self)

View File

@@ -0,0 +1,43 @@
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.migration_abc import MigrationABC
from bot_data.db_context import DBContext
class RemoveStatsMigration(MigrationABC):
name = "1.0_RemoveStatsMigration"
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"""
DROP TABLE IF EXISTS `Statistics`;
"""
)
)
def downgrade(self):
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `Statistics` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(255) NOT NULL,
`Description` VARCHAR(255) NOT NULL,
`Code` LONGTEXT NOT NULL,
`ServerId` BIGINT,
`CreatedAt` DATETIME(6),
`LastModifiedAt` DATETIME(6),
PRIMARY KEY(`Id`),
FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`)
);
"""
)
)

View File

@@ -0,0 +1,52 @@
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.migration_abc import MigrationABC
from bot_data.db_context import DBContext
class UserJoinedGameServerMigration(MigrationABC):
name = "1.0_UserJoinedGameServerMigration"
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 `UserJoinedGameServer` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`UserId` BIGINT NOT NULL,
`GameServer` VARCHAR(255) NOT NULL,
`JoinedOn` DATETIME(6) NOT NULL,
`LeavedOn` DATETIME(6),
`CreatedAt` DATETIME(6),
`LastModifiedAt` DATETIME(6),
FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`),
PRIMARY KEY(`Id`)
);
"""
)
)
self._cursor.execute(
str(
f"""
ALTER TABLE Users ADD MinecraftId VARCHAR(255) NULL AFTER XP;
"""
)
)
def downgrade(self):
self._cursor.execute("DROP TABLE `UserJoinedGameServer`;")
self._cursor.execute(
str(
f"""
ALTER TABLE Users DROP COLUMN MinecraftId;
"""
)
)

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data.model"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -0,0 +1,103 @@
from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC
from bot_data.model.user import User
class ApiKey(TableABC):
def __init__(
self,
identifier: str,
key: str,
creator: Optional[User],
created_at: datetime = None,
modified_at: datetime = None,
id=0,
):
self._id = id
self._identifier = identifier
self._key = key
self._creator = creator
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 identifier(self) -> str:
return self._identifier
@property
def key(self) -> str:
return self._key
@property
def creator(self) -> Optional[User]:
return self._creator
@staticmethod
def get_select_all_string() -> str:
return str(
f"""
SELECT * FROM `ApiKeys`;
"""
)
@staticmethod
def get_select_string(identifier: str, key: str) -> str:
return str(
f"""
SELECT * FROM `ApiKeys`
WHERE `Identifier` = '{identifier}'
AND `Key` = '{key}';
"""
)
@staticmethod
def get_select_by_key(key: str) -> str:
return str(
f"""
SELECT * FROM `ApiKeys`
WHERE `Key` = '{key}';
"""
)
@property
def insert_string(self) -> str:
return str(
f"""
INSERT INTO `ApiKeys` (
`Identifier`, `Key`, {"" if self._creator is None else "`CreatorId`,"} `CreatedAt`, `LastModifiedAt`
) VALUES (
'{self._identifier}',
'{self._key}',
{"" if self._creator is None else f"{self._creator.id},"}
'{self._created_at}',
'{self._modified_at}'
);
"""
)
@property
def udpate_string(self) -> str:
return str(
f"""
UPDATE `ApiKeys`
SET `Identifier` = '{self._identifier}',
`Key` = '{self._key}',
{"" if self._creator is None else f"`CreatorId` = {self._creator.id},"}
`LastModifiedAt` = '{self._modified_at}'
WHERE `Id` = {self._id};
"""
)
@property
def delete_string(self) -> str:
return str(
f"""
DELETE FROM `ApiKeys`
WHERE `Id` = {self._id};
"""
)

View File

@@ -2,6 +2,5 @@ from enum import Enum
class AuthRoleEnum(Enum): class AuthRoleEnum(Enum):
normal = 0 normal = 0
admin = 1 admin = 1

View File

@@ -1,11 +1,11 @@
import uuid import uuid
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_query.extension import List from cpl_query.extension import List
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum
from bot_data.model.server import Server
from bot_data.model.user import User from bot_data.model.user import User
@@ -42,6 +42,8 @@ class AuthUser(TableABC):
if users is None: if users is None:
self._users = List(User) self._users = List(User)
else:
self._users = users
self._auth_role_id = auth_role self._auth_role_id = auth_role
@@ -213,30 +215,30 @@ class AuthUser(TableABC):
`EMail`, `EMail`,
`Password`, `Password`,
`PasswordSalt`, `PasswordSalt`,
`RefreshToken`, {"" if self._refresh_token is None else f"`RefreshToken`,"}
`ConfirmationId`, {"" if self._confirmation_id is None else f"`ConfirmationId`,"}
`ForgotPasswordId`, {"" if self._forgot_password_id is None else f"`ForgotPasswordId`,"}
`OAuthId`, {"" if self._oauth_id is None else f"`OAuthId`,"}
`RefreshTokenExpiryTime`, `RefreshTokenExpiryTime`,
`AuthRole`, `AuthRole`,
`CreatedAt`, `CreatedAt`,
`LastModifiedAt` `LastModifiedAt`
) VALUES ( ) VALUES (
{self._auth_user_id}, {self._auth_user_id},
'{self._first_name}', '{self._first_name}',
'{self._last_name}', '{self._last_name}',
'{self._email}', '{self._email}',
'{self._password}', '{self._password}',
'{self._password_salt}', '{self._password_salt}',
'{"NULL" if self._refresh_token is None else self._refresh_token}', {"" if self._refresh_token is None else f"'{self._refresh_token}',"}
'{"NULL" if self._confirmation_id is None else self._confirmation_id}', {"" if self._confirmation_id is None else f"'{self._confirmation_id}',"}
'{"NULL" if self._forgot_password_id is None else self._forgot_password_id}', {"" if self._forgot_password_id is None else f"'{self._forgot_password_id}',"}
'{"NULL" if self._oauth_id is None else self._oauth_id}', {"" if self._oauth_id is None else f"'{self._oauth_id}',"}
'{self._refresh_token_expire_time.isoformat()}', '{self._refresh_token_expire_time.isoformat()}',
{self._auth_role_id.value}, {self._auth_role_id.value},
'{self._created_at}', '{self._created_at}',
'{self._modified_at}' '{self._modified_at}'
) )
""" """
) )
@@ -250,10 +252,10 @@ class AuthUser(TableABC):
`EMail` = '{self._email}', `EMail` = '{self._email}',
`Password` = '{self._password}', `Password` = '{self._password}',
`PasswordSalt` = '{self._password_salt}', `PasswordSalt` = '{self._password_salt}',
`RefreshToken` = '{"NULL" if self._refresh_token is None else self._refresh_token}', {'' if self._refresh_token is None else f"`RefreshToken` = '{self._refresh_token}',"}
`ConfirmationId` = '{"NULL" if self._confirmation_id is None else self._confirmation_id}', {'' if self._confirmation_id is None else f"'`ConfirmationId` = '{self._confirmation_id}',"}
`ForgotPasswordId` = '{"NULL" if self._forgot_password_id is None else self._forgot_password_id}', {'' if self._forgot_password_id is None else f"`ForgotPasswordId` = '{self._forgot_password_id}',"}
`OAuthId` = '{"NULL" if self._oauth_id is None else self._oauth_id}', {'' if self._oauth_id is None else f"`OAuthId` = '{self._oauth_id}',"}
`RefreshTokenExpiryTime` = '{self._refresh_token_expire_time.isoformat()}', `RefreshTokenExpiryTime` = '{self._refresh_token_expire_time.isoformat()}',
`AuthRole` = {self._auth_role_id.value}, `AuthRole` = {self._auth_role_id.value},
`LastModifiedAt` = '{self._modified_at}' `LastModifiedAt` = '{self._modified_at}'

View File

@@ -71,7 +71,7 @@ class AuthUserUsersRelation(TableABC):
`AuthUserId`, `UserId`, `CreatedAt`, `LastModifiedAt` `AuthUserId`, `UserId`, `CreatedAt`, `LastModifiedAt`
) VALUES ( ) VALUES (
{self._auth_user.id}, {self._auth_user.id},
{self._user.user_id}, {self._user.id},
'{self._created_at}', '{self._created_at}',
'{self._modified_at}' '{self._modified_at}'
); );
@@ -84,10 +84,10 @@ class AuthUserUsersRelation(TableABC):
f""" f"""
UPDATE `AuthUserUsersRelations` UPDATE `AuthUserUsersRelations`
SET `AuthUserId` = '{self._auth_user.id}',, SET `AuthUserId` = '{self._auth_user.id}',,
`UserId` = '{self._user.user_id}' `UserId` = '{self._user.id}'
`LastModifiedAt` = '{self._modified_at}' `LastModifiedAt` = '{self._modified_at}'
WHERE `AuthUserId` = {self._auth_user.id} WHERE `AuthUserId` = {self._auth_user.id}
AND `UserId` = {self._user.user_id}; AND `UserId` = {self._user.id};
""" """
) )
@@ -97,6 +97,6 @@ class AuthUserUsersRelation(TableABC):
f""" f"""
DELETE FROM `AuthUserUsersRelations` DELETE FROM `AuthUserUsersRelations`
WHERE `AuthUserId` = {self._auth_user.id} WHERE `AuthUserId` = {self._auth_user.id}
AND `UserId` = {self._user.user_id}; AND `UserId` = {self._user.id};
""" """
) )

View File

@@ -2,21 +2,25 @@ from datetime import datetime
from typing import Optional from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
from bot_data.model.server import Server
class AutoRole(TableABC): class AutoRole(TableABC):
def __init__( def __init__(
self, self,
server_id: int, server: Optional[Server],
dc_channel_id: int, channel_id: int,
dc_message_id: int, dc_message_id: int,
created_at: datetime = None, created_at: datetime = None,
modified_at: datetime = None, modified_at: datetime = None,
id=0, id=0,
): ):
self._auto_role_id = id self._auto_role_id = id
self._server_id = server_id self._server = server
self._discord_channel_id = dc_channel_id self._discord_channel_id = channel_id
self._discord_message_id = dc_message_id self._discord_message_id = dc_message_id
TableABC.__init__(self) TableABC.__init__(self)
@@ -24,21 +28,35 @@ class AutoRole(TableABC):
self._modified_at = modified_at if modified_at is not None else self._modified_at self._modified_at = modified_at if modified_at is not None else self._modified_at
@property @property
def auto_role_id(self) -> int: def id(self) -> int:
return self._auto_role_id return self._auto_role_id
@property @property
def server_id(self) -> int: def server(self) -> Server:
return self._server_id return self._server
@property @property
def discord_channel_id(self) -> int: def discord_channel_id(self) -> int:
return self._discord_channel_id return self._discord_channel_id
@discord_channel_id.setter
def discord_channel_id(self, value: int):
self._discord_channel_id = value
@property
@ServiceProviderABC.inject
def discord_channel_name(self, bot: DiscordBotServiceABC) -> str:
channel = bot.get_channel(self.discord_channel_id)
return None if channel is None else channel.name
@property @property
def discord_message_id(self) -> int: def discord_message_id(self) -> int:
return self._discord_message_id return self._discord_message_id
@discord_message_id.setter
def discord_message_id(self, value: int):
self._discord_message_id = value
@staticmethod @staticmethod
def get_select_all_string() -> str: def get_select_all_string() -> str:
return str( return str(
@@ -81,7 +99,7 @@ class AutoRole(TableABC):
INSERT INTO `AutoRoles` ( INSERT INTO `AutoRoles` (
`ServerId`, `DiscordChannelId`, `DiscordMessageId`, `CreatedAt`, `LastModifiedAt` `ServerId`, `DiscordChannelId`, `DiscordMessageId`, `CreatedAt`, `LastModifiedAt`
) VALUES ( ) VALUES (
{self._server_id}, {self._server.id},
{self._discord_channel_id}, {self._discord_channel_id},
{self._discord_message_id}, {self._discord_message_id},
'{self._created_at}', '{self._created_at}',
@@ -95,7 +113,7 @@ class AutoRole(TableABC):
return str( return str(
f""" f"""
UPDATE `AutoRoles` UPDATE `AutoRoles`
SET `ServerId` = {self._server_id}, SET `ServerId` = {self._server.id},
`DiscordChannelId` = {self._discord_channel_id}, `DiscordChannelId` = {self._discord_channel_id},
`DiscordMessageId` = {self._discord_message_id}, `DiscordMessageId` = {self._discord_message_id},
`LastModifiedAt` = '{self._modified_at}' `LastModifiedAt` = '{self._modified_at}'

View File

@@ -1,13 +1,16 @@
from datetime import datetime from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
from bot_data.model.auto_role import AutoRole
class AutoRoleRule(TableABC): class AutoRoleRule(TableABC):
def __init__( def __init__(
self, self,
auto_role_id: int, auto_role: AutoRole,
discord_emoji_name: str, discord_emoji_name: str,
discord_role_id: int, discord_role_id: int,
created_at: datetime = None, created_at: datetime = None,
@@ -15,7 +18,7 @@ class AutoRoleRule(TableABC):
id=0, id=0,
): ):
self._auto_role_rule_id = id self._auto_role_rule_id = id
self._auto_role_id = auto_role_id self._auto_role = auto_role
self._discord_emoji_name = discord_emoji_name self._discord_emoji_name = discord_emoji_name
self._discord_role_id = discord_role_id self._discord_role_id = discord_role_id
@@ -24,21 +27,35 @@ class AutoRoleRule(TableABC):
self._modified_at = modified_at if modified_at is not None else self._modified_at self._modified_at = modified_at if modified_at is not None else self._modified_at
@property @property
def auto_role_rule_id(self) -> int: def id(self) -> int:
return self._auto_role_rule_id return self._auto_role_rule_id
@property @property
def auto_role_id(self) -> int: def auto_role(self) -> AutoRole:
return self._auto_role_id return self._auto_role
@property @property
def emoji_name(self) -> str: def emoji_name(self) -> str:
return self._discord_emoji_name return self._discord_emoji_name
@emoji_name.setter
def emoji_name(self, value: str):
self._discord_emoji_name = value
@property @property
def role_id(self) -> int: def role_id(self) -> int:
return self._discord_role_id return self._discord_role_id
@property
@ServiceProviderABC.inject
def role_name(self, bot: DiscordBotServiceABC) -> str:
guild = bot.get_guild(self.auto_role.server.discord_id)
return guild.get_role(self.role_id).name
@role_id.setter
def role_id(self, value: int):
self._discord_role_id = value
@staticmethod @staticmethod
def get_select_all_string() -> str: def get_select_all_string() -> str:
return str( return str(
@@ -72,7 +89,7 @@ class AutoRoleRule(TableABC):
INSERT INTO `AutoRoleRules` ( INSERT INTO `AutoRoleRules` (
`AutoRoleId`, `DiscordEmojiName`, `DiscordRoleId`, `CreatedAt`, `LastModifiedAt` `AutoRoleId`, `DiscordEmojiName`, `DiscordRoleId`, `CreatedAt`, `LastModifiedAt`
) VALUES ( ) VALUES (
{self._auto_role_id}, {self._auto_role.id},
'{self._discord_emoji_name}', '{self._discord_emoji_name}',
{self._discord_role_id}, {self._discord_role_id},
'{self._created_at}', '{self._created_at}',
@@ -86,8 +103,8 @@ class AutoRoleRule(TableABC):
return str( return str(
f""" f"""
UPDATE `AutoRoleRules` UPDATE `AutoRoleRules`
SET `AutoRoleId` = {self._auto_role_id}, SET `AutoRoleId` = {self._auto_role.id},
`DiscordEmojiName` = {self._discord_emoji_name}, `DiscordEmojiName` = '{self._discord_emoji_name}',
`DiscordRoleId` = {self._discord_role_id}, `DiscordRoleId` = {self._discord_role_id},
`LastModifiedAt` = '{self._modified_at}' `LastModifiedAt` = '{self._modified_at}'
WHERE `AutoRoleRuleId` = {self._auto_role_rule_id}; WHERE `AutoRoleRuleId` = {self._auto_role_rule_id};

View File

@@ -1,5 +1,8 @@
from datetime import datetime from datetime import datetime
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
from bot_data.model.server import Server from bot_data.model.server import Server
@@ -32,13 +35,18 @@ class Client(TableABC):
self._modified_at = modified_at if modified_at is not None else self._modified_at self._modified_at = modified_at if modified_at is not None else self._modified_at
@property @property
def client_id(self) -> int: def id(self) -> int:
return self._client_id return self._client_id
@property @property
def discord_id(self) -> int: def discord_id(self) -> int:
return self._discord_client_id return self._discord_client_id
@property
@ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str:
return bot.user.name
@property @property
def sent_message_count(self) -> int: def sent_message_count(self) -> int:
return self._sent_message_count return self._sent_message_count
@@ -154,7 +162,7 @@ class Client(TableABC):
{self._deleted_message_count}, {self._deleted_message_count},
{self._received_message_count}, {self._received_message_count},
{self._moved_users_count}, {self._moved_users_count},
{self._server.server_id}, {self._server.id},
'{self._created_at}', '{self._created_at}',
'{self._modified_at}' '{self._modified_at}'
); );

View File

@@ -1,8 +1,6 @@
from datetime import datetime from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC
from bot_data.model.server import Server from cpl_core.database import TableABC
class KnownUser(TableABC): class KnownUser(TableABC):
@@ -21,7 +19,7 @@ class KnownUser(TableABC):
self._modified_at = modified_at if modified_at is not None else self._modified_at self._modified_at = modified_at if modified_at is not None else self._modified_at
@property @property
def known_user_id(self) -> int: def id(self) -> int:
return self._known_user_id return self._known_user_id
@property @property

View File

@@ -1,5 +1,6 @@
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from bot_data.model.server import Server from bot_data.model.server import Server
@@ -114,7 +115,7 @@ class Level(TableABC):
'{self._color}', '{self._color}',
{self._min_xp}, {self._min_xp},
{self._permissions}, {self._permissions},
{self._server.server_id}, {self._server.id},
'{self._created_at}', '{self._created_at}',
'{self._modified_at}' '{self._modified_at}'
); );

View File

@@ -1,7 +1,8 @@
from datetime import datetime from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
class Server(TableABC): class Server(TableABC):
@@ -20,13 +21,25 @@ class Server(TableABC):
self._modified_at = modified_at if modified_at is not None else self._modified_at self._modified_at = modified_at if modified_at is not None else self._modified_at
@property @property
def server_id(self) -> int: def id(self) -> int:
return self._server_id return self._server_id
@property @property
def discord_server_id(self) -> int: def discord_id(self) -> int:
return self._discord_server_id return self._discord_server_id
@property
@ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str:
guild = bot.get_guild(self.discord_id)
return None if guild is None else guild.name
@property
@ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> str:
guild = bot.get_guild(self.discord_id)
return None if guild is None else guild.icon.url
@staticmethod @staticmethod
def get_select_all_string() -> str: def get_select_all_string() -> str:
return str( return str(

View File

@@ -1,131 +0,0 @@
from datetime import datetime
from cpl_core.database import TableABC
from cpl_core.utils import CredentialManager
from bot_data.model.server import Server
class Statistic(TableABC):
def __init__(
self,
name: str,
description: str,
code: str,
server: Server,
created_at: datetime = None,
modified_at: datetime = None,
id=0,
):
self._id = id
self._name = name
self._description = description
self._code = CredentialManager.encrypt(code)
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
@property
def id(self) -> int:
return self._id
@property
def name(self) -> str:
return self._name
@property
def description(self) -> str:
return self._description
@description.setter
def description(self, value: str):
self._description = value
@property
def code(self) -> str:
return CredentialManager.decrypt(self._code)
@code.setter
def code(self, value: str):
self._code = CredentialManager.encrypt(value)
@property
def server(self) -> Server:
return self._server
@staticmethod
def get_select_all_string() -> str:
return str(
f"""
SELECT * FROM `Statistics`;
"""
)
@staticmethod
def get_select_by_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `Statistics`
WHERE `Id` = {id};
"""
)
@staticmethod
def get_select_by_name_string(name: str, s_id: int) -> str:
return str(
f"""
SELECT * FROM `Statistics`
WHERE `ServerId` = {s_id}
AND `Name` = '{name}';
"""
)
@staticmethod
def get_select_by_server_string(s_id: int) -> str:
return str(
f"""
SELECT * FROM `Statistics`
WHERE `ServerId` = {s_id};
"""
)
@property
def insert_string(self) -> str:
return str(
f"""
INSERT INTO `Statistics` (
`Name`, `Description`, `Code`, `ServerId`, `CreatedAt`, `LastModifiedAt`
) VALUES (
'{self._name}',
'{self._description}',
'{self._code}',
{self._server.server_id},
'{self._created_at}',
'{self._modified_at}'
);
"""
)
@property
def udpate_string(self) -> str:
return str(
f"""
UPDATE `Statistics`
SET `Name` = '{self._name}',
`Description` = '{self._description}',
`Code` = '{self._code}',
`LastModifiedAt` = '{self._modified_at}'
WHERE `Id` = {self._id};
"""
)
@property
def delete_string(self) -> str:
return str(
f"""
DELETE FROM `Statistics`
WHERE `Id` = {self._id};
"""
)

View File

@@ -1,7 +1,11 @@
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Optional
from cpl_core.database import TableABC
from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
from bot_data.model.level import Level
from bot_data.model.server import Server from bot_data.model.server import Server
@@ -10,6 +14,7 @@ class User(TableABC):
self, self,
dc_id: int, dc_id: int,
xp: int, xp: int,
minecraft_id: Optional[str],
server: Optional[Server], server: Optional[Server],
created_at: datetime = None, created_at: datetime = None,
modified_at: datetime = None, modified_at: datetime = None,
@@ -18,6 +23,7 @@ class User(TableABC):
self._user_id = id self._user_id = id
self._discord_id = dc_id self._discord_id = dc_id
self._xp = xp self._xp = xp
self._minecraft_id = minecraft_id
self._server = server self._server = server
TableABC.__init__(self) TableABC.__init__(self)
@@ -25,13 +31,27 @@ class User(TableABC):
self._modified_at = modified_at if modified_at is not None else self._modified_at self._modified_at = modified_at if modified_at is not None else self._modified_at
@property @property
def user_id(self) -> int: def id(self) -> int:
return self._user_id return self._user_id
@property @property
def discord_id(self) -> int: def discord_id(self) -> int:
return self._discord_id return self._discord_id
@property
@ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str:
guild = bot.get_guild(self.server.discord_id)
user = guild.get_member(self.discord_id)
return None if user is None else user.name
@property
@ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> str:
guild = bot.get_guild(self.server.discord_id)
user = guild.get_member(self.discord_id)
return None if user is None else user.display_icon
@property @property
def xp(self) -> int: def xp(self) -> int:
return self._xp return self._xp
@@ -41,10 +61,45 @@ class User(TableABC):
self._modified_at = datetime.now().isoformat() self._modified_at = datetime.now().isoformat()
self._xp = value self._xp = value
@property
@ServiceProviderABC.inject
def ontime(self, services: ServiceProviderABC) -> float:
from bot_core.abc.client_utils_abc import ClientUtilsABC
client_utils: ClientUtilsABC = services.get_service(ClientUtilsABC)
return client_utils.get_ontime_for_user(self)
@property
@ServiceProviderABC.inject
def level(self, services: ServiceProviderABC) -> Level:
from modules.level.service.level_service import LevelService
levels: LevelService = services.get_service(LevelService)
return levels.get_level(self)
@property
def minecraft_id(self) -> Optional[str]:
return self._minecraft_id
@minecraft_id.setter
def minecraft_id(self, value: str):
self._minecraft_id = value
@property @property
def server(self) -> Optional[Server]: def server(self) -> Optional[Server]:
return self._server return self._server
@property
@ServiceProviderABC.inject
def left_server(
self,
services: ServiceProviderABC,
) -> bool:
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
ujs: UserJoinedServerRepositoryABC = services.get_service(UserJoinedServerRepositoryABC)
return ujs.find_active_user_joined_server_by_user_id(self.id) is None
@staticmethod @staticmethod
def get_select_all_string() -> str: def get_select_all_string() -> str:
return str( return str(
@@ -62,6 +117,15 @@ class User(TableABC):
""" """
) )
@staticmethod
def get_select_by_server_id_string(server_id: int) -> str:
return str(
f"""
SELECT * FROM `Users`
WHERE `ServerId` = {server_id};
"""
)
@staticmethod @staticmethod
def get_select_by_discord_id_string(id: int) -> str: def get_select_by_discord_id_string(id: int) -> str:
return str( return str(
@@ -86,11 +150,12 @@ class User(TableABC):
return str( return str(
f""" f"""
INSERT INTO `Users` ( INSERT INTO `Users` (
`DiscordId`, `XP`, `ServerId`, `CreatedAt`, `LastModifiedAt` `DiscordId`, `XP`, {"" if self._minecraft_id is None else "`MinecraftId`,"} `ServerId`, `CreatedAt`, `LastModifiedAt`
) VALUES ( ) VALUES (
{self._discord_id}, {self._discord_id},
{self._xp}, {self._xp},
{self._server.server_id}, {"" if self._minecraft_id is None else f"'{self._minecraft_id}',"}
{self._server.id},
'{self._created_at}', '{self._created_at}',
'{self._modified_at}' '{self._modified_at}'
); );
@@ -103,6 +168,7 @@ class User(TableABC):
f""" f"""
UPDATE `Users` UPDATE `Users`
SET `XP` = {self._xp}, SET `XP` = {self._xp},
{"" if self._minecraft_id is None else f"`MinecraftId` = '{self._minecraft_id}',"}
`LastModifiedAt` = '{self._modified_at}' `LastModifiedAt` = '{self._modified_at}'
WHERE `UserId` = {self._user_id}; WHERE `UserId` = {self._user_id};
""" """

View File

@@ -0,0 +1,144 @@
from datetime import datetime
from cpl_core.database import TableABC
from bot_data.model.user import User
class UserJoinedGameServer(TableABC):
def __init__(
self,
user: User,
game_server: str,
joined_on: datetime,
leaved_on: datetime = None,
created_at: datetime = None,
modified_at: datetime = None,
id=0,
):
self._id = id
self._user = user
self._game_server = game_server
self._joined_on = joined_on
self._leaved_on = leaved_on
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 game_server(self) -> str:
return self._game_server
@property
def time(self) -> float:
return round((self.leaved_on - self.joined_on).total_seconds() / 3600, 2)
@property
def joined_on(self) -> datetime:
return self._joined_on
@joined_on.setter
def joined_on(self, value: datetime):
self._modified_at = datetime.now()
self.joined_on = value
@property
def leaved_on(self) -> datetime:
return self._leaved_on
@leaved_on.setter
def leaved_on(self, value: datetime):
self._modified_at = datetime.now()
self._leaved_on = value
@staticmethod
def get_select_all_string() -> str:
return str(
f"""
SELECT * FROM `UserJoinedGameServer`;
"""
)
@staticmethod
def get_select_by_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `UserJoinedGameServer`
WHERE `Id` = {id};
"""
)
@staticmethod
def get_select_by_user_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `UserJoinedGameServer`
WHERE `UserId` = {id};
"""
)
@staticmethod
def get_select_active_by_user_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `UserJoinedGameServer`
WHERE `UserId` = {id}
AND `LeavedOn` IS NULL;
"""
)
@property
def insert_string(self) -> str:
return str(
f"""
INSERT INTO `UserJoinedGameServer` (
`UserId`, `GameServer`, `JoinedOn`, {"" if self._leaved_on is None else "`LeavedOn`,"} `CreatedAt`, `LastModifiedAt`
) VALUES (
{self._user.id},
'{self._game_server}',
'{self._joined_on}',
{"" if self._leaved_on is None else f"'{self._leaved_on}',"}
'{self._created_at}',
'{self._modified_at}'
);
"""
)
@property
def udpate_string(self) -> str:
return str(
f"""
UPDATE `UserJoinedGameServer`
SET
{"" if self._leaved_on is None else f"`LeavedOn` = '{self._leaved_on}',"}
`LastModifiedAt` = '{self._modified_at}'
WHERE `Id` = {self._id};
"""
)
@property
def delete_string(self) -> str:
return str(
f"""
DELETE FROM `UserJoinedGameServer`
WHERE `Id` = {self._id};
"""
)
@staticmethod
def delete_by_user_id_string(id: int) -> str:
return str(
f"""
DELETE FROM `UserJoinedGameServer`
WHERE `UserId` = {id}
"""
)

View File

@@ -1,10 +1,8 @@
from datetime import datetime from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from bot_data.model.user import User from bot_data.model.user import User
from bot_data.model.server import Server
class UserJoinedServer(TableABC): class UserJoinedServer(TableABC):
@@ -27,7 +25,7 @@ class UserJoinedServer(TableABC):
self._modified_at = modified_at if modified_at is not None else self._modified_at self._modified_at = modified_at if modified_at is not None else self._modified_at
@property @property
def join_id(self) -> int: def id(self) -> int:
return self._join_id return self._join_id
@property @property
@@ -69,6 +67,15 @@ class UserJoinedServer(TableABC):
""" """
) )
@staticmethod
def get_select_by_server_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `UserJoinedServers`
WHERE `ServerId` = {id};
"""
)
@staticmethod @staticmethod
def get_select_by_user_id_string(id: int) -> str: def get_select_by_user_id_string(id: int) -> str:
return str( return str(
@@ -90,42 +97,29 @@ class UserJoinedServer(TableABC):
@property @property
def insert_string(self) -> str: def insert_string(self) -> str:
if self._leaved_on is not None: return str(
return str( f"""
f""" INSERT INTO `UserJoinedServers` (
INSERT INTO `UserJoinedServers` ( `UserId`, `JoinedOn`, {"" if self._leaved_on is None else "`LeavedOn`,"} `CreatedAt`, `LastModifiedAt`
`UserId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES (
) VALUES ( {self._user.id},
{self._user.user_id}, '{self._joined_on}',
'{self._joined_on}', {"" if self._leaved_on is None else f"'{self._leaved_on}',"}
'{self._leaved_on}', '{self._created_at}',
'{self._created_at}', '{self._modified_at}'
'{self._modified_at}' );
); """
""" )
)
else:
return str(
f"""
INSERT INTO `UserJoinedServers` (
`UserId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt`
) VALUES (
{self._user.user_id},
'{self._joined_on}',
'{self._created_at}',
'{self._modified_at}'
);
"""
)
@property @property
def udpate_string(self) -> str: def udpate_string(self) -> str:
return str( return str(
f""" f"""
UPDATE `UserJoinedServers` UPDATE `UserJoinedServers`
SET `LeavedOn` = '{self._leaved_on}', SET
{"" if self._leaved_on is None else f"`LeavedOn` = '{self._leaved_on}',"}
`LastModifiedAt` = '{self._modified_at}' `LastModifiedAt` = '{self._modified_at}'
WHERE `UserId` = {self._user.user_id}; WHERE `UserId` = {self._user.id};
""" """
) )

View File

@@ -1,6 +1,8 @@
from datetime import datetime from datetime import datetime
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
from bot_data.model.user import User from bot_data.model.user import User
@@ -9,7 +11,7 @@ class UserJoinedVoiceChannel(TableABC):
def __init__( def __init__(
self, self,
user: User, user: User,
dc_channel_id: int, channel_id: int,
joined_on: datetime, joined_on: datetime,
leaved_on: datetime = None, leaved_on: datetime = None,
created_at: datetime = None, created_at: datetime = None,
@@ -17,7 +19,7 @@ class UserJoinedVoiceChannel(TableABC):
id=0, id=0,
): ):
self._join_id = id self._join_id = id
self._dc_channel_id = dc_channel_id self._channel_id = channel_id
self._user = user self._user = user
self._joined_on = joined_on self._joined_on = joined_on
self._leaved_on = leaved_on self._leaved_on = leaved_on
@@ -27,17 +29,26 @@ class UserJoinedVoiceChannel(TableABC):
self._modified_at = modified_at if modified_at is not None else self._modified_at self._modified_at = modified_at if modified_at is not None else self._modified_at
@property @property
def join_id(self) -> int: def id(self) -> int:
return self._join_id return self._join_id
@property @property
def dc_channel_id(self) -> int: def channel_id(self) -> int:
return self._dc_channel_id return self._channel_id
@property
@ServiceProviderABC.inject
def channel_name(self, bot: DiscordBotServiceABC) -> str:
return bot.get_channel(self.channel_id).name
@property @property
def user(self) -> User: def user(self) -> User:
return self._user return self._user
@property
def time(self) -> float:
return round((self.leaved_on - self.joined_on).total_seconds() / 3600, 2)
@property @property
def joined_on(self) -> datetime: def joined_on(self) -> datetime:
return self._joined_on return self._joined_on
@@ -94,42 +105,28 @@ class UserJoinedVoiceChannel(TableABC):
@property @property
def insert_string(self) -> str: def insert_string(self) -> str:
if self._leaved_on is not None: return str(
return str( f"""
f""" INSERT INTO `UserJoinedVoiceChannel` (
INSERT INTO `UserJoinedVoiceChannel` ( `UserId`, `DiscordChannelId`, `JoinedOn`, {"" if self._leaved_on is None else "`LeavedOn`,"} `CreatedAt`, `LastModifiedAt`
`UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES (
) VALUES ( {self._user.id},
{self._user.user_id}, {self._channel_id},
{self._dc_channel_id}, '{self._joined_on}',
'{self._joined_on}', {"" if self._leaved_on is None else f"'{self._leaved_on}',"}
'{self._leaved_on}', '{self._created_at}',
'{self._created_at}', '{self._modified_at}'
'{self._modified_at}' );
); """
""" )
)
else:
return str(
f"""
INSERT INTO `UserJoinedVoiceChannel` (
`UserId`, `DiscordChannelId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt`
) VALUES (
{self._user.user_id},
{self._dc_channel_id},
'{self._joined_on}',
'{self._created_at}',
'{self._modified_at}'
);
"""
)
@property @property
def udpate_string(self) -> str: def udpate_string(self) -> str:
return str( return str(
f""" f"""
UPDATE `UserJoinedVoiceChannel` UPDATE `UserJoinedVoiceChannel`
SET `LeavedOn` = '{self._leaved_on}', SET
{"" if self._leaved_on is None else f"`LeavedOn` = '{self._leaved_on}',"}
`LastModifiedAt` = '{self._modified_at}' `LastModifiedAt` = '{self._modified_at}'
WHERE `JoinId` = {self._join_id}; WHERE `JoinId` = {self._join_id};
""" """

View File

@@ -97,7 +97,7 @@ class UserMessageCountPerHour(TableABC):
INSERT INTO `UserMessageCountPerHour` ( INSERT INTO `UserMessageCountPerHour` (
`UserId`, `Date`, `Hour`, `XPCount`, `CreatedAt`, `LastModifiedAt` `UserId`, `Date`, `Hour`, `XPCount`, `CreatedAt`, `LastModifiedAt`
) VALUES ( ) VALUES (
{self._user.user_id}, {self._user.id},
'{self._date}', '{self._date}',
{self._hour}, {self._hour},
{self._xp_count}, {self._xp_count},

View File

@@ -0,0 +1,8 @@
from enum import Enum
class UserRoleEnum(Enum):
member = 0
moderator = 1
admin = 2
technician = 3

View File

@@ -15,7 +15,7 @@ __title__ = "bot_data.service"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "0.3.1" __version__ = "1.0.dev130"
from collections import namedtuple from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="0", minor="3", micro="1") version_info = VersionInfo(major="1", minor="0", micro="dev130")

View File

@@ -0,0 +1,73 @@
from typing import Optional
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.api_key_repository_abc import ApiKeyRepositoryABC
from bot_data.abc.user_repository_abc import UserRepositoryABC
from bot_data.model.api_key import ApiKey
class ApiKeyRepositoryService(ApiKeyRepositoryABC):
def __init__(
self,
logger: DatabaseLogger,
db_context: DatabaseContextABC,
users: UserRepositoryABC,
):
self._logger = logger
self._context = db_context
self._users = users
ApiKeyRepositoryABC.__init__(self)
@staticmethod
def _get_value_from_result(value: any) -> Optional[any]:
if isinstance(value, str) and "NULL" in value:
return None
return value
def _api_key_from_result(self, sql_result: tuple) -> ApiKey:
creator = self._get_value_from_result(sql_result[3])
api_key = ApiKey(
self._get_value_from_result(sql_result[1]),
self._get_value_from_result(sql_result[2]),
None if creator is None else self._users.get_user_by_id(int(creator)),
self._get_value_from_result(sql_result[4]),
self._get_value_from_result(sql_result[5]),
id=self._get_value_from_result(sql_result[0]),
)
return api_key
def get_api_keys(self) -> List[ApiKey]:
api_keys = List(ApiKey)
self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_all_string()}")
results = self._context.select(ApiKey.get_select_all_string())
for result in results:
api_keys.append(self._api_key_from_result(result))
return api_keys
def get_api_key(self, identifier: str, key: str) -> ApiKey:
self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_string(identifier, key)}")
return self._api_key_from_result(self._context.select(ApiKey.get_select_string(identifier, key))[0])
def get_api_key_by_key(self, key: str) -> ApiKey:
self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_by_key(key)}")
return self._api_key_from_result(self._context.select(ApiKey.get_select_by_key(key))[0])
def add_api_key(self, api_key: ApiKey):
self._logger.trace(__name__, f"Send SQL command: {api_key.insert_string}")
self._context.cursor.execute(api_key.insert_string)
def update_api_key(self, api_key: ApiKey):
self._logger.trace(__name__, f"Send SQL command: {api_key.udpate_string}")
self._context.cursor.execute(api_key.udpate_string)
def delete_api_key(self, api_key: ApiKey):
self._logger.trace(__name__, f"Send SQL command: {api_key.delete_string}")
self._context.cursor.execute(api_key.delete_string)

View File

@@ -11,7 +11,6 @@ from bot_data.filtered_result import FilteredResult
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum
from bot_data.model.auth_user import AuthUser from bot_data.model.auth_user import AuthUser
from bot_data.model.auth_user_users_relation import AuthUserUsersRelation from bot_data.model.auth_user_users_relation import AuthUserUsersRelation
from bot_data.model.user import User
class AuthUserRepositoryService(AuthUserRepositoryABC): class AuthUserRepositoryService(AuthUserRepositoryABC):
@@ -29,7 +28,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
@staticmethod @staticmethod
def _get_value_from_result(value: any) -> Optional[any]: def _get_value_from_result(value: any) -> Optional[any]:
if isinstance(value, str) and "NULL" in value: if isinstance(value, str) and "null" in value:
return None return None
return value return value

View File

@@ -5,14 +5,16 @@ from cpl_query.extension import List
from bot_core.logging.database_logger import DatabaseLogger from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC 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 import AutoRole from bot_data.model.auto_role import AutoRole
from bot_data.model.auto_role_rule import AutoRoleRule from bot_data.model.auto_role_rule import AutoRoleRule
class AutoRoleRepositoryService(AutoRoleRepositoryABC): class AutoRoleRepositoryService(AutoRoleRepositoryABC):
def __init__(self, logger: DatabaseLogger, db_context: DatabaseContextABC): def __init__(self, logger: DatabaseLogger, db_context: DatabaseContextABC, servers: ServerRepositoryABC):
self._logger = logger self._logger = logger
self._context = db_context self._context = db_context
self._servers = servers
AutoRoleRepositoryABC.__init__(self) AutoRoleRepositoryABC.__init__(self)
@@ -21,14 +23,20 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_all_string()}")
results = self._context.select(AutoRole.get_select_all_string()) results = self._context.select(AutoRole.get_select_all_string())
for result in results: for result in results:
auto_roles.append(AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0])) auto_roles.append(
AutoRole(
self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0]
)
)
return auto_roles return auto_roles
def get_auto_role_by_id(self, id: int) -> AutoRole: def get_auto_role_by_id(self, id: int) -> AutoRole:
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}")
result = self._context.select(AutoRole.get_select_by_id_string(id))[0] result = self._context.select(AutoRole.get_select_by_id_string(id))[0]
return AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0]) return AutoRole(
self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0]
)
def find_auto_role_by_id(self, id: int) -> Optional[AutoRole]: def find_auto_role_by_id(self, id: int) -> Optional[AutoRole]:
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}")
@@ -38,14 +46,20 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
result = result[0] result = result[0]
return AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0]) return AutoRole(
self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0]
)
def get_auto_roles_by_server_id(self, id: int) -> List[AutoRole]: def get_auto_roles_by_server_id(self, id: int) -> List[AutoRole]:
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_server_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_server_id_string(id)}")
auto_roles = List(AutoRole) auto_roles = List(AutoRole)
results = self._context.select(AutoRole.get_select_by_server_id_string(id)) results = self._context.select(AutoRole.get_select_by_server_id_string(id))
for result in results: for result in results:
auto_roles.append(AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0])) auto_roles.append(
AutoRole(
self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0]
)
)
return auto_roles return auto_roles
@@ -55,7 +69,9 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
f"Send SQL command: {AutoRole.get_select_by_message_id_string(id)}", f"Send SQL command: {AutoRole.get_select_by_message_id_string(id)}",
) )
result = self._context.select(AutoRole.get_select_by_message_id_string(id))[0] result = self._context.select(AutoRole.get_select_by_message_id_string(id))[0]
return AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0]) return AutoRole(
self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0]
)
def find_auto_role_by_message_id(self, id: int) -> Optional[AutoRole]: def find_auto_role_by_message_id(self, id: int) -> Optional[AutoRole]:
self._logger.trace( self._logger.trace(
@@ -68,7 +84,9 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
result = result[0] result = result[0]
return AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0]) return AutoRole(
self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0]
)
def add_auto_role(self, auto_role: AutoRole): def add_auto_role(self, auto_role: AutoRole):
self._logger.trace(__name__, f"Send SQL command: {auto_role.insert_string}") self._logger.trace(__name__, f"Send SQL command: {auto_role.insert_string}")
@@ -87,14 +105,20 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_all_string()}")
results = self._context.select(AutoRoleRule.get_select_all_string()) results = self._context.select(AutoRoleRule.get_select_all_string())
for result in results: for result in results:
auto_role_rules.append(AutoRoleRule(result[1], result[2], result[3], result[4], result[5], id=result[0])) auto_role_rules.append(
AutoRoleRule(
self.get_auto_role_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0]
)
)
return auto_role_rules return auto_role_rules
def get_auto_role_rule_by_id(self, id: int) -> AutoRoleRule: def get_auto_role_rule_by_id(self, id: int) -> AutoRoleRule:
self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_by_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_by_id_string(id)}")
result = self._context.select(AutoRoleRule.get_select_by_id_string(id))[0] result = self._context.select(AutoRoleRule.get_select_by_id_string(id))[0]
return AutoRoleRule(result[1], result[2], result[3], result[4], result[5], id=result[0]) return AutoRoleRule(
self.get_auto_role_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0]
)
def get_auto_role_rules_by_auto_role_id(self, id: int) -> List[AutoRoleRule]: def get_auto_role_rules_by_auto_role_id(self, id: int) -> List[AutoRoleRule]:
auto_role_rules = List(AutoRoleRule) auto_role_rules = List(AutoRoleRule)
@@ -104,7 +128,11 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
) )
results = self._context.select(AutoRoleRule.get_select_by_auto_role_id_string(id)) results = self._context.select(AutoRoleRule.get_select_by_auto_role_id_string(id))
for result in results: for result in results:
auto_role_rules.append(AutoRoleRule(result[1], result[2], result[3], result[4], result[5], id=result[0])) auto_role_rules.append(
AutoRoleRule(
self.get_auto_role_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0]
)
)
return auto_role_rules return auto_role_rules

View File

@@ -38,6 +38,8 @@ class ClientRepositoryService(ClientRepositoryABC):
result[5], result[5],
result[6], result[6],
self._servers.get_server_by_id(result[7]), self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0], id=result[0],
) )
) )
@@ -55,9 +57,33 @@ class ClientRepositoryService(ClientRepositoryABC):
result[5], result[5],
result[6], result[6],
self._servers.get_server_by_id(result[7]), self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0], id=result[0],
) )
def get_clients_by_server_id(self, server_id: int) -> List[Client]:
clients = List(Client)
self._logger.trace(__name__, f"Send SQL command: {Client.get_select_by_server_id_string(server_id)}")
results = self._context.select(Client.get_select_by_server_id_string(server_id))
for result in results:
clients.append(
Client(
result[1],
result[2],
result[3],
result[4],
result[5],
result[6],
self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0],
)
)
return clients
def get_client_by_discord_id(self, discord_id: int) -> Client: def get_client_by_discord_id(self, discord_id: int) -> Client:
self._logger.trace( self._logger.trace(
__name__, __name__,
@@ -72,6 +98,8 @@ class ClientRepositoryService(ClientRepositoryABC):
result[5], result[5],
result[6], result[6],
self._servers.get_server_by_id(result[7]), self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0], id=result[0],
) )
@@ -94,6 +122,8 @@ class ClientRepositoryService(ClientRepositoryABC):
result[5], result[5],
result[6], result[6],
self._servers.get_server_by_id(result[7]), self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0], id=result[0],
) )
@@ -116,6 +146,8 @@ class ClientRepositoryService(ClientRepositoryABC):
result[5], result[5],
result[6], result[6],
self._servers.get_server_by_id(result[7]), self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0], id=result[0],
) )
@@ -138,6 +170,8 @@ class ClientRepositoryService(ClientRepositoryABC):
result[5], result[5],
result[6], result[6],
self._servers.get_server_by_id(result[7]), self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0], id=result[0],
) )
@@ -159,9 +193,9 @@ class ClientRepositoryService(ClientRepositoryABC):
self._logger.warn(__name__, f"Cannot find server by id {server_id}") self._logger.warn(__name__, f"Cannot find server by id {server_id}")
raise Exception("Value not found") raise Exception("Value not found")
client = self.find_client_by_discord_id_and_server_id(id, server.server_id) client = self.find_client_by_discord_id_and_server_id(id, server.id)
if client is None: if client is None:
self._logger.warn(__name__, f"Cannot find client by ids {id}@{server.server_id}") self._logger.warn(__name__, f"Cannot find client by ids {id}@{server.id}")
raise Exception("Value not found") raise Exception("Value not found")
return client return client

View File

@@ -1,6 +1,5 @@
from cpl_core.database.context import DatabaseContextABC from cpl_core.database.context import DatabaseContextABC
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
from cpl_query.extension import List
from bot_core.logging.database_logger import DatabaseLogger from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.data_seeder_abc import DataSeederABC from bot_data.abc.data_seeder_abc import DataSeederABC
@@ -18,12 +17,10 @@ class SeederService:
self._db = db self._db = db
self._seeder = List(type, DataSeederABC.__subclasses__())
async def seed(self): async def seed(self):
self._logger.info(__name__, f"Seed data") self._logger.info(__name__, f"Seed data")
for seeder in self._seeder: for seeder in self._services.get_services(list[DataSeederABC]):
seeder_as_service: DataSeederABC = self._services.get_service(seeder) seeder: DataSeederABC = seeder
self._logger.debug(__name__, f"Starting seeder {seeder.__name__}") self._logger.debug(__name__, f"Starting seeder {type(seeder).__name__}")
await seeder_as_service.seed() await seeder.seed()
self._db.save_changes() self._db.save_changes()

View File

@@ -22,7 +22,7 @@ class ServerRepositoryService(ServerRepositoryABC):
self._logger.trace(__name__, f"Send SQL command: {Server.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {Server.get_select_all_string()}")
results = self._context.select(Server.get_select_all_string()) results = self._context.select(Server.get_select_all_string())
for result in results: for result in results:
servers.append(Server(result[1], id=result[0])) servers.append(Server(result[1], result[2], result[3], id=result[0]))
return servers return servers
@@ -54,7 +54,7 @@ class ServerRepositoryService(ServerRepositoryABC):
def get_server_by_id(self, server_id: int) -> Server: def get_server_by_id(self, server_id: int) -> Server:
self._logger.trace(__name__, f"Send SQL command: {Server.get_select_by_id_string(server_id)}") 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] result = self._context.select(Server.get_select_by_id_string(server_id))[0]
return Server(result[1], id=result[0]) return Server(result[1], result[2], result[3], id=result[0])
def get_server_by_discord_id(self, discord_id: int) -> Server: def get_server_by_discord_id(self, discord_id: int) -> Server:
self._logger.trace( self._logger.trace(
@@ -62,7 +62,7 @@ class ServerRepositoryService(ServerRepositoryABC):
f"Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}", f"Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}",
) )
result = self._context.select(Server.get_select_by_discord_id_string(discord_id))[0] result = self._context.select(Server.get_select_by_discord_id_string(discord_id))[0]
return Server(result[1], id=result[0]) return Server(result[1], result[2], result[3], id=result[0])
def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]: def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]:
self._logger.trace( self._logger.trace(

View File

@@ -1,106 +0,0 @@
from typing import Optional
from cpl_core.database.context import DatabaseContextABC
from cpl_core.utils import CredentialManager
from cpl_query.extension import List
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.abc.statistic_repository_abc import StatisticRepositoryABC
from bot_data.model.statistic import Statistic
class StatisticRepositoryService(StatisticRepositoryABC):
def __init__(
self,
logger: DatabaseLogger,
db_context: DatabaseContextABC,
statistics: ServerRepositoryABC,
):
self._logger = logger
self._context = db_context
self._statistics = statistics
StatisticRepositoryABC.__init__(self)
@staticmethod
def _get_value_from_result(value: any) -> Optional[any]:
if isinstance(value, str) and "NULL" in value:
return None
return value
def _statistic_from_result(self, sql_result: tuple) -> Statistic:
code = self._get_value_from_result(sql_result[3])
if code is not None:
code = CredentialManager.decrypt(code)
statistic = Statistic(
self._get_value_from_result(sql_result[1]),
self._get_value_from_result(sql_result[2]),
code,
self._statistics.get_server_by_id(sql_result[4]),
id=self._get_value_from_result(sql_result[0]),
)
return statistic
def get_statistics(self) -> List[Statistic]:
statistics = List(Statistic)
self._logger.trace(__name__, f"Send SQL command: {Statistic.get_select_all_string()}")
results = self._context.select(Statistic.get_select_all_string())
for result in results:
statistics.append(self._statistic_from_result(result))
return statistics
def get_statistics_by_server_id(self, server_id: int) -> List[Statistic]:
statistics = List(Statistic)
self._logger.trace(
__name__,
f"Send SQL command: {Statistic.get_select_by_server_string(server_id)}",
)
results = self._context.select(Statistic.get_select_by_server_string(server_id))
for result in results:
statistics.append(self._statistic_from_result(result))
return statistics
def get_statistic_by_id(self, id: int) -> Statistic:
self._logger.trace(__name__, f"Send SQL command: {Statistic.get_select_by_id_string(id)}")
result = self._context.select(Statistic.get_select_by_id_string(id))[0]
return self._statistic_from_result(result)
def get_statistic_by_name(self, name: str, server_id: int) -> Statistic:
self._logger.trace(
__name__,
f"Send SQL command: {Statistic.get_select_by_name_string(name, server_id)}",
)
result = self._context.select(Statistic.get_select_by_name_string(name, server_id))[0]
return self._statistic_from_result(result)
def find_statistic_by_name(self, name: str, server_id: int) -> Optional[Statistic]:
self._logger.trace(
__name__,
f"Send SQL command: {Statistic.get_select_by_name_string(name, server_id)}",
)
result = self._context.select(Statistic.get_select_by_name_string(name, server_id))
if result is None or len(result) == 0:
return None
result = result[0]
return self._statistic_from_result(result)
def add_statistic(self, statistic: Statistic):
self._logger.trace(__name__, f"Send SQL command: {statistic.insert_string}")
self._context.cursor.execute(statistic.insert_string)
def update_statistic(self, statistic: Statistic):
self._logger.trace(__name__, f"Send SQL command: {statistic.udpate_string}")
self._context.cursor.execute(statistic.udpate_string)
def delete_statistic(self, statistic: Statistic):
self._logger.trace(__name__, f"Send SQL command: {statistic.delete_string}")
self._context.cursor.execute(statistic.delete_string)

View File

@@ -0,0 +1,160 @@
from typing import Optional
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.user_joined_game_server_repository_abc import (
UserJoinedGameServerRepositoryABC,
)
from bot_data.abc.user_repository_abc import UserRepositoryABC
from bot_data.model.user_joined_game_server import UserJoinedGameServer
class UserJoinedGameServerRepositoryService(UserJoinedGameServerRepositoryABC):
def __init__(
self,
logger: DatabaseLogger,
db_context: DatabaseContextABC,
users: UserRepositoryABC,
):
self._logger = logger
self._context = db_context
self._users = users
UserJoinedGameServerRepositoryABC.__init__(self)
def get_user_joined_game_servers(self) -> List[UserJoinedGameServer]:
joins = List(UserJoinedGameServer)
self._logger.trace(
__name__,
f"Send SQL command: {UserJoinedGameServer.get_select_all_string()}",
)
results = self._context.select(UserJoinedGameServer.get_select_all_string())
for result in results:
self._logger.trace(__name__, f"Get user-joined-game-server with id {result[0]}")
joins.append(
UserJoinedGameServer(
self._users.get_user_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
)
return joins
def get_user_joined_game_server_by_id(self, id: int) -> UserJoinedGameServer:
self._logger.trace(
__name__,
f"Send SQL command: {UserJoinedGameServer.get_select_by_id_string(id)}",
)
result = self._context.select(UserJoinedGameServer.get_select_by_id_string(id))[0]
return UserJoinedGameServer(
self._users.get_user_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
def get_user_joined_game_servers_by_user_id(self, user_id: int) -> List[UserJoinedGameServer]:
joins = List(UserJoinedGameServer)
self._logger.trace(
__name__,
f"Send SQL command: {UserJoinedGameServer.get_select_by_user_id_string(user_id)}",
)
results = self._context.select(UserJoinedGameServer.get_select_by_user_id_string(user_id))
for result in results:
joins.append(
UserJoinedGameServer(
self._users.get_user_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
)
return joins
def get_active_user_joined_game_server_by_user_id(self, user_id: int) -> UserJoinedGameServer:
self._logger.trace(
__name__,
f"Send SQL command: {UserJoinedGameServer.get_select_by_user_id_string(user_id)}",
)
result = self._context.select(UserJoinedGameServer.get_select_active_by_user_id_string(user_id))[0]
return UserJoinedGameServer(
self._users.get_user_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
def find_active_user_joined_game_server_by_user_id(self, user_id: int) -> Optional[UserJoinedGameServer]:
self._logger.trace(
__name__,
f"Send SQL command: {UserJoinedGameServer.get_select_by_user_id_string(user_id)}",
)
result = self._context.select(UserJoinedGameServer.get_select_active_by_user_id_string(user_id))
if result is None or len(result) == 0:
return None
result = result[0]
return UserJoinedGameServer(
self._users.get_user_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
def find_active_user_joined_game_servers_by_user_id(self, user_id: int) -> List[Optional[UserJoinedGameServer]]:
self._logger.trace(
__name__,
f"Send SQL command: {UserJoinedGameServer.get_select_active_by_user_id_string(user_id)}",
)
result = List(UserJoinedGameServer)
db_results = self._context.select(UserJoinedGameServer.get_select_active_by_user_id_string(user_id))
for db_result in db_results:
result.append(
UserJoinedGameServer(
self._users.get_user_by_id(db_result[1]),
db_result[2],
db_result[3],
db_result[4],
db_result[5],
id=db_result[0],
)
)
return result
def add_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer):
self._logger.trace(__name__, f"Send SQL command: {user_joined_game_server.insert_string}")
self._context.cursor.execute(user_joined_game_server.insert_string)
def update_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer):
self._logger.trace(__name__, f"Send SQL command: {user_joined_game_server.udpate_string}")
self._context.cursor.execute(user_joined_game_server.udpate_string)
def delete_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer):
self._logger.trace(__name__, f"Send SQL command: {user_joined_game_server.delete_string}")
self._context.cursor.execute(user_joined_game_server.delete_string)
def delete_user_joined_game_server_by_user_id(self, user_id: int):
self._logger.trace(
__name__,
f"Send SQL command: {UserJoinedGameServer.delete_by_user_id_string}",
)
self._context.cursor.execute(UserJoinedGameServer.delete_by_user_id_string(user_id))

View File

@@ -57,6 +57,21 @@ class UserJoinedServerRepositoryService(UserJoinedServerRepositoryABC):
id=result[0], id=result[0],
) )
def get_user_joined_server_by_server_id(self, server_id: int) -> UserJoinedServer:
self._logger.trace(
__name__,
f"Send SQL command: {UserJoinedServer.get(id)}",
)
result = self._context.select(UserJoinedServer.get_select_by_id_string(id))[0]
return UserJoinedServer(
self._users.get_user_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
def get_user_joined_servers_by_user_id(self, user_id: int) -> List[UserJoinedServer]: def get_user_joined_servers_by_user_id(self, user_id: int) -> List[UserJoinedServer]:
joins = List(UserJoinedServer) joins = List(UserJoinedServer)
self._logger.trace( self._logger.trace(

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