329 Commits

Author SHA1 Message Date
6fa08ea828 Fixed minor bugs #1.1.0 2023-08-21 16:25:42 +02:00
296c6e8044 Fixed stuff #1.1.0 2023-08-21 15:51:54 +02:00
0541f3dfde Fixed translations #1.1.0 2023-08-21 15:22:14 +02:00
052e0f976a Build release version #1.1.0 2023-08-21 14:44:11 +02:00
f41dfc9be2 Merge pull request '1.1.0.rc6' (#351) from 1.1.0.rc6 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#351
2023-08-21 14:41:53 +02:00
74437fdc20 Fixed client styling #1.1.0.rc6 2023-08-19 13:06:07 +02:00
df2b660b75 Fixed sidebar to support responsive mode #1.1.0.rc6 2023-08-19 10:04:38 +02:00
12f231aa41 Merge pull request 'Fixed responsive styling #1.1.0.rc5' (#350) from 1.1.0.rc5 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#350
2023-08-18 16:56:11 +02:00
2f3ae229c9 Fixed responsive styling #1.1.0.rc5 2023-08-18 16:50:19 +02:00
5bbed854a4 Merge pull request '1.1.0.rc5' (#349) from 1.1.0.rc5 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#349
2023-08-18 16:34:40 +02:00
2321c12bc9 Fixed auth user table #1.1.0.rc5 2023-08-18 16:33:13 +02:00
1cdfd1291f Fixed add icons #1.1.0.rc5 2023-08-18 16:31:30 +02:00
223946ad76 Fixed auto role rule emoji loading #1.1.0.rc5 2023-08-18 16:10:45 +02:00
4ea1b5b94c Improved table responsive mode #1.1.0.rc5 2023-08-18 16:01:20 +02:00
919970d199 Fixed add new infinity id bug & fixed translations #1.1.0.rc5 2023-08-18 08:26:00 +02:00
19ed164845 Set version correctly #1.1.0.rc5 2023-08-18 08:16:27 +02:00
92001a45be Fixed xp calculation #1.1.0.rc5 2023-08-18 08:09:43 +02:00
78b761a672 Fixed auto role tables #1.1.0.rc5 2023-08-18 08:05:27 +02:00
7bfa39f459 Merge pull request 'Fixed stylings #1.1.0.rc4 style fixes' (#348) from 1.1.0.rc4 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#348
2023-08-18 00:43:56 +02:00
d586cca672 Fixed stylings #1.1.0.rc4 2023-08-18 00:42:58 +02:00
efce172c01 Fixed table responsive mode #1.1.0 2023-08-17 23:50:36 +02:00
0974325148 Reset version #1.1.0 2023-08-17 23:42:41 +02:00
206754919f Merge pull request '1.1.0_responsive' (#347) from 1.1.0_responsive into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#347
2023-08-17 23:38:20 +02:00
b49512e28d Made hole app responsive #1.1.0 2023-08-17 23:36:44 +02:00
fa71759a20 Made dashboard responsive #1.1.0 2023-08-17 22:35:10 +02:00
9338e35504 Merge pull request 'Fixed hidden columns #1.1.0.rc4' (#346) from 1.1.0.rc4 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#346
2023-08-17 21:27:31 +02:00
2956dcb9c2 Fixed hidden columns #1.1.0.rc4 2023-08-17 21:26:18 +02:00
762bebf416 Merge pull request '1.1.0.rc4' (#345) from 1.1.0.rc4 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#345
Closes #344
2023-08-17 21:02:26 +02:00
f3b5cef253 Fixed discord data by guild filter #1.1.0.rc4 2023-08-17 19:58:25 +02:00
6869c5a671 Added coffee command #1.1.0.rc4 2023-08-17 16:18:11 +02:00
352b44be0f Fixed input styling #344 #1.1.0.rc4 2023-08-17 09:56:21 +02:00
5912708d3a Added dropdown to server config input #344 #1.1.0.rc4 2023-08-17 08:52:46 +02:00
45a3127696 Added dropdown to technicianId input #344 #1.1.0.rc4 2023-08-17 08:37:04 +02:00
10c20621a8 Set frontend version #1.1.0.rc4 2023-08-16 22:31:28 +02:00
49e0e44461 Build rc4 version #1.1.0.rc4 2023-08-16 22:30:51 +02:00
ec6b080ba6 Set rc4 version #1.1.0.rc4 2023-08-16 22:30:37 +02:00
28944755ac Fixed achievement events #1.1.0.rc4 2023-08-16 22:30:12 +02:00
7318239b2d Set frontend version #1.1.0 2023-08-16 22:17:26 +02:00
cf66d246a9 Set rc3 version #1.1.0 2023-08-16 22:16:06 +02:00
41fe6faa52 Build rc3 version #1.1.0 2023-08-16 22:15:38 +02:00
685c96bb38 Set rc3 version #1.1.0 2023-08-16 22:15:05 +02:00
2c3e5268e4 Merge pull request '1.1.0.rc3' (#343) from 1.1.0.rc3 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#343
Closes #339
Closes #338
Closes #340
Closes #337
Closes #341
2023-08-16 22:13:42 +02:00
2d5ce58612 Fixed complaint command #341 #1.1.0.rc3 2023-08-16 22:12:40 +02:00
fe3d67eff5 Fixed client data #337 #1.1.0.rc3 2023-08-16 21:23:03 +02:00
4cea31fce5 Added achievement validation triggers #340 #1.1.0.rc3 2023-08-16 21:20:14 +02:00
aa2c80ec12 Added feature flag checks #338 #1.1.0.rc3 2023-08-16 21:08:34 +02:00
e283a18def Added logic to check server view permissions #339 #1.1.0.rc3 2023-08-16 20:55:42 +02:00
f5b2bec356 Merge pull request '1.1.0.rc2' (#342) from 1.1.0.rc2 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#342
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-08-16 19:09:04 +02:00
c2b32996fd Made form transient #1.1.0.rc2 2023-08-16 18:47:13 +02:00
195566a2b6 Fixed restart command #1.1.0.rc2 2023-08-16 18:38:16 +02:00
073c318671 Fixed achievement server filter #1.1.0.rc2 2023-08-16 18:19:21 +02:00
caeec47b7c Fixed shutdown procedure async problems #1.1.0.rc2 2023-08-16 18:04:40 +02:00
44f6b36347 Fixed achievement_service #1.1.0.rc2 2023-08-16 16:55:29 +02:00
4e32414f48 Set frontend rc2 #1.1.0.rc2 2023-08-16 16:39:39 +02:00
573c9c999e Build rc2 #1.1.0.rc2 2023-08-16 16:38:54 +02:00
825fcff82d Set rc2 version #1.1.0.rc2 2023-08-16 16:38:37 +02:00
a95bf7bc6c Fixed reference errors #1.1.0.rc2 2023-08-16 16:37:49 +02:00
0bc3bff58e Merge pull request '1.1.0.rc1' (#336) from 1.1.0.rc1 into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#336
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-08-16 16:29:28 +02:00
c3b86fab6b Fixed config #1.1.0.rc1 2023-08-16 09:31:20 +02:00
906602134e Upated config #1.1.0.rc1 2023-08-16 08:59:10 +02:00
30791f7529 Fixed config loading #1.1.0.rc1 2023-08-16 08:47:48 +02:00
456d939b47 Fixed config loading #1.1.0.rc1 2023-08-16 08:30:12 +02:00
1f47636e8d Build rc1 #1.1.0.rc1 2023-08-16 07:55:32 +02:00
f4acc2669d Build rc1 #1.1.0.rc1 2023-08-16 07:43:23 +02:00
46b5757fd1 Merge pull request '#334_feature_flags_in_wi' (#335) from #334_feature_flags_in_wi into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#335
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #334
2023-08-16 00:03:44 +02:00
1cd75cd78f Hide feature flags in server config for non technicians #334 2023-08-16 00:02:04 +02:00
f7f3fea7a7 Improved feature flag defaults #334 2023-08-15 23:44:42 +02:00
5dd2000f10 Improved feature flag for server handling #334 2023-08-15 23:41:45 +02:00
1b2bb85b37 Improved feature flag for server handling #334 2023-08-15 23:24:29 +02:00
113b188a40 Reload config after change #334 2023-08-15 22:16:44 +02:00
e549341196 Secured config endpoints #334 2023-08-15 21:50:37 +02:00
8a0d939147 Added feature flags to server config #334 2023-08-15 20:50:11 +02:00
4b57d7f102 Added feature flags config to technician settings #334 2023-08-15 20:29:44 +02:00
02e0c72a80 Merge pull request '#79_hide_table_columns' (#333) from #79_hide_table_columns into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#333
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #79
2023-08-15 12:50:15 +02:00
bfc9979961 Added option to hide columns to all tables #79 2023-08-15 12:16:24 +02:00
8d76f79732 Hide members columns #79 2023-08-15 08:14:45 +02:00
4add293186 Added base logic to hide columns & added hide columns to levels #79 2023-08-14 23:33:02 +02:00
1fc5ef76a6 Merge pull request 'Added filter to mass_move channel_from #296' (#332) from #296_mass_move_filter into 1.1.0
Reviewed-on: sh-edraft.de/kd_discord_bot#332
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #296
2023-08-14 21:01:03 +02:00
e6c9959381 Added filter to mass_move channel_from #296 2023-08-14 20:57:59 +02:00
9db00516c3 Fixed translations #1.1.0 2023-08-14 19:36:22 +02:00
44e225c273 Fixed code after merges #1.1.0 2023-08-14 19:25:12 +02:00
99e75ba325 Merge branch 'support' into 1.1.0 #1.1.0
# Conflicts:
#	kdb-bot/src/bot/config
#	kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py
2023-08-14 19:22:23 +02:00
3a078271ff Merge branch 'master' into support 2023-08-14 19:17:07 +02:00
1f9991eeda Fixed queries #295 2023-08-14 19:14:59 +02:00
bfe72668dc Send message to team chat when a member leaves the server #295 2023-08-14 19:14:59 +02:00
51d95c81c1 Added technician config to frontend #127 2023-08-14 19:14:59 +02:00
6c39cd1ae1 Added server config to frontend #127 2023-08-14 19:14:59 +02:00
5d36f1188a Added server config mutation #127 2023-08-14 19:14:59 +02:00
4c42949516 Added translations #127 2023-08-14 19:14:59 +02:00
8922524f44 Added logic to edit technician config in WI #127 2023-08-14 19:14:59 +02:00
eac367c611 Added technician config to frontend #127 2023-08-14 19:14:59 +02:00
f02acd7f94 Added technician config mutation #127 2023-08-14 19:14:59 +02:00
05ddfb3de3 Added technician config queries #127 2023-08-14 19:14:59 +02:00
5c2c89ca45 Removed old settings #127 2023-08-14 19:14:59 +02:00
ec1ce4adef Changed config loading from file to db #127 2023-08-14 19:14:59 +02:00
71f1f972c9 Added technician config seeder #127 2023-08-14 19:14:59 +02:00
23757bc841 Improved technician config repo #127 2023-08-14 19:14:59 +02:00
9671090385 Added technician config repo #127 2023-08-14 19:14:59 +02:00
a03ddf3fc2 Added sql for cfg in wi migration #127 2023-08-14 19:14:59 +02:00
da3538a836 Added config migration #127 2023-08-14 19:14:59 +02:00
c782c11b6d Removed from_dict from settings stuff #127 2023-08-14 19:14:59 +02:00
05a2ea9b18 Added migration for config in wi #127 2023-08-14 19:14:59 +02:00
a482c72a56 Moved version settings to version.json #294 2023-08-14 19:14:59 +02:00
22bdf13835 Fixed workspace #268_achievements 2023-08-14 19:14:59 +02:00
0a3affc5d0 Added bug report #293_complaints 2023-08-14 19:14:59 +02:00
d642322985 Improved complaint command #293_complaints 2023-08-14 19:14:59 +02:00
9f63a9c6dd [UNTESTED] Added complaint command #293_complaints 2023-08-14 19:14:59 +02:00
11a4874bfb Added achievements to data integrity service #268_achievements 2023-08-14 19:14:59 +02:00
d4dd55944a Add xp for achievement #268_achievements 2023-08-14 19:14:59 +02:00
23d6216029 Added description to achievements #268_achievements 2023-08-14 19:14:59 +02:00
f7297ddf78 Added history for achievements to frontend #268_achievements 2023-08-14 19:14:59 +02:00
eb3715d00b Fixed achievements in user profile #268_achievements 2023-08-14 19:14:59 +02:00
aae6472e11 Added achievements to user profile #268_achievements 2023-08-14 19:14:59 +02:00
a71e3e4720 Added last_single_ontime_hours achievement logic #268_achievements 2023-08-14 19:14:59 +02:00
189128f0d3 Added played_on_game_server achievement logic #268_achievements 2023-08-14 19:14:59 +02:00
3fb951a748 Improved generic achievement logic #268_achievements 2023-08-14 19:14:59 +02:00
2293849d94 Improved internal achievement checks #268_achievements 2023-08-14 19:14:59 +02:00
cd5b3b6523 Added logic to make achievement config more generic #268_achievements 2023-08-14 19:14:59 +02:00
c8a2ed290b Fixed config #268_achievements 2023-08-14 19:14:59 +02:00
184d241695 Improved achievement logic #268_achievements 2023-08-14 19:14:59 +02:00
cab65477b0 Improved achievement endpoint #268_achievements 2023-08-14 19:14:59 +02:00
3507623c92 Improved achievement component #268_achievements 2023-08-14 19:14:59 +02:00
b99dd1bded Fixed server cache & improved frontend implementation #268_achievements 2023-08-14 19:14:59 +02:00
a0d38bec49 First step to add achievements to frontend #268_achievements 2023-08-14 19:14:59 +02:00
f312a2d776 Fixed achievement query #268_achievements 2023-08-14 19:14:58 +02:00
bfb816dd17 Fixed achievement query #268_achievements 2023-08-14 19:14:58 +02:00
d6854d44b7 Added achievement gql endpoint [UNTESTED] #268_achievements 2023-08-14 19:14:58 +02:00
fdbba1b89c Fixed models #268_achievements 2023-08-14 19:14:58 +02:00
7f197a0ea7 Added achievement data model #268_achievements 2023-08-14 19:14:58 +02:00
2c9569b75f Fixed gql playground # 2023-08-14 19:14:58 +02:00
607b7d8aee Ensure bot shutdown before data checks #292_shutdown_procedure 2023-08-14 19:14:58 +02:00
00db6ac10f Improved open voice state check #292_shutdown_procedure 2023-08-14 19:14:58 +02:00
f034413e35 Added data integrity check to shutdown #292_shutdown_procedure 2023-08-14 19:14:58 +02:00
ff16eae477 Moved data integrity check #292_shutdown_procedure 2023-08-14 19:14:58 +02:00
dbd82930d4 Removed comments #297_cpl_update 2023-08-14 19:14:58 +02:00
2e9cf0bd97 Updated cpl-discord #297_cpl_update 2023-08-14 19:14:58 +02:00
8a2edc7228 Updated stuff #297_cpl_update 2023-08-14 19:14:58 +02:00
6d14ba9d79 Updated packages #297_cpl_update 2023-08-14 19:14:58 +02:00
ba5f83f3d0 Merge pull request 'Add xp when event starts #323' (#324) from #323 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#324
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-08-14 09:30:16 +02:00
9f614e8a31 Repaired config for support 2023-07-08 09:59:50 +02:00
6e0d4a5144 Add xp when event starts #323 2023-07-08 09:40:20 +02:00
bd8bd40863 Added reaction channel null check #318 2023-06-08 08:47:56 +02:00
c7a1069c0c Merge pull request 'Fixed bug that mods cannot see auto role rules' (#315) from 314 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#315
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #314
2023-04-25 15:16:42 +02:00
dc0c6ca6a0 Merge branch 'support' into 314 2023-04-19 18:01:34 +02:00
ff009ffb61 Merge pull request 'support' (#316) from support into master
Reviewed-on: sh-edraft.de/kd_discord_bot#316
2023-04-18 22:23:59 +02:00
074b03eecf Merge branch 'master' into support 2023-04-18 22:23:51 +02:00
9201cbf357 Fixed bug that mods cannot see auto role rules 2023-04-18 20:33:59 +02:00
5ea698ef97 Build 1.0.7 patch 2023-04-14 23:28:56 +02:00
400e54a501 Merge pull request 'Als Nutzer des WI möchte ich nicht, dass Tabellen mit vielen Daten so lange laden #300' (#312) from #300 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#312
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #300
2023-04-14 23:25:39 +02:00
3c0233e8b3 Merge pull request 'Fixed closed navbar #307' (#311) from #307 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#311
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #307
2023-04-14 23:25:30 +02:00
8d2ae38d85 Set frontend version #300 2023-04-14 22:02:01 +02:00
2b866b5ab1 Improved level data loading #300 2023-04-14 22:01:06 +02:00
4da87ae3cb Improved auto-role data loading #300 2023-04-14 21:56:02 +02:00
1ebad89c97 Improved members data loading #300 2023-04-14 21:46:01 +02:00
b8320c83fe Fixed closed navbar #307 2023-04-14 21:09:03 +02:00
0ee26ccf3d Merge pull request 'Fixed register re nav #306' (#308) from #306 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#308
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-04-12 22:08:31 +02:00
31ca9cd8f4 Merge pull request 'Fixed is ready function #309' (#310) from #309 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#310
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-04-12 22:08:25 +02:00
089de53136 Fixed is ready function #309 2023-04-12 22:04:49 +02:00
280b22af55 Fixed register re nav #306 2023-04-12 21:43:45 +02:00
ebdf375283 Merge pull request 'Added level checks #304' (#305) from #304 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#305
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #304
2023-04-12 21:20:52 +02:00
c058312af7 Merge branch 'support' into #304 2023-04-12 21:02:40 +02:00
2befa921ea Added level on reaction handling #304 2023-04-12 21:02:18 +02:00
1792359e68 Merge pull request 'support' (#303) from support into master
Reviewed-on: sh-edraft.de/kd_discord_bot#303
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-04-12 20:20:20 +02:00
faaf14d63e Merge branch 'master' into support 2023-04-12 20:19:26 +02:00
49d1ec75c8 Build new patch version 2023-04-12 20:10:34 +02:00
629556b5fc Merge pull request 'Potentially fixed bug to kill web api on restart #301' (#302) from #301 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#302
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #301
2023-04-12 20:09:05 +02:00
9ece541e52 Fixed log message #301 2023-04-12 20:06:30 +02:00
fd51db8cac Merge branch 'support' into #301 2023-04-10 13:15:41 +02:00
2005d93f44 Merge pull request 'support in master' (#299) from support into master
Reviewed-on: sh-edraft.de/kd_discord_bot#299
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-04-10 13:15:32 +02:00
010dafc655 Potentially fixed bug to kill web api on restart #301 2023-04-10 00:13:09 +02:00
bea9dd1590 Merge branch 'master' into support 2023-04-09 20:04:54 +02:00
ef0da25f11 Improved license 2023-04-03 10:05:26 +02:00
c01a6b97fe Build patch version 2023-04-03 07:59:30 +02:00
059bd3aaf1 Build patch version 2023-04-03 07:56:25 +02:00
a9d180fdf1 Fixed last api changes 2023-04-03 07:53:24 +02:00
c71b1092f2 Merge pull request '#290' (#291) from #290 into support
Reviewed-on: sh-edraft.de/kd_discord_bot#291
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #290
2023-04-02 21:17:30 +02:00
c1e8274f46 Set async mode in web api #290 2023-04-02 18:32:34 +02:00
583218b215 Set async mode in web api #290 2023-04-02 14:41:05 +02:00
e05e67785b Build patched version 2023-03-31 12:25:37 +02:00
72d3ccded3 Merge pull request 'Fixed reaction handling #287' (#288) from 1.0.4 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#288
Closes #287
2023-03-31 12:04:09 +02:00
f30bd119df Fixed reaction handling #287 2023-03-31 12:03:07 +02:00
858fc062b3 Merge pull request '1.0.3 #285' (#286) from 1.0.3 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#286
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #285
2023-03-30 16:55:32 +02:00
6d622a70d3 Build patch version 2023-03-30 14:45:37 +02:00
4a0a6a4631 Improved logging to app end 2023-03-30 14:43:21 +02:00
17c2acd77c Improved logging to app end 2023-03-30 14:37:02 +02:00
27363522d3 Fixed xp input #285 2023-03-30 14:29:31 +02:00
1960b18058 Improved level service 2023-03-30 14:23:29 +02:00
91034cee09 Merge pull request '1.0.2 #283' (#284) from 1.0.2 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#284
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #283
2023-03-29 23:06:51 +02:00
a4d3cffa93 Removed test logs 2023-03-29 23:05:41 +02:00
809c6d4cb9 Build patch version 2023-03-29 22:59:40 +02:00
2fecbf2c31 Added cache service to cache server 2023-03-29 22:58:32 +02:00
c439d5925f Merge pull request '1.0.1' (#278) from 1.0.1 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#278
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
2023-03-29 21:00:02 +02:00
1777a32899 Merge pull request '#281' (#282) from #281 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#282
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #281
2023-03-29 19:45:10 +02:00
3e5301b2d8 Merge branch '1.0.1' into #281 2023-03-29 19:39:04 +02:00
653562b908 idk #281 2023-03-29 19:38:42 +02:00
8025c31339 Set xp by level only when incoming level is different from user level #281 2023-03-29 19:38:25 +02:00
ccf41bec79 Retry select after half a second 2023-03-29 15:17:19 +02:00
f75d8f2068 Merge pull request 'Fixed reaction handling #279' (#280) from #279 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#280
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #279
2023-03-29 14:53:49 +02:00
da02aca7e4 Fixed reaction handling #279 2023-03-29 14:52:36 +02:00
3762f16c7e Merge pull request 'Fixed remove warning team notification #270' (#271) from #270 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#271
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #270
2023-03-28 23:39:41 +02:00
b3099121ab Build bot version #270 2023-03-28 23:36:33 +02:00
6a750ee31b Set bot version #270 2023-03-28 23:36:06 +02:00
3c371ec074 Set correct frontend version #270 2023-03-28 23:34:42 +02:00
d818eafb9d Merge branch '1.0.1' into #270 2023-03-28 23:30:32 +02:00
b4a5fdb258 Merge pull request 'Fixed unnecessary voice states #274' (#275) from #274 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#275
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #274
2023-03-28 23:29:47 +02:00
cf69436168 Merge pull request 'Fixed can_user_see_element #272' (#273) from #272 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#273
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #272
2023-03-28 23:29:35 +02:00
ccf171e876 Merge pull request 'Fixed id access #266' (#267) from #266 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#267
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #266
2023-03-28 23:29:22 +02:00
5a312bf660 Merge pull request 'Als Admin möchte ich, dass bei Erstellung einer AutoRollen Regel die Reaktion automatisch hinzugefügt wird #259' (#263) from #259 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#263
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #259
2023-03-28 23:29:05 +02:00
0003255d7c Merge branch '1.0.1' into #274 2023-03-28 18:24:21 +02:00
27a4c140e4 Fixed unnecessary voice states #274 2023-03-28 18:23:45 +02:00
3183461195 Merge branch '1.0.1' into #272 2023-03-28 15:46:14 +02:00
cb4f8d870c Fixed can_user_see_element #272 2023-03-28 15:45:38 +02:00
7c447bb0f2 Set frontend version for patch version #270 2023-03-28 15:04:20 +02:00
4debe4e2ba Fixed remove warning team notification #270 2023-03-28 15:01:35 +02:00
3cd3df3e5f Merge branch '1.0.1' into #266 2023-03-27 19:46:51 +02:00
b4a631d4e4 Fixed id access #266 2023-03-27 19:46:10 +02:00
7ba0247519 Merge pull request 'Fixed dropdown color #260' (#262) from #260 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#262
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #260
2023-03-27 19:35:30 +02:00
209e75fdcc Merge pull request 'Disabled add button for mods in level list #264' (#265) from #264 into 1.0.1
Reviewed-on: sh-edraft.de/kd_discord_bot#265
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #264
2023-03-27 19:35:04 +02:00
3bca3f86eb Disabled add button for mods in level list #264 2023-03-27 19:33:22 +02:00
657a8fa586 Added comment #259 2023-03-27 10:17:56 +02:00
3c8a092f40 Added logic to add reaction after creating auto role rule in WI #259 2023-03-27 10:17:55 +02:00
61bf508cea Fixed dropdown color #260 2023-03-27 10:04:18 +02:00
75ad07477a Merge pull request '1.0.0' (#253) from 1.0.0 into master
Reviewed-on: sh-edraft.de/kd_discord_bot#253
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-03-27 09:30:49 +02:00
132d41f0a2 Fixed some stuff 2023-03-26 22:58:56 +02:00
707a835672 Updated docker & config 2023-03-26 20:08:04 +02:00
f56dbf8e2a Merge pull request 'Fixed permission handling for member data #256' (#258) from #256 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#258
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
#Closes #256
2023-03-25 18:01:57 +01:00
c311e534d7 Merge pull request 'Fixed profile navigation #255' (#257) from #255 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#257
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #255
2023-03-25 18:01:41 +01:00
87b277515c Fixed permission handling for member data #256 2023-03-24 14:23:13 +01:00
e6c614dfdc Fixed profile navigation #255 2023-03-24 14:15:21 +01:00
24d5bbf4d8 Made version in presence optional 2023-03-24 14:14:49 +01:00
52035af0cc Fixed jwt handling 2023-03-21 19:14:39 +01:00
fdc9a118c8 Fixed jwt handling 2023-03-20 16:30:07 +01:00
ba1f4ee955 Merge pull request '1.0.0-fix' (#254) from 1.0.0-fix into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#254
2023-03-20 14:41:33 +01:00
35d161c080 Removed obsolete fix 2023-03-20 14:40:56 +01:00
818163cbed Formatted tools 2023-03-20 14:39:23 +01:00
468ebb5f79 Merge branch 'master' into 1.0.0-fix
# Conflicts:
#	kdb-bot/src/bot/__init__.py
#	kdb-bot/src/bot/bot.json
#	kdb-bot/src/bot/config
#	kdb-bot/src/bot/extension/__init__.py
#	kdb-bot/src/bot_api/__init__.py
#	kdb-bot/src/bot_api/abc/__init__.py
#	kdb-bot/src/bot_api/bot-api.json
#	kdb-bot/src/bot_api/configuration/__init__.py
#	kdb-bot/src/bot_api/controller/__init__.py
#	kdb-bot/src/bot_api/event/__init__.py
#	kdb-bot/src/bot_api/exception/__init__.py
#	kdb-bot/src/bot_api/filter/__init__.py
#	kdb-bot/src/bot_api/filter/discord/__init__.py
#	kdb-bot/src/bot_api/logging/__init__.py
#	kdb-bot/src/bot_api/model/__init__.py
#	kdb-bot/src/bot_api/model/discord/__init__.py
#	kdb-bot/src/bot_api/route/__init__.py
#	kdb-bot/src/bot_api/service/__init__.py
#	kdb-bot/src/bot_api/transformer/__init__.py
#	kdb-bot/src/bot_core/__init__.py
#	kdb-bot/src/bot_core/abc/__init__.py
#	kdb-bot/src/bot_core/bot-core.json
#	kdb-bot/src/bot_core/configuration/__init__.py
#	kdb-bot/src/bot_core/core_extension/__init__.py
#	kdb-bot/src/bot_core/events/__init__.py
#	kdb-bot/src/bot_core/exception/__init__.py
#	kdb-bot/src/bot_core/helper/__init__.py
#	kdb-bot/src/bot_core/logging/__init__.py
#	kdb-bot/src/bot_core/pipes/__init__.py
#	kdb-bot/src/bot_core/service/__init__.py
#	kdb-bot/src/bot_data/__init__.py
#	kdb-bot/src/bot_data/abc/__init__.py
#	kdb-bot/src/bot_data/bot-data.json
#	kdb-bot/src/bot_data/migration/__init__.py
#	kdb-bot/src/bot_data/model/__init__.py
#	kdb-bot/src/bot_data/service/__init__.py
#	kdb-bot/src/bot_graphql/__init__.py
#	kdb-bot/src/bot_graphql/abc/__init__.py
#	kdb-bot/src/bot_graphql/filter/__init__.py
#	kdb-bot/src/bot_graphql/mutations/__init__.py
#	kdb-bot/src/modules/auto_role/__init__.py
#	kdb-bot/src/modules/auto_role/auto-role.json
#	kdb-bot/src/modules/auto_role/command/__init__.py
#	kdb-bot/src/modules/auto_role/events/__init__.py
#	kdb-bot/src/modules/auto_role/helper/__init__.py
#	kdb-bot/src/modules/base/__init__.py
#	kdb-bot/src/modules/base/abc/__init__.py
#	kdb-bot/src/modules/base/base.json
#	kdb-bot/src/modules/base/command/__init__.py
#	kdb-bot/src/modules/base/configuration/__init__.py
#	kdb-bot/src/modules/base/events/__init__.py
#	kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py
#	kdb-bot/src/modules/base/helper/__init__.py
#	kdb-bot/src/modules/base/model/__init__.py
#	kdb-bot/src/modules/base/service/__init__.py
#	kdb-bot/src/modules/base/thread/__init__.py
#	kdb-bot/src/modules/boot_log/__init__.py
#	kdb-bot/src/modules/boot_log/boot-log.json
#	kdb-bot/src/modules/boot_log/configuration/__init__.py
#	kdb-bot/src/modules/database/__init__.py
#	kdb-bot/src/modules/database/database.json
#	kdb-bot/src/modules/level/__init__.py
#	kdb-bot/src/modules/level/command/__init__.py
#	kdb-bot/src/modules/level/configuration/__init__.py
#	kdb-bot/src/modules/level/events/__init__.py
#	kdb-bot/src/modules/level/level.json
#	kdb-bot/src/modules/level/service/__init__.py
#	kdb-bot/src/modules/permission/__init__.py
#	kdb-bot/src/modules/permission/abc/__init__.py
#	kdb-bot/src/modules/permission/configuration/__init__.py
#	kdb-bot/src/modules/permission/events/__init__.py
#	kdb-bot/src/modules/permission/permission.json
#	kdb-bot/src/modules/permission/service/__init__.py
#	kdb-bot/src/modules/stats/service/__init__.py
#	kdb-bot/src/modules/stats/stats.json
#	kdb-bot/src/modules/technician/__init__.py
#	kdb-bot/src/modules/technician/command/__init__.py
#	kdb-bot/src/modules/technician/technician.json
#	kdb-bot/tools/get_version/get-version.json
#	kdb-bot/tools/post_build/post-build.json
#	kdb-bot/tools/set_version/set-version.json
2023-03-20 14:39:18 +01:00
085726bf60 Updated config 2023-03-20 14:32:44 +01:00
223abbe66f Fixed user mutation 2023-03-20 14:11:02 +01:00
4c5a8baed5 Build release 2023-03-20 14:01:08 +01:00
59162408e5 Merge pull request 'Datenschutz und Impressum angeben #251' (#252) from #251 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#252
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #251
2023-03-20 13:42:23 +01:00
634b81d23b Merge branch '1.0.0' into #251 2023-03-20 13:40:17 +01:00
c0cd5bb70e Merge pull request '1.0.0.rc2' (#250) from 1.0.0.rc2 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#250
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-03-20 13:40:00 +01:00
cc0a0a5c69 Added logic to confirm privacy before registration #251 2023-03-17 14:43:16 +01:00
4420c0e11c Added imprint & privacy to auth and improved getting url #251 2023-03-17 13:48:48 +01:00
7be40ed236 Added imprint and privacy urls 2023-03-17 13:18:33 +01:00
ff415c354d Merge branch '1.0.0' into 1.0.0.rc2 2023-03-14 18:43:35 +01:00
283eaabef6 Merge pull request 'Als Nutzer möchte ich Datenänderungen nach verfolgen können #246' (#248) from #246 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#248
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Reviewed-by: Jonas <joni.drescher@web.de>
2023-03-14 18:31:36 +01:00
b7e72888f7 Fixed translation #246 2023-03-14 17:00:52 +01:00
b29227e8d5 Fixed translation 2023-03-14 17:00:34 +01:00
9f57182fc1 Fixed collection sorting & paging order 2023-03-14 15:32:26 +01:00
699377be54 Added type hints #246 2023-03-14 15:32:00 +01:00
efba1a4ce8 Added type hints #246 2023-03-12 18:46:39 +01:00
68fa1b8c2d Fixed translation 2023-03-12 05:04:26 +01:00
8b79d69e41 Build 1.0.0.rc2 2023-03-12 04:55:42 +01:00
c1b75dff78 Set frontent version 1.0.0.rc2 2023-03-12 04:55:42 +01:00
5f284597aa Build 1.0.0.rc2 2023-03-12 04:55:42 +01:00
e1b1a68b07 Set version for rc2 2023-03-12 04:55:42 +01:00
b1a0115e8b Fixed db set date & show only changed fields in history view #246 2023-03-12 04:55:04 +01:00
ad00dce5d9 Fixed mysql scripts #246 2023-03-11 03:09:27 +01:00
e3c47ce5b1 Fixed mysql scripts #246 2023-03-11 03:09:18 +01:00
68026e4b47 Improved history component #246 2023-03-11 03:08:47 +01:00
ee503f76f2 Order history tables #246 2023-03-11 01:19:06 +01:00
a1f7b8b2dc Added en and fixed de translation #246 2023-03-11 01:19:06 +01:00
b8e4146b33 Added history to all data tables #246 2023-03-11 01:19:06 +01:00
51f0ee5744 Improved history component #246 2023-03-11 01:19:06 +01:00
69ce659328 Added history tables to graphql #246 2023-03-11 01:18:35 +01:00
325a17b5a8 Added level history to graphql #246 2023-03-11 01:18:35 +01:00
5df0501505 Added last migration parts #246 2023-03-11 01:18:35 +01:00
c3ef7a746f [WIP] Added last tables #246 2023-03-11 01:18:35 +01:00
bca33c6e56 [WIP] Added more tables #246 2023-03-11 01:18:35 +01:00
d24d3fa4de [WIP] Added more tables #246 2023-03-11 01:18:35 +01:00
1755efb5d9 [WIP] Added migration and basics for history logic #246 2023-03-11 01:18:35 +01:00
54b0086a14 Merge pull request 'Unbekannte Benutzer führen zu einem Fehler mit tracking id statt einer fehlermeldung #247' (#249) from #247 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#249
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
Closes #247
2023-03-11 01:17:15 +01:00
f404287cc1 Merge branch '1.0.0' into #247 2023-03-11 01:14:47 +01:00
7966ca16e5 Merge pull request '1.0.0.rc1' (#244) from 1.0.0.rc1 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#244
Reviewed-by: edraft-dev <dev.sven.heidemann@sh-edraft.de>
2023-03-11 01:12:31 +01:00
c0e5f0d4b0 Updated config 2023-03-09 19:41:10 +01:00
80769a1bf0 Fixed permission service 2023-03-09 19:27:56 +01:00
bc92dc4536 Fixed icon buttons #247 2023-03-09 11:22:10 +01:00
16ef29999c Fixed _is_email_valid method #247 2023-03-09 11:15:28 +01:00
33279b7053 Fixed collection count field #247 2023-03-09 11:12:48 +01:00
04fcfddbd9 Code cleanup #247 2023-03-09 11:10:53 +01:00
21f0f32322 Retranslate sidebar on lang change 2023-03-06 10:54:58 +01:00
d1420d18c0 Put boot log send message in loop task #243 2023-03-06 10:54:58 +01:00
22d26bf032 Reload levelsystem after mutate levels #245 2023-03-06 10:54:58 +01:00
a701807831 Fixed frontend permissions 2023-03-06 10:54:58 +01:00
3324cf3ac3 Fixed time calculation for user joined gs/vs 2023-03-06 10:54:58 +01:00
1664c67763 Fixed time calculation for user joined gs/vs 2023-03-06 10:54:58 +01:00
bddcd3929a Updated docker compose 2023-03-06 10:54:58 +01:00
23e17c1f38 Fixed auto-role error 2023-03-06 08:42:48 +01:00
883811d156 Removed minecraft_id 2023-03-06 08:42:48 +01:00
4d0e8898fe Build frontend 2023-03-06 08:42:48 +01:00
505c87b996 Build version 2023-03-06 08:42:48 +01:00
18fe6ecb86 Set version for rc 2023-03-06 08:42:48 +01:00
f02268c1a1 Merge pull request '#238' (#242) from #238 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#242
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #238
2023-03-06 08:42:21 +01:00
1b328dc20e Fixed translation #238 2023-03-06 08:05:30 +01:00
34c362a391 Improved game server handling for ontime #238 2023-03-06 08:05:08 +01:00
15dfc3f47c Added GameServer & ApiKey logic #238 2023-03-06 08:05:08 +01:00
91b2cf7546 Added GameServer handling & commands #238 2023-03-06 08:05:08 +01:00
a8dad6b223 Added GameServer data model #238 2023-03-06 08:05:08 +01:00
124209c371 Merge pull request '#240' (#241) from #240 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#241
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #240
2023-03-05 21:55:39 +01:00
d24c8e40de Merge branch '1.0.0' into #240 2023-03-05 21:47:53 +01:00
54004d10a5 Merge pull request 'Übersetzungen in Front und Backend aufräumen #232' (#237) from #232 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#237
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #232
2023-03-05 21:47:38 +01:00
a510cf731f Fixed german translation #232 2023-03-05 21:42:51 +01:00
23b7e4f59c Fixed english translation #232 2023-03-05 21:33:30 +01:00
24f90657e1 Fixed german translation #232 2023-03-05 21:22:22 +01:00
454fabb3e3 Added migration only mode #240 2023-03-04 18:57:51 +01:00
a588f8bf72 Merge pull request 'Verwarnungssystem #35' (#235) from #35 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#235
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #35
2023-02-24 08:49:08 +01:00
d75503569e Refactored translations #232 2023-02-23 10:58:08 +01:00
5b265488df Refactored translations #232 2023-02-23 10:56:07 +01:00
2d995544c3 Code refactoring #35 2023-02-23 08:58:04 +01:00
e5fb9fd504 Merge branch '1.0.0' into #35 2023-02-23 08:46:52 +01:00
a80bbc33cf Merge pull request 'Fixed table loading #220' (#236) from #220 into 1.0.0
Reviewed-on: sh-edraft.de/kd_discord_bot#236
Reviewed-by: Ebola-Chan <nick.jungmann@gmail.com>
Closes #220
2023-02-23 08:46:04 +01:00
6915515932 Fixed table loading #220 2023-02-22 21:02:49 +01:00
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
2674af64e9 Added warning commands #35 2023-02-22 08:44:08 +01:00
1eb625fe7a Improved warning handling #35 2023-02-22 08:39:50 +01:00
19f47a01e5 Added warnings service #35 2023-02-22 08:39:50 +01:00
8ff21debf0 Added user warning repository #35 2023-02-22 08:39:50 +01:00
89bcb655d2 Added user warning model #35 2023-02-22 08:39:50 +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
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
e1c89814da Fixed voice state update (ontime) handling 2023-01-19 20:02:56 +01:00
53cdaf3fa0 Added get_ontime_overlaps script 2023-01-19 19:34:03 +01:00
b11ce18ac9 Fixed switch channel handling 2023-01-19 18:35:49 +01:00
505 changed files with 21431 additions and 12711 deletions

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) 2022-2023 sh-edraft.de
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,100 @@
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class DBTable(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
self._name = self._name.replace("_db_table", "")
self._class_name = self._class_name.split("Db_table")[0]
def get_code(self) -> str:
import textwrap
code = textwrap.dedent(
"""\
from datetime import datetime
from cpl_core.database import TableABC
class $ClassName(TableABC):
def __init__(
self,
value: str,
created_at: datetime = None,
modified_at: datetime = None,
id=0,
):
self._id = id
self._value = value
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 value(self) -> str:
return self._value
@value.setter
def value(self, value: str):
self._value = value
@staticmethod
def get_select_all_string() -> str:
return str(
f\"""
SELECT * FROM `$TableName`;
\"""
)
@staticmethod
def get_select_by_id_string(id: int) -> str:
return str(
f\"""
SELECT * FROM `$TableName`
WHERE `Id` = {id};
\"""
)
@property
def insert_string(self) -> str:
return str(
f\"""
INSERT INTO `$TableName` (
`Value`
) VALUES (
{self._value}
);
\"""
)
@property
def udpate_string(self) -> str:
return str(
f\"""
UPDATE `$TableName`
SET `Value` = {self._value}
WHERE `Id` = {self._id};
\"""
)
@property
def delete_string(self) -> str:
return str(
f\"""
DELETE FROM `$TableName`
WHERE `Id` = {self._id};
\"""
)
"""
)
return self.build_code_str(
code,
ClassName=self._class_name,
TableName=self._class_name,
)
@classmethod
def register(cls):
GenerateSchematicABC.register(cls, "db-table", [])

View File

@@ -0,0 +1,55 @@
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class Migration(GenerateSchematicABC):
def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args)
def get_code(self) -> str:
import textwrap
code = textwrap.dedent(
"""\
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.migration_abc import MigrationABC
from bot_data.db_context import DBContext
class $ClassName(MigrationABC):
name = "1.0_$ClassName"
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 `$TableName` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`CreatedAt` DATETIME(6),
`LastModifiedAt` DATETIME(6),
PRIMARY KEY(`Id`)
);
\"""
)
)
def downgrade(self):
self._cursor.execute("DROP TABLE `$TableName`;")
"""
)
return self.build_code_str(
code,
ClassName=self._class_name,
TableName=self._class_name.split("Migration")[0],
)
@classmethod
def register(cls):
GenerateSchematicABC.register(cls, "migration", [])

View File

@@ -1,7 +1,7 @@
from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC
class query(GenerateSchematicABC): class Query(GenerateSchematicABC):
def __init__(self, *args: str): def __init__(self, *args: str):
GenerateSchematicABC.__init__(self, *args) GenerateSchematicABC.__init__(self, *args)

View File

@@ -7,38 +7,34 @@
"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", "bot-graphql": "src/bot_graphql/bot-graphql.json",
"achievements": "src/modules/achievements/achievements.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",
"config": "src/modules/config/config.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",
"technician": "src/modules/technician/technician.json", "technician": "src/modules/technician/technician.json",
"checks": "tools/checks/checks.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",
"set-version": "tools/set_version/set-version.json" "set-version": "tools/set_version/set-version.json"
}, },
"Scripts": { "Scripts": {
"format": "black ./", "format": "black ./",
"sv": "cpl set-version $ARGS", "sv": "cpl set-version $ARGS",
"set-version": "cpl run set-version $ARGS --dev; echo '';", "set-version": "cpl run set-version $ARGS --dev; echo '';",
"gv": "cpl get-version", "gv": "cpl get-version",
"get-version": "export VERSION=$(cpl run get-version --dev); echo $VERSION;", "get-version": "export VERSION=$(cpl run get-version --dev); echo $VERSION;",
"pre-build": "cpl set-version $ARGS; black ./;", "pre-build": "cpl set-version $ARGS; black ./;",
"post-build": "cpl run post-build --dev; black ./;", "post-build": "cpl run post-build --dev; black ./;",
"pre-prod": "cpl build", "pre-prod": "cpl build",
"prod": "export KDB_ENVIRONMENT=production; export KDB_NAME=KDB-Prod; cpl start;", "prod": "export KDB_ENVIRONMENT=production; export KDB_NAME=KDB-Prod; cpl start;",
"pre-stage": "cpl build", "pre-stage": "cpl build",
"stage": "export KDB_ENVIRONMENT=staging; export KDB_NAME=KDB-Stage; cpl start;", "stage": "export KDB_ENVIRONMENT=staging; export KDB_NAME=KDB-Stage; cpl start;",
"pre-dev": "cpl build", "pre-dev": "cpl build",
"dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;", "dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;",
"docker-build": "cpl build $ARGS; docker build -t kdb-bot/kdb-bot:$(cpl gv) .;", "docker-build": "cpl build $ARGS; docker build -t kdb-bot/kdb-bot:$(cpl gv) .;",
"dc-up": "docker-compose up -d", "dc-up": "docker-compose up -d",
"dc-down": "docker-compose down", "dc-down": "docker-compose down",

View File

@@ -15,4 +15,7 @@ RUN apk add nano
RUN pip install -r requirements.txt --extra-index-url https://pip.sh-edraft.de RUN pip install -r requirements.txt --extra-index-url https://pip.sh-edraft.de
RUN pip install flask[async] RUN pip install flask[async]
# RUN pip install dnspython==2.2.1 # https://stackoverflow.com/questions/75137717/eventlet-dns-python-attribute-error-module-dns-rdtypes-has-no-attribute-any
# ^ probably fixed py package updates
CMD [ "bash", "/app/bot/bot"] CMD [ "bash", "/app/bot/bot"]

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

View File

@@ -10,6 +10,7 @@ from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSet
from bot_api.api_thread import ApiThread from bot_api.api_thread import ApiThread
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_core.service.data_integrity_service import DataIntegrityService
class Application(DiscordBotApplicationABC): class Application(DiscordBotApplicationABC):
@@ -21,6 +22,7 @@ class Application(DiscordBotApplicationABC):
# cpl-core # cpl-core
self._logger: LoggerABC = services.get_service(LoggerABC) self._logger: LoggerABC = services.get_service(LoggerABC)
self._data_integrity: DataIntegrityService = services.get_service(DataIntegrityService)
# cpl-discord # cpl-discord
self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC) self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC)
self._bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings) self._bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings)
@@ -52,7 +54,7 @@ class Application(DiscordBotApplicationABC):
self._api.join() self._api.join()
return return
self._logger.trace(__name__, f"Try to start {DiscordBotService.__name__}") self._logger.info(__name__, f"Try to start {DiscordBotService.__name__}")
await self._bot.start_async() await self._bot.start_async()
await self._bot.stop_async() await self._bot.stop_async()
except Exception as e: except Exception as e:
@@ -64,13 +66,17 @@ class Application(DiscordBotApplicationABC):
self._is_stopping = True self._is_stopping = True
try: try:
self._logger.trace(__name__, f"Try to stop {DiscordBotService.__name__}") self._logger.info(__name__, f"Try to stop {DiscordBotService.__name__}")
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
self._api.stop()
await self._bot.close() await self._bot.close()
self._logger.trace(__name__, f"Stopped {DiscordBotService.__name__}") await self._data_integrity.check_data_integrity(is_for_shutdown=True)
self._logger.info(__name__, f"Stopped {DiscordBotService.__name__}")
except Exception as e: except Exception as e:
self._logger.error(__name__, "stop failed", e) self._logger.error(__name__, "stop failed", e)
Console.write_line() Console.write_line()
def is_restart(self): def is_restart(self):
return True if self._configuration.get_configuration("IS_RESTART") == "true" else False # return True if self._configuration.get_configuration("IS_RESTART") == "true" else False

View File

@@ -3,8 +3,8 @@
"Name": "bot", "Name": "bot",
"Version": { "Version": {
"Major": "1", "Major": "1",
"Minor": "0", "Minor": "1",
"Micro": "dev130" "Micro": "0"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de", "AuthorEmail": "sven.heidemann@sh-edraft.de",
@@ -16,24 +16,26 @@
"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.post3", "cpl-core==2023.4.0.post5",
"cpl-translation==2022.12.1", "cpl-translation==2023.4.0.post1",
"cpl-query==2022.12.2.post1", "cpl-query==2023.4.0.post1",
"Flask==2.2.2", "cpl-discord==2023.4.0.post3",
"Flask==2.3.2",
"Flask-Classful==0.14.2", "Flask-Classful==0.14.2",
"Flask-Cors==3.0.10", "Flask-Cors==4.0.0",
"PyJWT==2.6.0", "PyJWT==2.8.0",
"waitress==2.1.2", "waitress==2.1.2",
"Flask-SocketIO==5.3.2", "Flask-SocketIO==5.3.4",
"eventlet==0.33.3", "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", "ariadne==0.20.1",
"cpl-discord==2022.12.2" "cryptography==41.0.2",
"discord>=2.3.2"
], ],
"DevDependencies": [ "DevDependencies": [
"cpl-cli==2022.12.1.post3", "cpl-cli==2023.4.0.post3",
"pygount==1.5.1" "pygount==1.6.1"
], ],
"PythonVersion": ">=3.10.4", "PythonVersion": ">=3.10.4",
"PythonPath": {}, "PythonPath": {},
@@ -58,9 +60,11 @@
"../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", "../bot_graphql/bot-graphql.json",
"../modules/achievements/achievements.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/config/config.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",

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

View File

@@ -3,7 +3,7 @@ from cpl_core.configuration import ConfigurationABC
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC from cpl_discord.service import DiscordBotServiceABC
from bot_core.configuration.bot_settings import BotSettings from bot_data.model.technician_config import TechnicianConfig
class InitBotExtension(ApplicationExtensionABC): class InitBotExtension(ApplicationExtensionABC):
@@ -11,6 +11,6 @@ class InitBotExtension(ApplicationExtensionABC):
ApplicationExtensionABC.__init__(self) ApplicationExtensionABC.__init__(self)
async def run(self, config: ConfigurationABC, services: ServiceProviderABC): async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
settings = config.get_configuration(BotSettings) settings = config.get_configuration(TechnicianConfig)
bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC, max_messages=settings.cache_max_messages) bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC, max_messages=settings.cache_max_messages)

View File

@@ -15,6 +15,7 @@ from bot.startup_settings_extension import StartupSettingsExtension
from bot_api.app_api_extension import AppApiExtension from bot_api.app_api_extension import AppApiExtension
from bot_core.core_extension.core_extension import CoreExtension from bot_core.core_extension.core_extension import CoreExtension
from modules.boot_log.boot_log_extension import BootLogExtension from modules.boot_log.boot_log_extension import BootLogExtension
from modules.config.config_extension import ConfigExtension
from modules.database.database_extension import DatabaseExtension from modules.database.database_extension import DatabaseExtension
@@ -30,15 +31,17 @@ class Program:
.use_extension(StartupDiscordExtension) .use_extension(StartupDiscordExtension)
.use_extension(StartupModuleExtension) .use_extension(StartupModuleExtension)
.use_extension(StartupMigrationExtension) .use_extension(StartupMigrationExtension)
.use_extension(DatabaseExtension)
.use_extension(ConfigExtension)
.use_extension(InitBotExtension) .use_extension(InitBotExtension)
.use_extension(BootLogExtension) .use_extension(BootLogExtension)
.use_extension(DatabaseExtension)
.use_extension(AppApiExtension) .use_extension(AppApiExtension)
.use_extension(CoreExtension) .use_extension(CoreExtension)
.use_startup(Startup) .use_startup(Startup)
) )
self.app: Application = await app_builder.build_async() self.app: Application = await app_builder.build_async()
await self.app.run_async() await self.app.run_async()
Console.write_line(f"[ INFO ] [ {__name__} ]: Finished app.run_async")
async def stop(self): async def stop(self):
if self.app is None: if self.app is None:

View File

@@ -5,9 +5,11 @@ 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 bot_graphql.graphql_module import GraphQLModule
from modules.achievements.achievements_module import AchievementsModule
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.config.config_module import ConfigModule
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
@@ -23,14 +25,16 @@ class ModuleList:
[ [
CoreModule, # has to be first! CoreModule, # has to be first!
DataModule, DataModule,
ConfigModule, # has to be before db check
DatabaseModule,
GraphQLModule, GraphQLModule,
PermissionModule, PermissionModule,
LevelModule,
DatabaseModule,
AutoRoleModule, AutoRoleModule,
BaseModule, BaseModule,
LevelModule,
ApiModule, ApiModule,
TechnicianModule, TechnicianModule,
AchievementsModule,
# has to be last! # has to be last!
BootLogModule, BootLogModule,
CoreExtensionModule, CoreExtensionModule,

View File

@@ -4,10 +4,14 @@ 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.achievements_migration import AchievementsMigration
from bot_data.migration.api_key_migration import ApiKeyMigration 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.config_feature_flags_migration import ConfigFeatureFlagsMigration
from bot_data.migration.config_migration import ConfigMigration
from bot_data.migration.db_history_migration import DBHistoryMigration
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.remove_stats_migration import RemoveStatsMigration
@@ -16,6 +20,7 @@ from bot_data.migration.user_joined_game_server_migration import UserJoinedGameS
from bot_data.migration.user_message_count_per_hour_migration import ( from bot_data.migration.user_message_count_per_hour_migration import (
UserMessageCountPerHourMigration, UserMessageCountPerHourMigration,
) )
from bot_data.migration.user_warning_migration import UserWarningMigration
from bot_data.service.migration_service import MigrationService from bot_data.service.migration_service import MigrationService
@@ -38,3 +43,8 @@ class StartupMigrationExtension(StartupExtensionABC):
services.add_transient(MigrationABC, ApiKeyMigration) # 09.02.2023 #162 - 1.0.0 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, UserJoinedGameServerMigration) # 12.02.2023 #181 - 1.0.0
services.add_transient(MigrationABC, RemoveStatsMigration) # 19.02.2023 #190 - 1.0.0 services.add_transient(MigrationABC, RemoveStatsMigration) # 19.02.2023 #190 - 1.0.0
services.add_transient(MigrationABC, UserWarningMigration) # 21.02.2023 #35 - 1.0.0
services.add_transient(MigrationABC, DBHistoryMigration) # 06.03.2023 #246 - 1.0.0
services.add_transient(MigrationABC, AchievementsMigration) # 14.06.2023 #268 - 1.1.0
services.add_transient(MigrationABC, ConfigMigration) # 19.07.2023 #127 - 1.1.0
services.add_transient(MigrationABC, ConfigFeatureFlagsMigration) # 15.08.2023 #334 - 1.1.0

View File

@@ -1,6 +1,6 @@
import os import os
from datetime import datetime from datetime import datetime
from typing import Callable, Type, Optional from typing import Optional, Type, Callable
from cpl_core.application import StartupExtensionABC from cpl_core.application import StartupExtensionABC
from cpl_core.configuration import ConfigurationABC from cpl_core.configuration import ConfigurationABC
@@ -8,11 +8,6 @@ from cpl_core.dependency_injection import ServiceCollectionABC
from cpl_core.environment import ApplicationEnvironmentABC from cpl_core.environment import ApplicationEnvironmentABC
from bot_core.configuration.bot_logging_settings import BotLoggingSettings from bot_core.configuration.bot_logging_settings import BotLoggingSettings
from bot_core.configuration.bot_settings import BotSettings
from modules.base.configuration.base_settings import BaseSettings
from modules.boot_log.configuration.boot_log_settings import BootLogSettings
from modules.level.configuration.level_settings import LevelSettings
from modules.permission.configuration.permission_settings import PermissionSettings
class StartupSettingsExtension(StartupExtensionABC): class StartupSettingsExtension(StartupExtensionABC):
@@ -34,13 +29,6 @@ class StartupSettingsExtension(StartupExtensionABC):
configuration.add_json_file(f"config/feature-flags.{environment.host_name}.json", optional=True) configuration.add_json_file(f"config/feature-flags.{environment.host_name}.json", optional=True)
configuration.add_configuration("Startup_StartTime", str(self._start_time)) configuration.add_configuration("Startup_StartTime", str(self._start_time))
self._configure_settings_with_sub_settings(configuration, BotSettings, lambda x: x.servers, lambda x: x.id)
self._configure_settings_with_sub_settings(configuration, BaseSettings, lambda x: x.servers, lambda x: x.id)
self._configure_settings_with_sub_settings(configuration, BootLogSettings, lambda x: x.servers, lambda x: x.id)
self._configure_settings_with_sub_settings(configuration, LevelSettings, lambda x: x.servers, lambda x: x.id)
self._configure_settings_with_sub_settings(
configuration, PermissionSettings, lambda x: x.servers, lambda x: x.id
)
self._configure_settings_with_sub_settings( self._configure_settings_with_sub_settings(
configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key
) )
@@ -50,9 +38,9 @@ class StartupSettingsExtension(StartupExtensionABC):
@staticmethod @staticmethod
def _configure_settings_with_sub_settings( def _configure_settings_with_sub_settings(
config: ConfigurationABC, settings: Type, list_atr: Callable, atr: Callable config: ConfigurationABC, settings_type: Type, list_atr: Callable, atr: Callable
): ):
settings: Optional[settings] = config.get_configuration(settings) settings: Optional[settings_type] = config.get_configuration(settings_type)
if settings is None: if settings is None:
return return

View File

@@ -1,51 +1,27 @@
{ {
"api": {
"api": {
"test_mail": {
"message": "Dies ist eine Test-Mail vom Krümelmonster Web Interface\nGesendet von {}-{}",
"subject": "Krümelmonster Web Interface Test-Mail"
}
},
"auth": {
"confirmation": {
"message": "Öffne den Link, um die E-Mail zu bestätigen:\n{}auth/register/{}",
"subject": "E-Mail für {} {} bestätigen"
},
"forgot_password": {
"message": "Öffne den Link, um das Passwort zu ändern:\n{}auth/forgot-password/{}",
"subject": "Passwort für {} {} zurücksetzen"
}
},
"mail": {
"automatic_mail": "\n\nDies ist eine automatische E-Mail.\nGesendet von {}-{}@{}"
}
},
"common": { "common": {
"hello_world": "Hallo Welt",
"bot_has_no_permission_message": "Ey!!!\nWas soll das?\nIch habe keine Berechtigungen :(\nScheiß System...", "bot_has_no_permission_message": "Ey!!!\nWas soll das?\nIch habe keine Berechtigungen :(\nScheiß System...",
"no_permission_message": "Nein!\nIch höre nicht auf dich ¯\\_(ツ)_/¯",
"not_implemented_yet": "Ey Alter, das kann ich noch nicht...",
"presence": {
"booting": "{} Ich fahre gerade hoch...",
"running": "{} Ich esse Kekse :D",
"restart": "{} Muss neue Kekse holen...",
"shutdown": "{} Ich werde bestimmt wieder kommen..."
},
"errors": {
"error": "Es gab einen Fehler. Meld dich bitte bei einem Admin.",
"command_error": "Es gab einen Fehler beim bearbeiten des Befehls. Meld dich bitte bei einem Admin.",
"missing_required_argument": "Fehler: Ein benötigter Parameter fehlt!",
"argument_parsing_error": "Fehler: Parameter konnte nicht gelesen werden!",
"unexpected_quote_error": "Fehler: Unerwarteter Zitat Fehler!",
"invalid_end_of_quoted_string_error": "Fehler: Ungültiges Zitatende!",
"expected_closing_quote_error": "Fehler: Erwarte Zitatende!",
"bad_argument": "Fehler: Ungültiger Parameter!",
"bad_union_argument": "Fehler: Ungültiger Union Parameter!",
"private_message_only": "Fehler: Nur private Nachrichten sind erlaubt!",
"no_private_message": "Fehler: Private Nachrichten sind nicht erlaubt!",
"check_failure": "Fehler: Du hast nicht die benötigte Berechtigung!",
"check_any_failure": "Fehler: Alle checks sind Fehlgeschlagen!",
"command_not_found": "Fehler: Befehl konnte nicht gefunden werden!",
"disabled_command": "Fehler: Befehl wurde deaktiviert!",
"command_invoke_error": "Fehler: Befehl konnte nicht aufgerufen werden!",
"too_many_arguments": "Fehler: Zu viele Parameter!",
"user_input_error": "Fehler: Eingabefehler!",
"command_on_cooldown": "Fehler: Befehl befindet sich im cooldown!",
"max_concurrency_reached": "Fehler: Maximale Parallelität erreicht!",
"not_owner": "Fehler: Du bist nicht mein besitzer!",
"missing_permissions": "Fehler: Berechtigungen fehlen!",
"bot_missing_permissions": "Fehler: Mir fehlen Berechtigungen!",
"missing_role": "Fehler: Benötigte Rolle fehlt!",
"bot_missing_role": "Fehler: Mir fehlt eine benötigte Rolle!",
"missing_any_role": "Fehler: Alle benötigten Rollen fehlen!",
"bot_missing_any_role": "Fehler: Mir fehlen alle benötigten Rollen!",
"nsfw_channel_required": "Fehler: NSFW Kanal benötigt!",
"extension_error": "Fehler: Erweiterungsfehler!",
"extension_already_loaded": "Fehler: Erweiterung wurde bereits geladen!",
"extension_not_loaded": "Fehler: Erweiterung wurde nicht geladen!",
"no_entry_point_error": "Fehler: Kein Eintrittspunkt!",
"extension_failed": "Fehler: Erweiterung ist fehlgeschlagen!",
"bot_not_ready_yet": "Ey Alter! Gedulde dich doch mal! ..."
},
"colors": { "colors": {
"blue": "Blau", "blue": "Blau",
"dark_blue": "Dunkelblau", "dark_blue": "Dunkelblau",
@@ -69,235 +45,315 @@
"red": "Rot", "red": "Rot",
"teal": "Blaugrün", "teal": "Blaugrün",
"yellow": "Gelb" "yellow": "Gelb"
},
"errors": {
"argument_parsing_error": "Fehler: Parameter konnte nicht gelesen werden!",
"bad_argument": "Fehler: Ungültiger Parameter!",
"bad_union_argument": "Fehler: Ungültiger Union Parameter!",
"bot_missing_any_role": "Fehler: Mir fehlen alle benötigten Rollen!",
"bot_missing_permissions": "Fehler: Mir fehlen Berechtigungen!",
"bot_missing_role": "Fehler: Mir fehlt eine benötigte Rolle!",
"bot_not_ready_yet": "Ey Alter! Gedulde dich doch mal! ...",
"check_any_failure": "Fehler: Alle Checks sind Fehlgeschlagen!",
"check_failure": "Fehler: Du hast nicht die benötigte Berechtigung!",
"command_error": "Es gab einen Fehler beim Bearbeiten des Befehls. Melde dich bitte bei einem Admin.",
"command_invoke_error": "Fehler: Befehl konnte nicht aufgerufen werden!",
"command_not_found": "Fehler: Befehl konnte nicht gefunden werden!",
"command_on_cooldown": "Fehler: Befehl befindet sich im Cooldown!",
"disabled_command": "Fehler: Befehl wurde deaktiviert!",
"error": "Es gab einen Fehler. Melde dich bitte bei einem Admin.",
"expected_closing_quote_error": "Fehler: Erwarte Zitatende!",
"extension_already_loaded": "Fehler: Erweiterung wurde bereits geladen!",
"extension_error": "Fehler: Erweiterungsfehler!",
"extension_failed": "Fehler: Erweiterung ist fehlgeschlagen!",
"extension_not_loaded": "Fehler: Erweiterung wurde nicht geladen!",
"invalid_end_of_quoted_string_error": "Fehler: Ungültiges Zitatende!",
"max_concurrency_reached": "Fehler: Maximale Parallelität erreicht!",
"missing_any_role": "Fehler: Alle benötigten Rollen fehlen!",
"missing_permissions": "Fehler: Berechtigungen fehlen!",
"missing_required_argument": "Fehler: Ein benötigter Parameter fehlt!",
"missing_role": "Fehler: Benötigte Rolle fehlt!",
"no_entry_point_error": "Fehler: Kein Eintrittspunkt!",
"no_private_message": "Fehler: Private Nachrichten sind nicht erlaubt!",
"not_owner": "Fehler: Du bist nicht mein besitzer!",
"nsfw_channel_required": "Fehler: NSFW Kanal benötigt!",
"private_message_only": "Fehler: Nur private Nachrichten sind erlaubt!",
"too_many_arguments": "Fehler: Zu viele Parameter!",
"unexpected_quote_error": "Fehler: Unerwarteter Fehler beim Anführungszeichen!",
"user_input_error": "Fehler: Eingabefehler!"
},
"hello_world": "Hallo Welt",
"no_permission_message": "Nein!\nIch höre nicht auf dich ¯\\_(ツ)_/¯",
"not_implemented_yet": "Ey Alter, das kann ich noch nicht...",
"presence": {
"booting": "Ich fahre gerade hoch...",
"restart": "Muss neue Kekse holen...",
"running": "Ich esse Kekse :D",
"shutdown": "Ich werde bestimmt wieder kommen..."
} }
}, },
"modules": { "modules": {
"achievements": {
"got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D",
"commands": {
"check": "Alles klar, ich schaue eben nach... nom nom"
}
},
"auto_role": { "auto_role": {
"list": {
"title": "Beobachtete Nachrichten:",
"description": "Von auto-role beobachtete Nachrichten:",
"auto_role_id": "auto-role Id",
"message_id": "Nachricht-Id"
},
"add": { "add": {
"success": "auto-role für die Nachricht {} wurde hinzugefügt :D",
"error": { "error": {
"not_found": "Nachricht {} in {} nicht gefunden!", "already_exists": "auto-role für die Nachricht {} existiert bereits!",
"already_exists": "auto-role für die Nachricht {} existiert bereits!" "not_found": "Nachricht {} in {} nicht gefunden!"
} },
}, "success": "auto-role für die Nachricht {} wurde hinzugefügt :D"
"remove": {
"success": "auto-role {} wurde entfernt :D",
"error": {
"not_found": "auto-role {} nicht gefunden!"
}
}, },
"error": { "error": {
"nothing_found": "Keine auto-role Einträge gefunden." "nothing_found": "Keine auto-role Einträge gefunden."
}, },
"list": {
"auto_role_id": "auto-role Id",
"description": "Von auto-role beobachtete Nachrichten:",
"message_id": "Nachricht-Id",
"title": "Beobachtete Nachrichten:"
},
"remove": {
"error": {
"not_found": "auto-role {} nicht gefunden!"
},
"success": "auto-role {} wurde entfernt :D"
},
"rule": { "rule": {
"list": {
"title": "auto-role Regeln:",
"description": "Von auto-role angewendete Regeln:",
"auto_role_rule_id": "auto-role Regel Id",
"emoji": "Emoji",
"role": "Rolle"
},
"add": { "add": {
"success": "Regel {} -> {} für auto-role {} wurde hinzugefügt :D",
"error": { "error": {
"not_found": "Regel für auto-role {} nicht gefunden!", "already_exists": "Regel für auto-role {} existiert bereits!",
"emoji_not_found": "Emoji {} für auto-role Regel {} nicht gefunden!", "emoji_not_found": "Emoji {} für auto-role Regel {} nicht gefunden!",
"role_not_found": "Rolle {} für auto-role Regel {} nicht gefunden!", "not_found": "Regel für auto-role {} nicht gefunden!",
"already_exists": "Regel für auto-role {} existiert bereits!" "role_not_found": "Rolle {} für auto-role Regel {} nicht gefunden!"
} },
}, "success": "Regel {} -> {} für auto-role {} wurde hinzugefügt :D"
"remove": {
"success": "Regel für auto-role {} wurde entfernt :D",
"error": {
"not_found": "Regel für auto-role {} nicht gefunden!"
}
}, },
"error": { "error": {
"id_not_found": "Kein auto-role Eintrag mit der Id gefunden!" "id_not_found": "Kein auto-role Eintrag mit der Id gefunden!"
},
"list": {
"auto_role_rule_id": "auto-role Regel Id",
"description": "Von auto-role angewendete Regeln:",
"emoji": "Emoji",
"role": "Rolle",
"title": "auto-role Regeln:"
},
"remove": {
"error": {
"not_found": "Regel für auto-role {} nicht gefunden!"
},
"success": "Regel für auto-role {} wurde entfernt :D"
} }
} }
}, },
"moderator": {
"purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss."
},
"base": { "base": {
"technician_error_message": "Es gab ein Fehler mit dem Event: {}\nDatum und Zeit: {}\nSchau bitte ins log für Details.\nUUID: {}", "member_left_message": "{} hat uns leider verlassen :(",
"technician_command_error_message": "Es gab ein Fehler mit dem Befehl: {} ausgelöst von {} -> {}\nDatum und Zeit: {}\nSchau bitte ins log für Details.\nUUID: {}", "complaints": {
"welcome_message": "Hello There!\nIch heiße dich bei {} herzlichst Willkommen!", "title": "Beschwerde einreichen",
"welcome_message_for_team": "{} hat gerade das Irrenhaus betreten.", "label": "Beschwerde",
"goodbye_message": "Schade, dass du uns so schnell verlässt :(", "message": "{} hat eine Beschwerde eingereicht:\n{}",
"response": "Danke für deine Beschwerde"
},
"bug": {
"title": "Bug melden",
"label": "Bug",
"message": "{} meldet einen Bug:\n{}",
"response": "Danke für dein Feedback :D"
},
"afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?", "afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?",
"afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)", "afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)",
"member_joined_help_voice_channel": "{} braucht hilfe, bitte kümmer dich drum :D", "game_server": {
"pong": "Pong", "error": {
"nothing_found": "Keine Gameserver gefunden."
},
"list": {
"title": "Gameserver",
"description": "Konfigurierte Gameserver:",
"name": "Name",
"api_key": "API Key"
},
"add": {
"success": "Gameserver {} wurde hinzugefügt :)"
},
"remove": {
"success": "Gameserver wurde entfernt :D"
}
},
"goodbye_message": "Schade, dass du uns so schnell verlässt :(",
"info": { "info": {
"title": "Krümmelmonster",
"description": "Informationen über mich", "description": "Informationen über mich",
"fields": { "fields": {
"version": "Version",
"ontime": "Ontime",
"sent_message_count": "Gesendete Nachrichten",
"received_message_count": "Empfangene Nachrichten",
"deleted_message_count": "Gelöschte Nachrichten", "deleted_message_count": "Gelöschte Nachrichten",
"received_command_count": "Empfangene Befehle", "modules": "Module",
"moved_users_count": "Verschobene Benutzer", "moved_users_count": "Verschobene Benutzer",
"modules": "Module" "ontime": "Ontime",
"received_command_count": "Empfangene Befehle",
"received_message_count": "Empfangene Nachrichten",
"sent_message_count": "Gesendete Nachrichten",
"version": "Version"
}, },
"footer": "" "footer": "",
"title": "Krümelmonster"
}, },
"mass_move": { "mass_move": {
"moved": "Alle Personen aus {} wurden nach {} verschoben.", "channel_from_error": "Du musst dich in einem Voicechannel befinden oder die Option \"channel_from\" mit angeben.",
"channel_from_error": "Du musst dich in einem Voicechannel befinden oder die Option \"channel_from\" mit angeben." "moved": "Alle Personen aus {} wurden nach {} verschoben."
}, },
"member_joined_help_voice_channel": "{} braucht Hilfe, bitte kümmere dich drum :D",
"pong": "Pong",
"presence": { "presence": {
"changed": "Presence wurde geändert.", "changed": "Presence wurde geändert.",
"removed": "Presence wurde entfernt.", "max_char_count_exceeded": "Der Text darf nicht mehr als 128 Zeichen lang sein!",
"max_char_count_exceeded": "Der Text darf nicht mehr als 128 Zeichen lang sein!" "removed": "Presence wurde entfernt."
},
"register": {
"not_found": "Benutzer konnte nicht gefunden werden!",
"success": "Spieler wurde mit dem Mitglied verlinkt :D"
},
"technician_command_error_message": "Es gab ein Fehler mit dem Befehl: {} ausgelöst von {} -> {}\nDatum und Zeit: {}\nSchau bitte ins Log für Details.\nUUID: {}",
"technician_error_message": "Es gab ein Fehler mit dem Event: {}\nDatum und Zeit: {}\nSchau bitte ins Log für Details.\nUUID: {}",
"unregister": {
"success": "Verlinkung wurde entfernt :D"
}, },
"user": { "user": {
"add": {
"xp": "Die {} von {} wurden um {} erhöht"
},
"atr": { "atr": {
"id": "Id",
"name": "Name",
"discord_join": "Discord beigetreten am", "discord_join": "Discord beigetreten am",
"id": "Id",
"joins": "Beitritte",
"last_join": "Server beigetreten am", "last_join": "Server beigetreten am",
"xp": "XP", "lefts": "Abgänge",
"name": "Name",
"ontime": "Ontime", "ontime": "Ontime",
"roles": "Rollen", "roles": "Rollen",
"joins": "Beitritte", "warnings": "Verwarnungen",
"lefts": "Abgänge", "xp": "XP"
"warnings": "Verwarnungen" },
"error": {
"atr_not_found": "Das Attribut {} konnte nicht gefunden werden :("
},
"get": {
"ontime": "{} war insgesamt {} Stunden aktiv in einem Sprachkanal",
"xp": "{} hat {} xp"
}, },
"info": { "info": {
"footer": "" "footer": ""
}, },
"get": {
"xp": "{} hat {} xp",
"ontime": "{} war insgesamt {} Stunden aktiv in einem Sprachkanal"
},
"set": {
"xp": "{} hat nun {} xp",
"error": {
"value_type_not_numeric": "Der angegebende Wert ist keine Ganzzahl! :(",
"type_error": "Der angegebene Wert ist keine Zahl! :("
}
},
"add": {
"xp": "Die {} von {} wurden um {} erhöht"
},
"remove": { "remove": {
"xp": "Die {} von {} wurden um {} verringert" "xp": "Die {} von {} wurden um {} verringert"
}, },
"reset": { "reset": {
"xp": "Die {} von {} wurden entfernt", "ontime": "Die {} von {} wurden entfernt",
"ontime": "Die {} von {} wurden entfernt" "xp": "Die {} von {} wurden entfernt"
}, },
"error": { "set": {
"atr_not_found": "Das Attribut {} konnte nicht gefunden werden :(" "error": {
"type_error": "Der angegebene Wert ist keine Zahl! :(",
"value_type_not_numeric": "Der angegebende Wert ist keine Ganzzahl! :("
},
"xp": "{} hat nun {} xp"
} }
}, },
"register": { "warnings": {
"success": "Spieler wurde mit dem Mitglied verlinkt :D", "add": {
"not_found": "Benutzer nicht gefunden!" "failed": "Verwarnung konnte nicht hinzugefügt werden :(",
"success": "Verwarnung wurde hinzugefügt :)"
},
"first": "Bei der nächsten Verwarnung wirst du auf das vorherige Level zurückgesetzt!",
"kick": "Ich musste {} aufgrund zu vieler Verwarnungen kicken",
"remove": {
"failed": "Verwarnung konnte nicht entfernt werden :(",
"success": "Verwarnung wurde entfernt :)"
},
"removed": "Die Verwarnung '{}' wurde entfernt.",
"second": "Bei der nächsten verwarnung wirst du auf das erste Level zurückgesetzt!",
"show": {
"description": "Beschreibung",
"id": "Id"
},
"team_removed": "Die Verwarnung '{}' an {} wurde entfernt.",
"team_warned": "{} wurde verwarnt. Der Grund ist: {}",
"third": "Bei der nächsten verwarnung wirst du gekickt und zurückgesetzt!",
"warned": "Du wurdest verwarnt. Der Grund ist: {}"
}, },
"unregister": { "welcome_message": "Hello There!\nIch heiße dich bei {} herzlichst Willkommen!",
"success": "Verlinkung wurde entfernt :D" "welcome_message_for_team": "{} hat gerade das Irrenhaus betreten."
}
}, },
"boot_log": { "boot_log": {
"login_message": "Ich bin on the line :D\nDer Scheiß hat {} Sekunden gedauert" "login_message": "Ich bin on the line :D\nDer Scheiß hat {} Sekunden gedauert"
}, },
"level": { "level": {
"new_level_message": "{} ist nun Level {}",
"seeding_started": "Levelsystem wird neu geladen...",
"seeding_failed": "Levelsystem konnte nicht neu geladen werden :(",
"seeding_finished": "Levelsystem wurde Erfolgreich neu geladen :)",
"error": {
"nothing_found": "Keine Level Einträge gefunden.",
"level_with_name_already_exists": "Ein Level mit dem Namen {} existiert bereits!",
"level_with_xp_already_exists": "Das Level {} hat bereits die Mindest-XP {}!"
},
"list": {
"title": "Level:",
"description": "Konfigurierte Level:",
"name": "Name",
"min_xp": "Mindest-XP",
"permission_int": "Berechtigungen"
},
"create": { "create": {
"created": "Level {} mit Berechtigungen {} wurde erstellt :D" "created": "Level {} mit Berechtigungen {} wurde erstellt :D"
}, },
"edit": {
"edited": "Level {} wurde bearbeitet :D",
"color_invalid": "Die Farbe {} ist ungültig!",
"permission_invalid": "Der Berechtigungswert {} ist ungültig!",
"not_found": "Level {} nicht gefunden!"
},
"remove": {
"success": "Level {} wurde entfernt :D",
"error": {
"not_found": "Level {} nicht gefunden!"
}
},
"down": { "down": {
"already_first": "{} hat bereits das erste Level.", "already_first": "{} hat bereits das erste Level.",
"success": "{} wurde auf Level {} runtergesetzt :)", "failed": "{} konnte nicht runtergesetzt werden :(",
"failed": "{} konnte nicht runtergesetzt werden :(" "success": "{} wurde auf Level {} runtergesetzt :)"
},
"edit": {
"color_invalid": "Die Farbe {} ist ungültig!",
"edited": "Level {} wurde bearbeitet :D",
"not_found": "Level {} nicht gefunden!",
"permission_invalid": "Der Berechtigungswert {} ist ungültig!"
},
"error": {
"level_with_name_already_exists": "Ein Level mit dem Namen {} existiert bereits!",
"level_with_xp_already_exists": "Das Level {} hat bereits die Mindest-XP {}!",
"nothing_found": "Keine Einträge gefunden."
},
"list": {
"description": "Konfigurierte Level:",
"min_xp": "Mindest-XP",
"name": "Name",
"permission_int": "Berechtigungen",
"title": "Level:"
},
"new_level_message": "{} ist nun Level {}",
"remove": {
"error": {
"not_found": "Level {} nicht gefunden!"
},
"success": "Level {} wurde entfernt :D"
},
"seeding_failed": "Levelsystem konnte nicht neu geladen werden :(",
"seeding_finished": "Levelsystem wurde erfolgreich neu geladen :)",
"seeding_started": "Levelsystem wird neu geladen...",
"set": {
"already_level": "{} hat bereits das Level {} :/",
"failed": "Das Level von {} konnte nicht auf {} gesetzt werden :(",
"not_found": "Das Level {} konnte nicht gefunden werden :(",
"success": "{} ist nun Level {} :)"
}, },
"up": { "up": {
"already_last": "{} hat bereits das höchste Level.", "already_last": "{} hat bereits das höchste Level.",
"success": "{} wurde auf Level {} hochgesetzt :)", "failed": "{} konnte nicht hochgesetzt werden :(",
"failed": "{} konnte nicht hochgesetzt werden :(" "success": "{} wurde auf Level {} hochgesetzt :)"
},
"set": {
"already_level": "{} hat bereits das Level {} :/",
"success": "{} ist nun Level {} :)",
"failed": "Das Level von {} konnte nicht auf {} gesetzt werden :(",
"not_found": "Das Level {} konnte nicht gefunden werden :("
} }
}, },
"database": {}, "moderator": {
"permission": {}, "purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss."
},
"technician": { "technician": {
"restart_message": "Bin gleich wieder da :D",
"shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, Euer Freund. Lebt lange und in Frieden :)",
"log_message": "Hier sind deine Logdateien! :)",
"api_key": { "api_key": {
"get": "API-Schlüssel für {}: {}",
"add": { "add": {
"success": "API-Schlüssel für {} wurde erstellt: {}" "success": "API-Schlüssel für {} wurde erstellt: {}"
}, },
"get": "API-Schlüssel für {}: {}",
"remove": { "remove": {
"not_found": "API-Schlüssel konnte nicht gefunden werden!", "not_found": "API-Schlüssel konnte nicht gefunden werden!",
"success": "API-Schlüssel wurde entfernt :D" "success": "API-Schlüssel wurde entfernt :D"
} }
}
}
},
"api": {
"mail": {
"automatic_mail": "\n\nDies ist eine automatische E-Mail.\nGesendet von {}-{}@{}"
},
"api": {
"test_mail": {
"subject": "Krümmelmonster Web Interface Test-Mail",
"message": "Dies ist eine Test-Mail vom Krümmelmonster Web Interface\nGesendet von {}-{}"
}
},
"auth": {
"confirmation": {
"subject": "E-Mail für {} {} bestätigen",
"message": "Öffne den Link um die E-Mail zu bestätigen:\n{}auth/register/{}"
}, },
"forgot_password": { "log_message": "Hier sind deine Logdateien! :)",
"subject": "Passwort für {} {} zurücksetzen", "restart_message": "Bin gleich wieder da :D",
"message": "Öffne den Link um das Passwort zu ändern:\n{}auth/forgot-password/{}" "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 :)"
}
} }
} }
} }

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

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

View File

@@ -1,8 +1,9 @@
import socket
import sys import sys
import textwrap import textwrap
import uuid import uuid
from functools import partial from functools import partial
from typing import Union from typing import Union, Optional
import eventlet import eventlet
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
@@ -53,10 +54,15 @@ class Api(Flask):
self.register_error_handler(exc_class, self.handle_exception) self.register_error_handler(exc_class, self.handle_exception)
# websockets # websockets
self._socketio = SocketIO(self, cors_allowed_origins="*", path="/api/socket.io") # Added async_mode see link below
# https://github.com/miguelgrinberg/Flask-SocketIO/discussions/1849
# https://stackoverflow.com/questions/39370848/flask-socket-io-sometimes-client-calls-freeze-the-server
self._socketio = SocketIO(self, cors_allowed_origins="*", path="/api/socket.io", async_mode="eventlet")
self._socketio.on_event("connect", self.on_connect) self._socketio.on_event("connect", self.on_connect)
self._socketio.on_event("disconnect", self.on_disconnect) self._socketio.on_event("disconnect", self.on_disconnect)
self._socket: Optional[socket] = None
self._requests = {} self._requests = {}
@staticmethod @staticmethod
@@ -149,7 +155,14 @@ class Api(Flask):
# 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(eventlet.listen((self._api_settings.host, self._api_settings.port)), self, log_output=False) self._socket = eventlet.listen((self._api_settings.host, self._api_settings.port))
wsgi.server(self._socket, self, log_output=False)
def stop(self):
if self._socket is None:
return
self._socket.shutdown(socket.SHUT_RDWR)
self._socket.close()
def on_connect(self): def on_connect(self):
self._logger.info(__name__, f"Client connected") self._logger.info(__name__, f"Client connected")

View File

@@ -17,3 +17,10 @@ class ApiThread(threading.Thread):
self._api.start() self._api.start()
except Exception as e: except Exception as e:
self._logger.error(__name__, "Start failed", e) self._logger.error(__name__, "Start failed", e)
def stop(self):
try:
self._logger.trace(__name__, f"Try to stop {type(self._api).__name__}")
self._api.stop()
except Exception as e:
self._logger.error(__name__, "Stop failed", e)

View File

@@ -3,8 +3,8 @@
"Name": "bot-api", "Name": "bot-api",
"Version": { "Version": {
"Major": "1", "Major": "1",
"Minor": "0", "Minor": "1",
"Micro": "dev130" "Micro": "0"
}, },
"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__ = "1.0.dev130" __version__ = "1.1.0"
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="1", minor="0", micro="dev130") version_info = VersionInfo(major="1", minor="1", micro="0")

View File

@@ -1,16 +1,13 @@
import traceback
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console import Console
class ApiSettings(ConfigurationModelABC): class ApiSettings(ConfigurationModelABC):
def __init__(self): def __init__(self, port: int = None, host: str = None, redirect_uri: bool = None):
ConfigurationModelABC.__init__(self) ConfigurationModelABC.__init__(self)
self._port = 80 self._port = 80 if port is None else port
self._host = "" self._host = "" if host is None else host
self._redirect_to_https = False self._redirect_to_https = False if redirect_uri is None else redirect_uri
@property @property
def port(self) -> int: def port(self) -> int:
@@ -23,12 +20,3 @@ class ApiSettings(ConfigurationModelABC):
@property @property
def redirect_to_https(self) -> bool: def redirect_to_https(self) -> bool:
return self._redirect_to_https return self._redirect_to_https
def from_dict(self, settings: dict):
try:
self._port = int(settings["Port"])
self._host = settings["Host"]
self._redirect_to_https = bool(settings["RedirectToHTTPS"])
except Exception as e:
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

View File

@@ -1,19 +1,22 @@
import traceback
from datetime import datetime
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console import Console
class AuthenticationSettings(ConfigurationModelABC): class AuthenticationSettings(ConfigurationModelABC):
def __init__(self): def __init__(
self,
secret_key: str = None,
issuer: str = None,
audience: str = None,
token_expire_time: int = None,
refresh_token_expire_time: int = None,
):
ConfigurationModelABC.__init__(self) ConfigurationModelABC.__init__(self)
self._secret_key = "" self._secret_key = "" if secret_key is None else secret_key
self._issuer = "" self._issuer = "" if issuer is None else issuer
self._audience = "" self._audience = "" if audience is None else audience
self._token_expire_time = 0 self._token_expire_time = 0 if token_expire_time is None else token_expire_time
self._refresh_token_expire_time = 0 self._refresh_token_expire_time = 0 if refresh_token_expire_time is None else refresh_token_expire_time
@property @property
def secret_key(self) -> str: def secret_key(self) -> str:
@@ -34,14 +37,3 @@ class AuthenticationSettings(ConfigurationModelABC):
@property @property
def refresh_token_expire_time(self) -> int: def refresh_token_expire_time(self) -> int:
return self._refresh_token_expire_time return self._refresh_token_expire_time
def from_dict(self, settings: dict):
try:
self._secret_key = settings["SecretKey"]
self._issuer = settings["Issuer"]
self._audience = settings["Audience"]
self._token_expire_time = int(settings["TokenExpireTime"])
self._refresh_token_expire_time = int(settings["RefreshTokenExpireTime"])
except Exception as e:
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

View File

@@ -1,19 +1,23 @@
import traceback
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console import Console
from cpl_query.extension import List from cpl_query.extension import List
class DiscordAuthenticationSettings(ConfigurationModelABC): class DiscordAuthenticationSettings(ConfigurationModelABC):
def __init__(self): def __init__(
self,
client_secret: str = None,
redirect_uri: str = None,
scope: list = None,
token_url: str = None,
auth_url: str = None,
):
ConfigurationModelABC.__init__(self) ConfigurationModelABC.__init__(self)
self._client_secret = "" self._client_secret = "" if client_secret is None else client_secret
self._redirect_url = "" self._redirect_url = "" if redirect_uri is None else redirect_uri
self._scope = List() self._scope = List() if scope is None else List(str, scope)
self._token_url = "" self._token_url = "" if token_url is None else token_url
self._auth_url = "" self._auth_url = "" if auth_url is None else auth_url
@property @property
def client_secret(self) -> str: def client_secret(self) -> str:
@@ -34,14 +38,3 @@ class DiscordAuthenticationSettings(ConfigurationModelABC):
@property @property
def auth_url(self) -> str: def auth_url(self) -> str:
return self._auth_url return self._auth_url
def from_dict(self, settings: dict):
try:
self._client_secret = settings["ClientSecret"]
self._redirect_url = settings["RedirectURL"]
self._scope = List(str, settings["Scope"])
self._token_url = settings["TokenURL"]
self._auth_url = settings["AuthURL"]
except Exception as e:
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

View File

@@ -1,22 +1,12 @@
import traceback
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console import Console
class FrontendSettings(ConfigurationModelABC): class FrontendSettings(ConfigurationModelABC):
def __init__(self): def __init__(self, url: str = None):
ConfigurationModelABC.__init__(self) ConfigurationModelABC.__init__(self)
self._url = "" self._url = "" if url is None else url
@property @property
def url(self) -> str: def url(self) -> str:
return self._url return self._url
def from_dict(self, settings: dict):
try:
self._url = settings["URL"]
except Exception as e:
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

View File

@@ -1,49 +0,0 @@
from typing import Optional
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum
class VersionSettings(ConfigurationModelABC):
def __init__(self, major: str = None, minor: str = None, micro: str = None):
ConfigurationModelABC.__init__(self)
self._major: Optional[str] = major
self._minor: Optional[str] = minor
self._micro: Optional[str] = micro
@property
def major(self) -> str:
return self._major
@property
def minor(self) -> str:
return self._minor
@property
def micro(self) -> str:
return self._micro
def to_str(self) -> str:
if self._micro is None:
return f"{self._major}.{self._minor}"
else:
return f"{self._major}.{self._minor}.{self._micro}"
def from_dict(self, settings: dict):
self._major = settings[VersionSettingsNameEnum.major.value]
self._minor = settings[VersionSettingsNameEnum.minor.value]
micro = settings[VersionSettingsNameEnum.micro.value]
if micro != "":
self._micro = micro
def to_dict(self) -> dict:
version = {
VersionSettingsNameEnum.major.value: self._major,
VersionSettingsNameEnum.minor.value: self._minor,
}
if self._micro is not None:
version[VersionSettingsNameEnum.micro.value] = self._micro
return version

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

View File

@@ -71,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(dto) 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>")
@@ -129,7 +129,6 @@ class AuthController:
return "", 200 return "", 200
@Route.post(f"{BasePath}/refresh") @Route.post(f"{BasePath}/refresh")
@Route.authorize
async def refresh(self) -> Response: async def refresh(self) -> Response:
dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True)) dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True))
result = await self._auth_service.refresh_async(dto) result = await self._auth_service.refresh_async(dto)

View File

@@ -1,5 +1,5 @@
from ariadne import graphql_sync from ariadne import graphql_sync
from ariadne.constants import PLAYGROUND_HTML from ariadne.explorer import ExplorerPlayground
from cpl_core.configuration import ConfigurationABC from cpl_core.configuration import ConfigurationABC
from cpl_core.environment import ApplicationEnvironmentABC from cpl_core.environment import ApplicationEnvironmentABC
from flask import request, jsonify from flask import request, jsonify
@@ -30,7 +30,7 @@ class GraphQLController:
if self._env.environment_name != "development": if self._env.environment_name != "development":
return "", 403 return "", 403
return PLAYGROUND_HTML, 200 return ExplorerPlayground().html(None), 200
@Route.post(f"{BasePath}") @Route.post(f"{BasePath}")
@Route.authorize(by_api_key=True) @Route.authorize(by_api_key=True)

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

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

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

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

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

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

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

View File

@@ -10,7 +10,6 @@ class UserDTO(DtoABC):
id: int = None, id: int = None,
dc_id: int = None, dc_id: int = None,
xp: int = None, xp: int = None,
minecraft_id: Optional[str] = None,
server: Optional[Server] = None, server: Optional[Server] = None,
is_technician: Optional[bool] = None, is_technician: Optional[bool] = None,
is_admin: Optional[bool] = None, is_admin: Optional[bool] = None,
@@ -21,7 +20,6 @@ class UserDTO(DtoABC):
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
self._is_technician = is_technician self._is_technician = is_technician
@@ -44,14 +42,6 @@ class UserDTO(DtoABC):
def xp(self, value: int): def xp(self, value: int):
self._xp = value 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 @property
def server(self) -> Optional[Server]: def server(self) -> Optional[Server]:
return self._server return self._server
@@ -72,7 +62,6 @@ class UserDTO(DtoABC):
self._user_id = values["id"] self._user_id = values["id"]
self._discord_id = values["dcId"] self._discord_id = values["dcId"]
self._xp = values["xp"] self._xp = values["xp"]
self._minecraft_id = values["minecraftId"]
self._server = values["server"] self._server = values["server"]
def to_dict(self) -> dict: def to_dict(self) -> dict:
@@ -80,7 +69,6 @@ class UserDTO(DtoABC):
"id": self._user_id, "id": self._user_id,
"dcId": self._discord_id, "dcId": self._discord_id,
"xp": self._xp, "xp": self._xp,
"minecraftId": self._minecraft_id,
"server": self._server.id, "server": self._server.id,
"isTechnician": self.is_technician, "isTechnician": self.is_technician,
"isAdmin": self.is_admin, "isAdmin": self.is_admin,

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

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

View File

@@ -80,6 +80,9 @@ class AuthService(AuthServiceABC):
@staticmethod @staticmethod
def _is_email_valid(email: str) -> bool: def _is_email_valid(email: str) -> bool:
if email is None:
raise False
if re.fullmatch(_email_regex, email) is not None: if re.fullmatch(_email_regex, email) is not None:
return True return True
@@ -480,18 +483,19 @@ class AuthService(AuthServiceABC):
if user_dto is None: if user_dto is None:
raise ServiceException(ServiceErrorCode.InvalidData, "User not set") raise ServiceException(ServiceErrorCode.InvalidData, "User not set")
members = self._users.get_users_by_discord_id(dc_id)
if members.count() == 0:
raise ServiceException(ServiceErrorCode.InvalidUser, f"Member not found")
added_user = False 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:
self.add_auth_user(user_dto) self.add_auth_user(user_dto)
added_user = True added_user = True
# 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: if db_user.users.count() == 0:
self._users.get_users_by_discord_id(dc_id).for_each( members.for_each(lambda x: self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_user, x)))
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: if db_user.confirmation_id is not None and not added_user:
raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified") raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified")

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

View File

@@ -69,7 +69,6 @@ class AuthUserTransformer(TransformerABC):
u.id, u.id,
u.discord_id, u.discord_id,
u.xp, u.xp,
u.minecraft_id,
u.server, u.server,
cls._is_technician(u), cls._is_technician(u),
cls._is_admin(u), cls._is_admin(u),

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

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

View File

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

View File

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

View File

@@ -3,8 +3,8 @@
"Name": "bot-core", "Name": "bot-core",
"Version": { "Version": {
"Major": "1", "Major": "1",
"Minor": "0", "Minor": "1",
"Micro": "dev130" "Micro": "0"
}, },
"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__ = "1.0.dev130" __version__ = "1.1.0"
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="1", minor="0", micro="dev130") version_info = VersionInfo(major="1", minor="1", micro="0")

View File

@@ -1,32 +1,25 @@
import traceback
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console import Console, ForegroundColorEnum from cpl_core.utils.json_processor import JSONProcessor
from cpl_query.extension import List from cpl_query.extension import List
from bot_core.configuration.file_logging_settings import FileLoggingSettings from bot_core.configuration.file_logging_settings import FileLoggingSettings
class BotLoggingSettings(ConfigurationModelABC): class BotLoggingSettings(ConfigurationModelABC):
def __init__(self): def __init__(self, **kwargs: dict):
ConfigurationModelABC.__init__(self) ConfigurationModelABC.__init__(self)
self._files: List[FileLoggingSettings] = List(FileLoggingSettings) self._files: List[FileLoggingSettings] = List(FileLoggingSettings)
if kwargs is not None:
self._files_from_dict(kwargs)
@property @property
def files(self) -> List[FileLoggingSettings]: def files(self) -> List[FileLoggingSettings]:
return self._files return self._files
def from_dict(self, settings: dict): def _files_from_dict(self, settings: dict):
try: files = List(FileLoggingSettings)
files = List(FileLoggingSettings) for s in settings:
for s in settings: settings[s]["Key"] = s
st = FileLoggingSettings() files.append(JSONProcessor.process(FileLoggingSettings, settings[s]))
settings[s]["Key"] = s self._files = files
st.from_dict(settings[s])
files.append(st)
self._files = files
except Exception as e:
Console.set_foreground_color(ForegroundColorEnum.red)
Console.write_line(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.write_line(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
Console.set_foreground_color(ForegroundColorEnum.default)

View File

@@ -1,62 +0,0 @@
import traceback
from cpl_core.configuration import ConfigurationModelABC
from cpl_core.console import Console
from cpl_query.extension import List
from bot_core.configuration.server_settings import ServerSettings
class BotSettings(ConfigurationModelABC):
def __init__(self):
ConfigurationModelABC.__init__(self)
self._servers: List[ServerSettings] = List(ServerSettings)
self._technicians: List[int] = List(int)
self._wait_for_restart = 2
self._wait_for_shutdown = 2
self._cache_max_messages = 1000
@property
def servers(self) -> List[ServerSettings]:
return self._servers
@property
def technicians(self) -> List[int]:
return self._technicians
@property
def wait_for_restart(self) -> int:
return self._wait_for_restart
@property
def wait_for_shutdown(self) -> int:
return self._wait_for_shutdown
@property
def cache_max_messages(self) -> int:
return self._cache_max_messages
def from_dict(self, settings: dict):
try:
self._technicians = settings["Technicians"]
self._wait_for_restart = settings["WaitForRestart"]
self._wait_for_shutdown = settings["WaitForShutdown"]
settings.pop("Technicians")
settings.pop("WaitForRestart")
settings.pop("WaitForShutdown")
if "CacheMaxMessages" in settings:
self._cache_max_messages = settings["CacheMaxMessages"]
settings.pop("CacheMaxMessages")
servers = List(ServerSettings)
for s in settings:
st = ServerSettings()
settings[s]["Id"] = s
st.from_dict(settings[s])
servers.append(st)
self._servers = servers
except Exception as e:
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

View File

@@ -3,18 +3,20 @@ from enum import Enum
class FeatureFlagsEnum(Enum): class FeatureFlagsEnum(Enum):
# modules # modules
achievements_module = "AchievementsModule"
api_module = "ApiModule" api_module = "ApiModule"
admin_module = "AdminModule"
auto_role_module = "AutoRoleModule" auto_role_module = "AutoRoleModule"
base_module = "BaseModule" base_module = "BaseModule"
boot_log_module = "BootLogModule" boot_log_module = "BootLogModule"
core_module = "CoreModule" core_module = "CoreModule"
core_extension_module = "CoreExtensionModule" core_extension_module = "CoreExtensionModule"
data_module = ("DataModule",) config_module = "ConfigModule"
database_module = ("DatabaseModule",) data_module = "DataModule"
database_module = "DatabaseModule"
level_module = "LevelModule" level_module = "LevelModule"
moderator_module = "ModeratorModule" moderator_module = "ModeratorModule"
permission_module = "PermissionModule" permission_module = "PermissionModule"
# features # features
api_only = "ApiOnly" api_only = "ApiOnly"
presence = "Presence" presence = "Presence"
version_in_presence = "VersionInPresence"

View File

@@ -1,33 +1,48 @@
import traceback
from typing import Optional, Callable
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console import Console
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
class FeatureFlagsSettings(ConfigurationModelABC): class FeatureFlagsSettings(ConfigurationModelABC):
def __init__(self): _flags = {
# modules
FeatureFlagsEnum.achievements_module.value: False, # 14.06.2023 #268
FeatureFlagsEnum.api_module.value: False, # 13.10.2022 #70
FeatureFlagsEnum.auto_role_module.value: False, # 03.10.2022 #54
FeatureFlagsEnum.base_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.boot_log_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.core_module.value: True, # 03.10.2022 #56
FeatureFlagsEnum.core_extension_module.value: True, # 03.10.2022 #56
FeatureFlagsEnum.data_module.value: True, # 03.10.2022 #56
FeatureFlagsEnum.database_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48
FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.config_module.value: True, # 19.07.2023 #127
# features
FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70
FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56
FeatureFlagsEnum.version_in_presence.value: False, # 21.03.2023 #253
}
def __init__(self, **kwargs: dict):
ConfigurationModelABC.__init__(self) ConfigurationModelABC.__init__(self)
self._flags = { if len(kwargs.keys()) == 0:
# modules return
FeatureFlagsEnum.api_module.value: False, # 13.10.2022 #70
FeatureFlagsEnum.admin_module.value: False, # 02.10.2022 #48 for flag in [f.value for f in FeatureFlagsEnum]:
FeatureFlagsEnum.auto_role_module.value: True, # 03.10.2022 #54 self._load_flag(kwargs, FeatureFlagsEnum(flag))
FeatureFlagsEnum.base_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.boot_log_module.value: True, # 02.10.2022 #48 @classmethod
FeatureFlagsEnum.core_module.value: True, # 03.10.2022 #56 def get_flag_from_dict(cls, flags: dict, key: FeatureFlagsEnum) -> bool:
FeatureFlagsEnum.core_extension_module.value: True, # 03.10.2022 #56 def get_flag():
FeatureFlagsEnum.data_module.value: True, # 03.10.2022 #56 if key.value not in cls._flags:
FeatureFlagsEnum.database_module.value: True, # 02.10.2022 #48 return False
FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48 return cls._flags[key.value]
FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48
# features if key.value not in flags:
FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70 return get_flag()
FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56 return flags[key.value]
}
def get_flag(self, key: FeatureFlagsEnum) -> bool: def get_flag(self, key: FeatureFlagsEnum) -> bool:
if key.value not in self._flags: if key.value not in self._flags:
@@ -39,11 +54,3 @@ class FeatureFlagsSettings(ConfigurationModelABC):
return return
self._flags[key.value] = bool(settings[key.value]) self._flags[key.value] = bool(settings[key.value])
def from_dict(self, settings: dict):
try:
for flag in [f.value for f in FeatureFlagsEnum]:
self._load_flag(settings, FeatureFlagsEnum(flag))
except Exception as e:
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

View File

@@ -1,23 +1,19 @@
import traceback from cpl_core.logging import LoggingSettings, LoggingLevelEnum
from cpl_core.console import Console
from cpl_core.logging import LoggingSettings
class FileLoggingSettings(LoggingSettings): class FileLoggingSettings(LoggingSettings):
def __init__(self): def __init__(
LoggingSettings.__init__(self) self,
key: str,
path: str = None,
filename: str = None,
console_log_level: LoggingLevelEnum = None,
file_log_level: LoggingLevelEnum = None,
):
LoggingSettings.__init__(self, path, filename, console_log_level, file_log_level)
self._key = "" self._key = key
@property @property
def key(self) -> str: def key(self) -> str:
return self._key return self._key
def from_dict(self, settings: dict):
try:
self._key = settings["Key"]
super().from_dict(settings)
except Exception as e:
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

View File

@@ -1,28 +0,0 @@
import traceback
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
from cpl_core.console import Console
class ServerSettings(ConfigurationModelABC):
def __init__(self):
ConfigurationModelABC.__init__(self)
self._id: int = 0
self._message_delete_timer: int = 0
@property
def id(self) -> int:
return self._id
@property
def message_delete_timer(self) -> int:
return self._message_delete_timer
def from_dict(self, settings: dict):
try:
self._id = int(settings["Id"])
self._message_delete_timer = int(settings["MessageDeleteTimer"])
except Exception as e:
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in settings")
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")

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

View File

@@ -11,6 +11,8 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
from bot_core.events.core_on_ready_event import CoreOnReadyEvent from bot_core.events.core_on_ready_event import CoreOnReadyEvent
from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe
from bot_core.service.client_utils_service import ClientUtilsService from bot_core.service.client_utils_service import ClientUtilsService
from bot_core.service.config_service import ConfigService
from bot_core.service.data_integrity_service import DataIntegrityService
from bot_core.service.message_service import MessageService from bot_core.service.message_service import MessageService
@@ -22,8 +24,10 @@ class CoreModule(ModuleABC):
pass pass
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
services.add_transient(ConfigService)
services.add_transient(MessageServiceABC, MessageService) services.add_transient(MessageServiceABC, MessageService)
services.add_transient(ClientUtilsABC, ClientUtilsService) services.add_transient(ClientUtilsABC, ClientUtilsService)
services.add_transient(DataIntegrityService)
# pipes # pipes
services.add_transient(DateTimeOffsetPipe) services.add_transient(DateTimeOffsetPipe)

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

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

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

View File

@@ -1,13 +1,9 @@
from typing import Optional from typing import Optional
from cpl_translation import TranslatePipe
from discord.ext import commands from discord.ext import commands
from discord.ext.commands import Context
from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.client_utils_abc import ClientUtilsABC
from bot_core.abc.message_service_abc import MessageServiceABC
from bot_core.exception.check_error import CheckError from bot_core.exception.check_error import CheckError
from modules.permission.abc.permission_service_abc import PermissionServiceABC
class EventChecks: class EventChecks:
@@ -23,7 +19,7 @@ class EventChecks:
@classmethod @classmethod
def check_is_ready(cls): def check_is_ready(cls):
async def check_if_bot_is_ready() -> bool: async def check_if_bot_is_ready() -> bool:
result = await cls._client_utils.check_if_bot_is_ready() result = await cls._client_utils.check_if_bot_is_ready_yet()
if not result: if not result:
raise CheckError(f"Bot is not ready") raise CheckError(f"Bot is not ready")
return result return result

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

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

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

View File

@@ -9,6 +9,7 @@ from cpl_core.time import TimeFormatSettings
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 cpl_translation import TranslatePipe from cpl_translation import TranslatePipe
from discord import Guild
from discord.ext.commands import Context from discord.ext.commands import Context
from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.client_utils_abc import ClientUtilsABC
@@ -23,9 +24,10 @@ from bot_data.abc.user_joined_voice_channel_repository_abc import (
from bot_data.abc.user_message_count_per_hour_repository_abc import ( from bot_data.abc.user_message_count_per_hour_repository_abc import (
UserMessageCountPerHourRepositoryABC, UserMessageCountPerHourRepositoryABC,
) )
from bot_data.model.auto_role_rule import AutoRoleRule
from bot_data.model.server_config import ServerConfig
from bot_data.model.user import User from bot_data.model.user import User
from bot_data.model.user_message_count_per_hour import UserMessageCountPerHour from bot_data.model.user_message_count_per_hour import UserMessageCountPerHour
from modules.base.configuration.base_server_settings import BaseServerSettings
class ClientUtilsService(ClientUtilsABC): class ClientUtilsService(ClientUtilsABC):
@@ -111,7 +113,11 @@ class ClientUtilsService(ClientUtilsABC):
import bot import bot
name = self._t.transform(t_key).format(bot.__version__) if self._feature_flags.get_flag(FeatureFlagsEnum.version_in_presence):
name = f"{bot.__version__} {self._t.transform(t_key)}"
else:
name = self._t.transform(t_key)
await self._bot.change_presence(activity=discord.Game(name=name)) await self._bot.change_presence(activity=discord.Game(name=name))
self._logger.info(__name__, f"Set presence {name}") self._logger.info(__name__, f"Set presence {name}")
@@ -133,7 +139,7 @@ class ClientUtilsService(ClientUtilsABC):
self, self,
created_at: datetime, created_at: datetime,
user: User, user: User,
settings: BaseServerSettings, settings: ServerConfig,
is_reaction: bool = False, is_reaction: bool = False,
) -> bool: ) -> bool:
umcph = None umcph = None
@@ -188,3 +194,27 @@ class ClientUtilsService(ClientUtilsABC):
.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,
) )
async def react_to_message_by_auto_role_rule(
self, discord_channel_id: int, discord_message_id: int, rule: AutoRoleRule, guild: discord.Guild
):
try:
guild: Guild = self._bot.guilds.where(lambda g: g == guild).single()
channel = guild.get_channel(discord_channel_id)
message = await channel.fetch_message(discord_message_id)
emoji = List(discord.Emoji, guild.emojis).where(lambda x: x.name == rule.emoji_name).single()
if emoji is None:
self._logger.debug(__name__, f"Emoji {rule.emoji_name} not found")
return
await message.add_reaction(emoji)
self._logger.debug(
__name__,
f"Added reaction {rule.emoji_name} to message: {discord_message_id}",
)
except Exception as e:
self._logger.error(
__name__,
f"Cannot add reaction {rule.emoji_name} to message: {discord_message_id}",
e,
)

View File

@@ -0,0 +1,50 @@
from cpl_core.configuration import ConfigurationABC
from cpl_core.dependency_injection import ServiceProviderABC
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC
from bot_data.abc.technician_config_repository_abc import TechnicianConfigRepositoryABC
from bot_data.model.server import Server
from bot_data.model.technician_config import TechnicianConfig
from bot_data.service.server_config_seeder import ServerConfigSeeder
from bot_data.service.technician_config_seeder import TechnicianConfigSeeder
from modules.permission.abc.permission_service_abc import PermissionServiceABC
class ConfigService:
def __init__(
self,
config: ConfigurationABC,
services: ServiceProviderABC,
technician_config_repo: TechnicianConfigRepositoryABC,
server_config_repo: ServerConfigRepositoryABC,
tech_seeder: TechnicianConfigSeeder,
server_seeder: ServerConfigSeeder,
):
self._config = config
self._services = services
self._technician_config_repo = technician_config_repo
self._server_config_repo = server_config_repo
self._tech_seeder = tech_seeder
self._server_seeder = server_seeder
async def reload_technician_config(self):
if not self._technician_config_repo.does_technician_config_exists():
await self._tech_seeder.seed()
technician_config = self._technician_config_repo.get_technician_config()
self._config.add_configuration(TechnicianConfig, technician_config)
self._config.add_configuration(FeatureFlagsSettings, FeatureFlagsSettings(**technician_config.feature_flags))
async def reload_server_config(self, server: Server):
if not self._server_config_repo.does_server_config_exists(server.id):
await self._server_seeder.seed()
server_config = self._server_config_repo.get_server_config_by_server(server.id)
self._config.add_configuration(
f"{type(server_config).__name__}_{server_config.server.discord_id}", server_config
)
permissions: PermissionServiceABC = self._services.get_service(PermissionServiceABC)
permissions.on_ready()

View File

@@ -0,0 +1,396 @@
from datetime import datetime, timedelta
from typing import Union
import discord
from cpl_core.configuration import ConfigurationABC
from cpl_core.database.context import DatabaseContextABC
from cpl_discord.service import DiscordBotServiceABC
from bot_core.logging.database_logger import DatabaseLogger
from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe
from bot_data.abc.client_repository_abc import ClientRepositoryABC
from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC
from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
from bot_data.abc.user_joined_voice_channel_repository_abc import (
UserJoinedVoiceChannelRepositoryABC,
)
from bot_data.abc.user_repository_abc import UserRepositoryABC
from bot_data.model.client import Client
from bot_data.model.known_user import KnownUser
from bot_data.model.server import Server
from bot_data.model.server_config import ServerConfig
from bot_data.model.user import User
from bot_data.model.user_joined_server import UserJoinedServer
from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
from bot_data.service.seeder_service import SeederService
from bot_data.service.user_repository_service import ServerRepositoryABC
from modules.achievements.achievement_service import AchievementService
class DataIntegrityService:
def __init__(
self,
config: ConfigurationABC,
logger: DatabaseLogger,
seeder: SeederService,
bot: DiscordBotServiceABC,
db_context: DatabaseContextABC,
server_repo: ServerRepositoryABC,
user_repo: UserRepositoryABC,
client_repo: ClientRepositoryABC,
known_users: KnownUserRepositoryABC,
user_joins: UserJoinedServerRepositoryABC,
user_joins_vc: UserJoinedVoiceChannelRepositoryABC,
user_joined_gs: UserJoinedGameServerRepositoryABC,
achievement_service: AchievementService,
dtp: DateTimeOffsetPipe,
):
self._config = config
self._logger = logger
self._seeder = seeder
self._bot = bot
self._db_context = db_context
self._servers = server_repo
self._users = user_repo
self._clients = client_repo
self._known_users = known_users
self._user_joins = user_joins
self._user_joins_vc = user_joins_vc
self._user_joined_gs = user_joined_gs
self._achievements = achievement_service
self._dtp = dtp
self._is_for_shutdown = False
def _check_known_users(self):
self._logger.debug(__name__, f"Start checking KnownUsers table, {len(self._bot.users)}")
for u in self._bot.users:
u: discord.User = u
try:
if u.bot:
self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot")
continue
user = self._known_users.find_user_by_discord_id(u.id)
if user is not None:
continue
self._logger.warn(__name__, f"Unknown user: {u.id}")
self._logger.debug(__name__, f"Add user: {u.id}")
self._known_users.add_user(KnownUser(u.id))
self._db_context.save_changes()
user = self._known_users.find_user_by_discord_id(u.id)
if user is None:
self._logger.fatal(__name__, f"Cannot add user: {u.id}")
self._logger.debug(__name__, f"Added user: {u.id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get user", e)
def _check_servers(self):
self._logger.debug(__name__, f"Start checking Servers table")
for g in self._bot.guilds:
g: discord.Guild = g
try:
server = self._servers.find_server_by_discord_id(g.id)
if server is not None:
continue
self._logger.warn(__name__, f"Server not found in database: {g.id}")
self._logger.debug(__name__, f"Add server: {g.id}")
self._servers.add_server(Server(g.id))
self._db_context.save_changes()
server = self._servers.find_server_by_discord_id(g.id)
if server is None:
self._logger.fatal(__name__, f"Cannot add server: {g.id}")
self._logger.debug(__name__, f"Added server: {g.id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get server", e)
results = self._servers.get_servers()
if results is None or len(results) == 0:
self._logger.error(__name__, f"Table Servers is empty!")
def _check_clients(self):
self._logger.debug(__name__, f"Start checking Clients table")
for g in self._bot.guilds:
g: discord.Guild = g
try:
server: Server = self._servers.find_server_by_discord_id(g.id)
if server is None:
self._logger.fatal(__name__, f"Server not found in database: {g.id}")
client = self._clients.find_client_by_server_id(server.id)
if client is not None:
continue
self._logger.warn(
__name__,
f"Client for server {g.id} not found in database: {self._bot.user.id}",
)
self._logger.debug(__name__, f"Add client: {self._bot.user.id}")
self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server))
self._db_context.save_changes()
client = self._clients.find_client_by_server_id(server.id)
if client is None:
self._logger.fatal(
__name__,
f"Cannot add client {self._bot.user.id} for server {g.id}",
)
self._logger.debug(__name__, f"Added client: {g.id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get client", e)
results = self._servers.get_servers()
if results is None or len(results) == 0:
self._logger.error(__name__, f"Table Servers is empty!")
def _check_users(self):
self._logger.debug(__name__, f"Start checking Users table")
for g in self._bot.guilds:
g: discord.Guild = g
try:
server = self._servers.find_server_by_discord_id(g.id)
if server is None:
self._logger.fatal(__name__, f"Server not found in database: {g.id}")
for u in g.members:
u: Union[discord.Member, discord.User] = u
if u.bot:
self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot")
continue
user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id)
if user is not None:
continue
self._logger.warn(__name__, f"User not found in database: {u.id}")
self._logger.debug(__name__, f"Add user: {u.id}")
self._users.add_user(User(u.id, 0, 0, 0, server))
self._db_context.save_changes()
self._logger.debug(__name__, f"Added User: {u.id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get User", e)
results = self._users.get_users()
if results is None or len(results) == 0:
self._logger.error(__name__, f"Table Users is empty!")
def _check_user_joins(self):
self._logger.debug(__name__, f"Start checking UserJoinedServers table")
for guild in self._bot.guilds:
guild: discord.Guild = guild
server = self._servers.find_server_by_discord_id(guild.id)
if server is None:
self._logger.fatal(__name__, f"Server not found in database: {guild.id}")
try:
for u in guild.members:
u: discord.User = u
if u.bot:
self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot")
continue
user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id)
if user is None:
self._logger.fatal(__name__, f"User not found in database: {u.id}")
join = self._user_joins.find_active_user_joined_server_by_user_id(user.id)
if join is not None:
continue
m: discord.Member = u
self._logger.warn(
__name__,
f"Active UserJoinedServer not found in database: {guild.id}:{u.id}@{m.joined_at}",
)
self._logger.debug(
__name__,
f"Add UserJoinedServer: {guild.id}:{u.id}@{m.joined_at}",
)
self._user_joins.add_user_joined_server(
UserJoinedServer(user, self._dtp.transform(m.joined_at), None)
)
self._db_context.save_changes()
self._logger.debug(__name__, f"Added UserJoinedServer: {u.id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get UserJoinedServer", e)
results = self._users.get_users()
if results is None or len(results) == 0:
self._logger.error(__name__, f"Table Users is empty!")
joins = self._user_joins.get_user_joined_servers()
for join in joins:
join: UserJoinedServer = join
if join.user.server.discord_id != guild.id:
continue
if join.leaved_on is not None:
continue
dc_user = guild.get_member(join.user.discord_id)
if dc_user is None:
self._logger.warn(
__name__,
f"User {join.user.discord_id} already left the server.",
)
join.leaved_on = datetime.now()
self._user_joins.update_user_joined_server(join)
self._db_context.save_changes()
def _check_user_joins_vc(self):
self._logger.debug(__name__, f"Start checking UserJoinedVoiceChannel table")
for guild in self._bot.guilds:
guild: discord.Guild = guild
settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild.id}")
server = self._servers.find_server_by_discord_id(guild.id)
if server is None:
self._logger.fatal(__name__, f"Server not found in database: {guild.id}")
try:
# close open voice states
for member in guild.members:
if member.bot:
self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot")
continue
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)
if user is None:
self._logger.fatal(__name__, f"User not found in database: {member.id}")
joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.id)
if joins is None or len(joins) == 0:
continue
for join in joins:
self._logger.warn(
__name__,
f"Active UserJoinedVoiceChannel found in database: {guild.id}:{member.id}@{join.joined_on}",
)
join.leaved_on = datetime.now()
if (
(join.leaved_on - join.joined_on).total_seconds() / 60 / 60
) > settings.max_voice_state_hours:
join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours)
self._user_joins_vc.update_user_joined_voice_channel(join)
if self._is_for_shutdown:
user.xp += round(join.time * settings.xp_per_ontime_hour)
self._users.update_user(user)
self._db_context.save_changes()
if self._is_for_shutdown:
return
# add open voice states
for member in guild.members:
if member.bot:
self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot")
continue
if member.voice is None or member.voice.channel.id in settings.afk_channel_ids:
continue
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)
if user is None:
self._logger.fatal(__name__, f"User not found in database: {member.id}")
join = UserJoinedVoiceChannel(user, member.voice.channel.id, datetime.now())
self._user_joins_vc.add_user_joined_voice_channel(join)
self._db_context.save_changes()
except Exception as e:
self._logger.error(__name__, f"Cannot get UserJoinedVoiceChannel", e)
def _check_user_joined_gs(self):
self._logger.debug(__name__, f"Start checking UserJoinedGameServer table")
for guild in self._bot.guilds:
guild: discord.Guild = guild
server = self._servers.find_server_by_discord_id(guild.id)
if server is None:
self._logger.fatal(__name__, f"Server not found in database: {guild.id}")
try:
for member in guild.members:
if member.bot:
self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot")
continue
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)
if user is None:
self._logger.fatal(__name__, f"User not found in database: {member.id}")
joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.id)
if joins is None or len(joins) == 0:
continue
for join in joins:
self._logger.warn(
__name__,
f"Active UserJoinedGameServer found in database: {guild.id}:{member.id}@{join.joined_on}",
)
join.leaved_on = datetime.now()
settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild.id}")
if (
(join.leaved_on - join.joined_on).total_seconds() / 60 / 60
) > settings.max_voice_state_hours:
join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours)
self._user_joined_gs.update_user_joined_game_server(join)
if self._is_for_shutdown:
user.xp += round(join.time * settings.xp_per_ontime_hour)
self._users.update_user(user)
self._db_context.save_changes()
except Exception as e:
self._logger.error(__name__, f"Cannot get UserJoinedGameServer", e)
async def _check_for_user_achievements(self):
self._logger.debug(__name__, f"Start checking UserGotAchievement table")
for guild in self._bot.guilds:
server = self._servers.find_server_by_discord_id(guild.id)
if server is None:
self._logger.fatal(__name__, f"Server not found in database: {guild.id}")
for member in guild.members:
if member.bot:
self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot")
continue
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)
if user is None:
self._logger.fatal(__name__, f"User not found in database: {member.id}")
await self._achievements.validate_achievements_for_user(user)
async def check_data_integrity(self, is_for_shutdown=False):
if is_for_shutdown != self._is_for_shutdown:
self._is_for_shutdown = is_for_shutdown
self._check_known_users()
self._check_servers()
self._check_clients()
self._check_users()
self._check_user_joins()
self._check_user_joins_vc()
self._check_user_joined_gs()
await self._check_for_user_achievements()

View File

@@ -10,10 +10,10 @@ from discord import Interaction
from discord.ext.commands import Context from discord.ext.commands import Context
from bot_core.abc.message_service_abc import MessageServiceABC from bot_core.abc.message_service_abc import MessageServiceABC
from bot_core.configuration.server_settings import ServerSettings
from bot_core.helper.log_message_helper import LogMessageHelper from bot_core.helper.log_message_helper import LogMessageHelper
from bot_core.logging.message_logger import MessageLogger from bot_core.logging.message_logger import MessageLogger
from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC
from bot_data.model.server_config import ServerConfig
class MessageService(MessageServiceABC): class MessageService(MessageServiceABC):
@@ -33,7 +33,7 @@ class MessageService(MessageServiceABC):
async def delete_messages(self, messages: List[discord.Message], guild_id: int, without_tracking=False): async def delete_messages(self, messages: List[discord.Message], guild_id: int, without_tracking=False):
self._logger.debug(__name__, f"Try to delete {messages.count()} messages") self._logger.debug(__name__, f"Try to delete {messages.count()} messages")
server_st: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild_id}") server_st: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild_id}")
await asyncio.sleep(server_st.message_delete_timer) await asyncio.sleep(server_st.message_delete_timer)
for message in messages: for message in messages:
await self.delete_message(message, mass_delete=True, without_tracking=without_tracking) await self.delete_message(message, mass_delete=True, without_tracking=without_tracking)
@@ -50,7 +50,7 @@ class MessageService(MessageServiceABC):
else None else None
) )
server_st: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild_id}") server_st: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild_id}")
if not mass_delete: if not mass_delete:
await asyncio.sleep(server_st.message_delete_timer) await asyncio.sleep(server_st.message_delete_timer)
self._logger.debug( self._logger.debug(

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

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

View File

@@ -0,0 +1,52 @@
from abc import ABC, abstractmethod
from cpl_query.extension import List
from bot_data.model.achievement import Achievement
from bot_data.model.user_got_achievement import UserGotAchievement
class AchievementRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def get_achievements(self) -> List[Achievement]:
pass
@abstractmethod
def get_achievement_by_id(self, id: int) -> Achievement:
pass
@abstractmethod
def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]:
pass
@abstractmethod
def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]:
pass
@abstractmethod
def get_user_got_achievements_by_achievement_id(self, achievement_id: int) -> List[Achievement]:
pass
@abstractmethod
def add_achievement(self, achievement: Achievement):
pass
@abstractmethod
def update_achievement(self, achievement: Achievement):
pass
@abstractmethod
def delete_achievement(self, achievement: Achievement):
pass
@abstractmethod
def add_user_got_achievement(self, join: UserGotAchievement):
pass
@abstractmethod
def delete_user_got_achievement(self, join: UserGotAchievement):
pass

View File

@@ -18,6 +18,10 @@ class ApiKeyRepositoryABC(ABC):
def get_api_key(self, identifier: str, key: str) -> ApiKey: def get_api_key(self, identifier: str, key: str) -> ApiKey:
pass pass
@abstractmethod
def get_api_key_by_id(self, id: int) -> ApiKey:
pass
@abstractmethod @abstractmethod
def get_api_key_by_key(self, key: str) -> ApiKey: def get_api_key_by_key(self, key: str) -> ApiKey:
pass pass

View File

@@ -7,5 +7,5 @@ class DataSeederABC(ABC):
pass pass
@abstractmethod @abstractmethod
def seed(self): async def seed(self):
pass pass

View File

@@ -0,0 +1,39 @@
from abc import ABC, abstractmethod
from cpl_query.extension import List
from bot_data.model.game_server import GameServer
class GameServerRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def get_game_servers(self) -> List[GameServer]:
pass
@abstractmethod
def get_game_server_by_id(self, id: int) -> GameServer:
pass
@abstractmethod
def get_game_servers_by_server_id(self, id: int) -> List[GameServer]:
pass
@abstractmethod
def get_game_server_by_api_key_id(self, id: int) -> GameServer:
pass
@abstractmethod
def add_game_server(self, game_server: GameServer):
pass
@abstractmethod
def update_game_server(self, game_server: GameServer):
pass
@abstractmethod
def delete_game_server(self, game_server: GameServer):
pass

View File

@@ -0,0 +1,27 @@
from abc import ABC, abstractmethod
from datetime import datetime
class HistoryTableABC(ABC):
@abstractmethod
def __init__(self):
self._id = 0
self._deleted = False
self._date_from = datetime.now().isoformat()
self._date_to = datetime.now().isoformat()
@property
def id(self) -> int:
return self._id
@property
def deleted(self) -> bool:
return self._deleted
@property
def date_from(self) -> str:
return self._date_from
@property
def date_to(self) -> str:
return self._date_to

View File

@@ -3,6 +3,7 @@ from abc import ABC, abstractmethod
class MigrationABC(ABC): class MigrationABC(ABC):
name = None name = None
prio = 0
@abstractmethod @abstractmethod
def __init__(self): def __init__(self):

View File

@@ -0,0 +1,59 @@
from abc import ABC, abstractmethod
from bot_data.model.server_afk_channel_ids_config import ServerAFKChannelIdsConfig
from bot_data.model.server_config import ServerConfig
from bot_data.model.server_team_role_ids_config import ServerTeamRoleIdsConfig
class ServerConfigRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def does_server_config_exists(self, server_id: int) -> bool:
pass
@abstractmethod
def get_server_config_by_server(self, server_id: int) -> ServerConfig:
pass
@abstractmethod
def get_server_config_by_id(self, config_id: int) -> ServerConfig:
pass
@abstractmethod
def add_server_config(self, server_config: ServerConfig):
pass
@abstractmethod
def update_server_config(self, server_config: ServerConfig):
pass
@abstractmethod
def delete_server_config(self, server_config: ServerConfig):
pass
@abstractmethod
def add_server_team_role_id_config(self, server_team_role_id: ServerTeamRoleIdsConfig):
pass
@abstractmethod
def update_server_team_role_id_config(self, server_team_role_id: ServerTeamRoleIdsConfig):
pass
@abstractmethod
def delete_server_team_role_id_config(self, server_team_role_id: ServerTeamRoleIdsConfig):
pass
@abstractmethod
def add_server_afk_channel_config(self, server_afk_channel: ServerAFKChannelIdsConfig):
pass
@abstractmethod
def update_server_afk_channel_config(self, server_afk_channel: ServerAFKChannelIdsConfig):
pass
@abstractmethod
def delete_server_afk_channel_config(self, server_afk_channel: ServerAFKChannelIdsConfig):
pass

View File

@@ -0,0 +1,15 @@
from abc import abstractmethod
from cpl_core.database import TableABC
class TableWithIdABC(TableABC):
@abstractmethod
def __init__(self):
self.__init__()
self._id = 0
@property
def id(self) -> int:
return self._id

View File

@@ -0,0 +1,55 @@
from abc import ABC, abstractmethod
from bot_data.model.technician_config import TechnicianConfig
from bot_data.model.technician_id_config import TechnicianIdConfig
from bot_data.model.technician_ping_url_config import TechnicianPingUrlConfig
class TechnicianConfigRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def does_technician_config_exists(self) -> bool:
pass
@abstractmethod
def get_technician_config(self) -> TechnicianConfig:
pass
@abstractmethod
def add_technician_config(self, technician_config: TechnicianConfig):
pass
@abstractmethod
def update_technician_config(self, technician_config: TechnicianConfig):
pass
@abstractmethod
def delete_technician_config(self, technician_config: TechnicianConfig):
pass
@abstractmethod
def add_technician_id_config(self, technician_id: TechnicianIdConfig):
pass
@abstractmethod
def update_technician_id_config(self, technician_id: TechnicianIdConfig):
pass
@abstractmethod
def delete_technician_id_config(self, technician_id: TechnicianIdConfig):
pass
@abstractmethod
def add_technician_ping_url_config(self, technician_ping_url: TechnicianPingUrlConfig):
pass
@abstractmethod
def update_technician_ping_url_config(self, technician_ping_url: TechnicianPingUrlConfig):
pass
@abstractmethod
def delete_technician_ping_url_config(self, technician_ping_url: TechnicianPingUrlConfig):
pass

View File

@@ -0,0 +1,47 @@
from abc import ABC, abstractmethod
from cpl_query.extension import List
from bot_data.model.user_game_ident import UserGameIdent
class UserGameIdentRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def get_user_game_idents(self) -> List[UserGameIdent]:
pass
@abstractmethod
def get_user_game_ident_by_id(self, id: int) -> UserGameIdent:
pass
@abstractmethod
def get_user_game_ident_by_ident(self, ident: str) -> UserGameIdent:
pass
@abstractmethod
def find_user_game_ident_by_ident(self, ident: str) -> UserGameIdent:
pass
@abstractmethod
def get_user_game_idents_by_user_id(self, user_id: int) -> List[UserGameIdent]:
pass
@abstractmethod
def add_user_game_ident(self, user_game_ident: UserGameIdent):
pass
@abstractmethod
def update_user_game_ident(self, user_game_ident: UserGameIdent):
pass
@abstractmethod
def delete_user_game_ident(self, user_game_ident: UserGameIdent):
pass
@abstractmethod
def delete_user_game_ident_by_user_id(self, user_id: int):
pass

View File

@@ -0,0 +1,35 @@
from abc import ABC, abstractmethod
from cpl_query.extension import List
from bot_data.model.user_warnings import UserWarnings
class UserWarningsRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def get_user_warnings(self) -> List[UserWarnings]:
pass
@abstractmethod
def get_user_warnings_by_id(self, id: int) -> UserWarnings:
pass
@abstractmethod
def get_user_warnings_by_user_id(self, user_id: int) -> List[UserWarnings]:
pass
@abstractmethod
def add_user_warnings(self, user_warnings: UserWarnings):
pass
@abstractmethod
def update_user_warnings(self, user_warnings: UserWarnings):
pass
@abstractmethod
def delete_user_warnings(self, user_warnings: UserWarnings):
pass

View File

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

View File

@@ -5,13 +5,19 @@ 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.achievement_repository_abc import AchievementRepositoryABC
from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC 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.data_seeder_abc import DataSeederABC
from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC
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_config_repository_abc import ServerConfigRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.abc.technician_config_repository_abc import TechnicianConfigRepositoryABC
from bot_data.abc.user_game_ident_repository_abc import UserGameIdentRepositoryABC
from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC 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 (
@@ -21,14 +27,23 @@ 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.abc.user_warnings_repository_abc import UserWarningsRepositoryABC
from bot_data.service.achievements_repository_service import AchievementRepositoryService
from bot_data.service.api_key_repository_service import ApiKeyRepositoryService from bot_data.service.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.cache_service import CacheService
from bot_data.service.client_repository_service import ClientRepositoryService from bot_data.service.client_repository_service import ClientRepositoryService
from bot_data.service.game_server_repository_service import GameServerRepositoryService
from bot_data.service.known_user_repository_service import KnownUserRepositoryService from bot_data.service.known_user_repository_service import KnownUserRepositoryService
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_config_repository_service import ServerConfigRepositoryService
from bot_data.service.server_config_seeder import ServerConfigSeeder
from bot_data.service.server_repository_service import ServerRepositoryService from bot_data.service.server_repository_service import ServerRepositoryService
from bot_data.service.technician_config_repository_service import TechnicianConfigRepositoryService
from bot_data.service.technician_config_seeder import TechnicianConfigSeeder
from bot_data.service.user_game_ident_repository_service import UserGameIdentRepositoryService
from bot_data.service.user_joined_game_server_repository_service import UserJoinedGameServerRepositoryService 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,
@@ -40,6 +55,7 @@ from bot_data.service.user_message_count_per_hour_repository_service import (
UserMessageCountPerHourRepositoryService, UserMessageCountPerHourRepositoryService,
) )
from bot_data.service.user_repository_service import UserRepositoryService from bot_data.service.user_repository_service import UserRepositoryService
from bot_data.service.user_warnings_repository_service import UserWarningsRepositoryService
class DataModule(ModuleABC): class DataModule(ModuleABC):
@@ -50,6 +66,8 @@ class DataModule(ModuleABC):
pass pass
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
services.add_singleton(CacheService)
services.add_transient(ApiKeyRepositoryABC, ApiKeyRepositoryService) 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)
@@ -61,9 +79,17 @@ class DataModule(ModuleABC):
services.add_transient(UserJoinedGameServerRepositoryABC, UserJoinedGameServerRepositoryService) 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(UserWarningsRepositoryABC, UserWarningsRepositoryService)
services.add_transient( services.add_transient(
UserMessageCountPerHourRepositoryABC, UserMessageCountPerHourRepositoryABC,
UserMessageCountPerHourRepositoryService, UserMessageCountPerHourRepositoryService,
) )
services.add_transient(GameServerRepositoryABC, GameServerRepositoryService)
services.add_transient(UserGameIdentRepositoryABC, UserGameIdentRepositoryService)
services.add_transient(AchievementRepositoryABC, AchievementRepositoryService)
services.add_transient(TechnicianConfigRepositoryABC, TechnicianConfigRepositoryService)
services.add_transient(ServerConfigRepositoryABC, ServerConfigRepositoryService)
services.add_transient(SeederService) services.add_transient(SeederService)
services.add_transient(DataSeederABC, TechnicianConfigSeeder)
services.add_transient(DataSeederABC, ServerConfigSeeder)

View File

@@ -1,3 +1,5 @@
import time
from cpl_core.database import DatabaseSettings from cpl_core.database import DatabaseSettings
from cpl_core.database.context import DatabaseContext from cpl_core.database.context import DatabaseContext
@@ -9,6 +11,7 @@ class DBContext(DatabaseContext):
self._logger = logger self._logger = logger
DatabaseContext.__init__(self) DatabaseContext.__init__(self)
self._fails = 0
def connect(self, database_settings: DatabaseSettings): def connect(self, database_settings: DatabaseSettings):
try: try:
@@ -30,5 +33,14 @@ class DBContext(DatabaseContext):
try: try:
return super(DBContext, self).select(statement) return super(DBContext, self).select(statement)
except Exception as e: except Exception as e:
if self._fails >= 3:
self._logger.fatal(__name__, f"Database error caused by {statement}", e)
self._logger.error(__name__, f"Database error caused by {statement}", e) self._logger.error(__name__, f"Database error caused by {statement}", e)
self._fails += 1
try:
time.sleep(0.5)
return self.select(statement)
except Exception as e:
pass
return [] return []

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

View File

@@ -0,0 +1,127 @@
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.migration_abc import MigrationABC
from bot_data.db_context import DBContext
class AchievementsMigration(MigrationABC):
name = "1.1.0_AchievementsMigration"
def __init__(self, logger: DatabaseLogger, db: DBContext):
MigrationABC.__init__(self)
self._logger = logger
self._db = db
self._cursor = db.cursor
def upgrade(self):
self._logger.debug(__name__, "Running upgrade")
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `Achievements` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(255) NOT NULL,
`Description` VARCHAR(255) NOT NULL,
`Attribute` VARCHAR(255) NOT NULL,
`Operator` VARCHAR(255) NOT NULL,
`Value` VARCHAR(255) NOT NULL,
`ServerId` BIGINT,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY(`Id`),
FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`)
);
"""
)
)
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `AchievementsHistory`
(
`Id` BIGINT(20) NOT NULL,
`Name` VARCHAR(255) NOT NULL,
`Description` VARCHAR(255) NOT NULL,
`Attribute` VARCHAR(255) NOT NULL,
`Operator` VARCHAR(255) NOT NULL,
`Value` VARCHAR(255) NOT NULL,
`ServerId` BIGINT,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
"""
)
)
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `UserGotAchievements` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`UserId` BIGINT,
`AchievementId` BIGINT,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY(`Id`),
FOREIGN KEY (`UserId`) REFERENCES `Users`(`UserId`),
FOREIGN KEY (`AchievementId`) REFERENCES `Achievements`(`Id`)
);
"""
)
)
# A join table history between users and achievements is not necessary.
self._cursor.execute(str(f"""ALTER TABLE Users ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
self._cursor.execute(str(f"""ALTER TABLE Users ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
self._cursor.execute(str(f"""DROP TRIGGER IF EXISTS `TR_AchievementsUpdate`;"""))
self._cursor.execute(
str(
f"""
CREATE TRIGGER `TR_AchievementsUpdate`
AFTER UPDATE
ON `Achievements`
FOR EACH ROW
BEGIN
INSERT INTO `AchievementsHistory` (
`Id`, `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId`, `DateFrom`, `DateTo`
)
VALUES (
OLD.Id, OLD.Name, OLD.Description, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;
"""
)
)
self._cursor.execute(str(f"""DROP TRIGGER IF EXISTS `TR_AchievementsDelete`;"""))
self._cursor.execute(
str(
f"""
CREATE TRIGGER `TR_AchievementsDelete`
AFTER DELETE
ON `Achievements`
FOR EACH ROW
BEGIN
INSERT INTO `AchievementsHistory` (
`Id`, `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId`, `Deleted`, `DateFrom`, `DateTo`
)
VALUES (
OLD.Id, OLD.Name, OLD.Description, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;
"""
)
)
def downgrade(self):
self._cursor.execute("DROP TABLE `Achievements`;")
self._cursor.execute(str(f"""ALTER TABLE Users DROP COLUMN MessageCount;"""))
self._cursor.execute(str(f"""ALTER TABLE Users DROP COLUMN ReactionCount;"""))

View File

@@ -4,7 +4,7 @@ from bot_data.db_context import DBContext
class ApiKeyMigration(MigrationABC): class ApiKeyMigration(MigrationABC):
name = "1.0_ApiKeyMigration" name = "1.0.0_ApiKeyMigration"
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,29 @@
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.migration_abc import MigrationABC
from bot_data.db_context import DBContext
class ConfigFeatureFlagsMigration(MigrationABC):
name = "1.1.0_ConfigFeatureFlagsMigration"
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("""ALTER TABLE CFG_Technician ADD FeatureFlags JSON NULL DEFAULT ('{}') AFTER CacheMaxMessages;""")
)
self._cursor.execute(
str("""ALTER TABLE CFG_Server ADD FeatureFlags JSON NULL DEFAULT ('{}') AFTER LoginMessageChannelId;""")
)
def downgrade(self):
self._logger.debug(__name__, "Running downgrade")
self._cursor.execute("ALTER TABLE CFG_Technician DROP COLUMN FeatureFlags;")
self._cursor.execute("ALTER TABLE CFG_Server DROP COLUMN FeatureFlags;")

View File

@@ -0,0 +1,155 @@
import os
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.migration_abc import MigrationABC
from bot_data.db_context import DBContext
class ConfigMigration(MigrationABC):
name = "1.1.0_ConfigMigration"
def __init__(self, logger: DatabaseLogger, db: DBContext):
MigrationABC.__init__(self)
self._logger = logger
self._db = db
self._cursor = db.cursor
def _exec(self, file: str):
path = f"{os.path.dirname(os.path.realpath(__file__))}/db_history_scripts"
sql = open(f"{path}/{file}").read()
for statement in sql.split("\n\n"):
self._cursor.execute(statement + ";")
def upgrade(self):
self._logger.debug(__name__, "Running upgrade")
self._server_upgrade()
self._technician_upgrade()
self._exec("config/server.sql")
self._exec("config/server_afk_channels.sql")
self._exec("config/server_team_roles.sql")
self._exec("config/technician.sql")
self._exec("config/technician_ids.sql")
self._exec("config/technician_ping_urls.sql")
def _server_upgrade(self):
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `CFG_Server` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`MessageDeleteTimer` BIGINT NOT NULL DEFAULT 6,
`NotificationChatId` BIGINT NOT NULL,
`MaxVoiceStateHours` BIGINT NOT NULL DEFAULT 6,
`XpPerMessage` BIGINT NOT NULL DEFAULT 1,
`XpPerReaction` BIGINT NOT NULL DEFAULT 1,
`MaxMessageXpPerHour` BIGINT NOT NULL DEFAULT 20,
`XpPerOntimeHour` BIGINT NOT NULL DEFAULT 10,
`XpPerEventParticipation` BIGINT NOT NULL DEFAULT 10,
`XpPerAchievement` BIGINT NOT NULL DEFAULT 10,
`AFKCommandChannelId` BIGINT NOT NULL,
`HelpVoiceChannelId` BIGINT NOT NULL,
`TeamChannelId` BIGINT NOT NULL,
`LoginMessageChannelId` BIGINT NOT NULL,
`ServerId` BIGINT NOT NULL,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY(`Id`),
FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`)
);
"""
)
)
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `CFG_ServerAFKChannelIds` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`ChannelId` BIGINT NOT NULL,
`ServerId` BIGINT NOT NULL,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY(`Id`),
FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`)
);
"""
)
)
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `CFG_ServerTeamRoleIds` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`RoleId` BIGINT NOT NULL,
`TeamMemberType` ENUM('Moderator', 'Admin') NOT NULL,
`ServerId` BIGINT NOT NULL,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY(`Id`),
FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`)
);
"""
)
)
def _technician_upgrade(self):
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `CFG_Technician` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`HelpCommandReferenceUrl` VARCHAR(255) NOT NULL,
`WaitForRestart` BIGINT NOT NULL DEFAULT 8,
`WaitForShutdown` BIGINT NOT NULL DEFAULT 8,
`CacheMaxMessages` BIGINT NOT NULL DEFAULT 1000000,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY(`Id`)
);
"""
)
)
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `CFG_TechnicianPingUrls` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`URL` VARCHAR(255) NOT NULL,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY(`Id`)
);
"""
)
)
self._cursor.execute(
str(
f"""
CREATE TABLE IF NOT EXISTS `CFG_TechnicianIds` (
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`TechnicianId` BIGINT NOT NULL,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY(`Id`)
);
"""
)
)
def downgrade(self):
self._logger.debug(__name__, "Running downgrade")
self._server_downgrade()
self._technician_downgrade()
def _server_downgrade(self):
self._cursor.execute("DROP TABLE `CFG_Server`;")
def _technician_downgrade(self):
self._cursor.execute("DROP TABLE `CFG_Technician`;")
self._cursor.execute("DROP TABLE `CFG_TechnicianPingUrls`;")
self._cursor.execute("DROP TABLE `CFG_TechnicianIds`;")

View File

@@ -0,0 +1,65 @@
import os
from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.migration_abc import MigrationABC
from bot_data.db_context import DBContext
class DBHistoryMigration(MigrationABC):
name = "1.0.0_DBHistoryMigration"
prio = 1
def __init__(self, logger: DatabaseLogger, db: DBContext):
MigrationABC.__init__(self)
self._logger = logger
self._db = db
self._cursor = db.cursor
def _exec(self, file: str):
path = f"{os.path.dirname(os.path.realpath(__file__))}/db_history_scripts"
sql = open(f"{path}/{file}").read()
for statement in sql.split("\n\n"):
self._cursor.execute(statement + ";")
def upgrade(self):
self._logger.debug(__name__, "Running upgrade")
self._exec("api_keys.sql")
self._exec("auth_users.sql")
self._exec("auth_user_users_relation.sql")
self._exec("auto_role_rules.sql")
self._exec("auto_roles.sql")
self._exec("clients.sql")
self._exec("game_servers.sql")
self._exec("known_users.sql")
self._exec("levels.sql")
self._exec("servers.sql")
self._exec("user_game_idents.sql")
self._exec("user_joined_game_servers.sql")
self._exec("user_joined_servers.sql")
self._exec("user_joined_voice_channel.sql")
self._exec("user_message_count_per_hour.sql")
self._exec("users.sql")
self._exec("user_warnings.sql")
self._logger.debug(__name__, "Finished history upgrade")
def downgrade(self):
self._cursor.execute("DROP TABLE `ApiKeysHistory`;")
self._cursor.execute("DROP TABLE `AuthUsersHistory`;")
self._cursor.execute("DROP TABLE `AuthUserUsersRelationsHistory`;")
self._cursor.execute("DROP TABLE `AutoRoleRulesHistory`;")
self._cursor.execute("DROP TABLE `AutoRolesHistory`;")
self._cursor.execute("DROP TABLE `ClientsHistory`;")
self._cursor.execute("DROP TABLE `GameServersHistory`;")
self._cursor.execute("DROP TABLE `KnownUsersHistory`;")
self._cursor.execute("DROP TABLE `LevelsHistory`;")
self._cursor.execute("DROP TABLE `ServersHistory`;")
self._cursor.execute("DROP TABLE `UserGameIdentsHistory`;")
self._cursor.execute("DROP TABLE `UserJoinedGameServerHistory`;")
self._cursor.execute("DROP TABLE `UserJoinedServersHistory`;")
self._cursor.execute("DROP TABLE `UserJoinedVoiceChannelHistory`;")
self._cursor.execute("DROP TABLE `UserMessageCountPerHourHistory`;")
self._cursor.execute("DROP TABLE `UsersHistory`;")
self._cursor.execute("DROP TABLE `UserWarningsHistory`;")

View File

@@ -0,0 +1,46 @@
ALTER TABLE `ApiKeys`
CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6);
ALTER TABLE `ApiKeys`
CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6);
CREATE TABLE IF NOT EXISTS `ApiKeysHistory`
(
`Id` BIGINT(20) NOT NULL,
`Identifier` VARCHAR(255) NOT NULL,
`Key` VARCHAR(255) NOT NULL,
`CreatorId` BIGINT(20) DEFAULT NULL,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
DROP TRIGGER IF EXISTS `TR_ApiKeysUpdate`;
CREATE TRIGGER `TR_ApiKeysUpdate`
AFTER UPDATE
ON `ApiKeys`
FOR EACH ROW
BEGIN
INSERT INTO `ApiKeysHistory` (
`Id`, `Identifier`, `Key`, `CreatorId`, `DateFrom`, `DateTo`
)
VALUES (
OLD.Id, OLD.Identifier, OLD.Key, OLD.CreatorId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;
DROP TRIGGER IF EXISTS `TR_ApiKeysDelete`;
CREATE TRIGGER `TR_ApiKeysDelete`
AFTER DELETE
ON `ApiKeys`
FOR EACH ROW
BEGIN
INSERT INTO `ApiKeysHistory` (
`Id`, `Identifier`, `Key`, `CreatorId`, `Deleted`, `DateFrom`, `DateTo`
)
VALUES (
OLD.Id, OLD.Identifier, OLD.Key, OLD.CreatorId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;

View File

@@ -0,0 +1,46 @@
ALTER TABLE `AuthUserUsersRelations`
CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6);
ALTER TABLE `AuthUserUsersRelations`
CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6);
CREATE TABLE IF NOT EXISTS `AuthUserUsersRelationsHistory`
(
`Id` BIGINT(20) NOT NULL,
`AuthUserId` BIGINT(20) DEFAULT NULL,
`UserId` BIGINT(20) DEFAULT NULL,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
DROP TRIGGER IF EXISTS `TR_AuthUserUsersRelationsUpdate`;
CREATE TRIGGER `TR_AuthUserUsersRelationsUpdate`
AFTER UPDATE
ON `AuthUserUsersRelations`
FOR EACH ROW
BEGIN
INSERT INTO `AuthUserUsersRelationsHistory` (
`Id`, `AuthUserId`, `UserId`, `DateFrom`, `DateTo`
)
VALUES (
OLD.Id, OLD.AuthUserId, OLD.UserId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;
DROP TRIGGER IF EXISTS `TR_AuthUserUsersRelationsDelete`;
CREATE TRIGGER `TR_AuthUserUsersRelationsDelete`
AFTER DELETE
ON `AuthUserUsersRelations`
FOR EACH ROW
BEGIN
INSERT INTO `AuthUserUsersRelationsHistory` (
`Id`, `AuthUserId`, `UserId`, `Deleted`, `DateFrom`, `DateTo`
)
VALUES (
OLD.Id, OLD.AuthUserId, OLD.UserId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;

View File

@@ -0,0 +1,62 @@
ALTER TABLE `AuthUsers`
CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6);
ALTER TABLE `AuthUsers`
CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6);
CREATE TABLE IF NOT EXISTS `AuthUsersHistory`
(
`Id` BIGINT(20) NOT NULL,
`FirstName` VARCHAR(255) DEFAULT NULL,
`LastName` VARCHAR(255) DEFAULT NULL,
`EMail` VARCHAR(255) DEFAULT NULL,
`Password` VARCHAR(255) DEFAULT NULL,
`PasswordSalt` VARCHAR(255) DEFAULT NULL,
`RefreshToken` VARCHAR(255) DEFAULT NULL,
`ConfirmationId` VARCHAR(255) DEFAULT NULL,
`ForgotPasswordId` VARCHAR(255) DEFAULT NULL,
`OAuthId` VARCHAR(255) DEFAULT NULL,
`RefreshTokenExpiryTime` DATETIME(6) NOT NULL,
`AuthRole` BIGINT(11) NOT NULL DEFAULT 0,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
DROP TRIGGER IF EXISTS `TR_AuthUsersUpdate`;
CREATE TRIGGER `TR_AuthUsersUpdate`
AFTER UPDATE
ON `AuthUsers`
FOR EACH ROW
BEGIN
INSERT INTO `AuthUsersHistory` (
`Id`, `FirstName`, `LastName`, `EMail`, `Password`, `PasswordSalt`,
`RefreshToken`, `ConfirmationId`, `ForgotPasswordId`, `OAuthId`,
`RefreshTokenExpiryTime`, `AuthRole`, `DateFrom`, `DateTo`
)
VALUES (
OLD.Id, OLD.FirstName, OLD.LastName, OLD.EMail, OLD.Password, OLD.PasswordSalt, OLD.RefreshToken,
OLD.ConfirmationId, OLD.ForgotPasswordId, OLD.OAuthId, OLD.RefreshTokenExpiryTime, OLD.AuthRole,
OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;
DROP TRIGGER IF EXISTS `TR_AuthUsersDelete`;
CREATE TRIGGER `TR_AuthUsersDelete`
AFTER DELETE
ON `AuthUsers`
FOR EACH ROW
BEGIN
INSERT INTO `AuthUsersHistory` (
`Id`, `FirstName`, `LastName`, `EMail`, `Password`, `PasswordSalt`, `RefreshToken`,
`ConfirmationId`, `ForgotPasswordId`, `OAuthId`, `RefreshTokenExpiryTime`,
`AuthRole`, `Deleted`, `DateFrom`, `DateTo`
)
VALUES (
OLD.Id, OLD.FirstName, OLD.LastName, OLD.EMail, OLD.Password, OLD.PasswordSalt, OLD.RefreshToken,
OLD.ConfirmationId, OLD.ForgotPasswordId, OLD.OAuthId, OLD.RefreshTokenExpiryTime, OLD.AuthRole, TRUE,
OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;

View File

@@ -0,0 +1,46 @@
ALTER TABLE `AutoRoleRules`
CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6);
ALTER TABLE `AutoRoleRules`
CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6);
CREATE TABLE IF NOT EXISTS `AutoRoleRulesHistory`
(
`Id` BIGINT(20) NOT NULL,
`AutoRoleId` BIGINT(20) DEFAULT NULL,
`DiscordEmojiName` VARCHAR(64) DEFAULT NULL,
`DiscordRoleId` BIGINT(20) NOT NULL,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
DROP TRIGGER IF EXISTS `TR_AutoRoleRulesUpdate`;
CREATE TRIGGER `TR_AutoRoleRulesUpdate`
AFTER UPDATE
ON `AutoRoleRules`
FOR EACH ROW
BEGIN
INSERT INTO `AutoRoleRulesHistory` (
`Id`, `AutoRoleId`, `DiscordEmojiName`, `DiscordRoleId`, `DateFrom`, `DateTo`
)
VALUES (
OLD.AutoRoleRuleId, OLD.AutoRoleId, OLD.DiscordEmojiName, OLD.DiscordRoleId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;
DROP TRIGGER IF EXISTS `TR_AutoRoleRulesDelete`;
CREATE TRIGGER `TR_AutoRoleRulesDelete`
AFTER DELETE
ON `AutoRoleRules`
FOR EACH ROW
BEGIN
INSERT INTO `AutoRoleRulesHistory` (
`Id`, `AutoRoleId`, `DiscordEmojiName`, `DiscordRoleId`, `Deleted`, `DateFrom`, `DateTo`
)
VALUES (
OLD.AutoRoleRuleId, OLD.AutoRoleId, OLD.DiscordEmojiName, OLD.DiscordRoleId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;

View File

@@ -0,0 +1,48 @@
ALTER TABLE `AutoRoles`
CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6);
ALTER TABLE `AutoRoles`
CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6);
CREATE TABLE IF NOT EXISTS `AutoRolesHistory`
(
`Id` BIGINT(20) NOT NULL,
`ServerId` BIGINT(20) DEFAULT NULL,
`DiscordChannelId` BIGINT(20) NOT NULL,
`DiscordMessageId` BIGINT(20) NOT NULL,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
DROP TRIGGER IF EXISTS `TR_AutoRolesUpdate`;
CREATE TRIGGER `TR_AutoRolesUpdate`
AFTER UPDATE
ON `AutoRoles`
FOR EACH ROW
BEGIN
INSERT INTO `AutoRolesHistory` (
`Id`, `ServerId`, `DiscordChannelId`, `DiscordMessageId`, `DateFrom`, `DateTo`
)
VALUES (
OLD.AutoRoleId, OLD.ServerId, OLD.DiscordChannelId, OLD.DiscordMessageId, OLD.LastModifiedAt,
CURRENT_TIMESTAMP(6)
);
END;
DROP TRIGGER IF EXISTS `TR_AutoRolesDelete`;
CREATE TRIGGER `TR_AutoRolesDelete`
AFTER DELETE
ON `AutoRoles`
FOR EACH ROW
BEGIN
INSERT INTO `AutoRolesHistory` (
`Id`, `ServerId`, `DiscordChannelId`, `DiscordMessageId`, `Deleted`, `DateFrom`, `DateTo`
)
VALUES (
OLD.AutoRoleId, OLD.ServerId, OLD.DiscordChannelId, OLD.DiscordMessageId, TRUE, OLD.LastModifiedAt,
CURRENT_TIMESTAMP(6)
);
END;

View File

@@ -0,0 +1,54 @@
ALTER TABLE `Clients`
CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6);
ALTER TABLE `Clients`
CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6);
CREATE TABLE IF NOT EXISTS `ClientsHistory`
(
`Id` BIGINT(20) NOT NULL,
`DiscordId` BIGINT(20) NOT NULL,
`SentMessageCount` BIGINT(20) NOT NULL DEFAULT 0,
`ReceivedMessageCount` BIGINT(20) NOT NULL DEFAULT 0,
`DeletedMessageCount` BIGINT(20) NOT NULL DEFAULT 0,
`ReceivedCommandsCount` BIGINT(20) NOT NULL DEFAULT 0,
`MovedUsersCount` BIGINT(20) NOT NULL DEFAULT 0,
`ServerId` BIGINT(20) DEFAULT NULL,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
DROP TRIGGER IF EXISTS `TR_ClientsUpdate`;
CREATE TRIGGER `TR_ClientsUpdate`
AFTER UPDATE
ON `Clients`
FOR EACH ROW
BEGIN
INSERT INTO `ClientsHistory` (
`Id`, `DiscordId`, `SentMessageCount`, `ReceivedMessageCount`, `DeletedMessageCount`,
`ReceivedCommandsCount`, `MovedUsersCount`, `ServerId`, `DateFrom`, `DateTo`
)
VALUES (
OLD.ClientId, OLD.DiscordClientId, OLD.SentMessageCount, OLD.ReceivedMessageCount, OLD.DeletedMessageCount,
OLD.ReceivedCommandsCount, OLD.MovedUsersCount, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;
DROP TRIGGER IF EXISTS `TR_ClientsDelete`;
CREATE TRIGGER `TR_ClientsDelete`
AFTER DELETE
ON `Clients`
FOR EACH ROW
BEGIN
INSERT INTO `ClientsHistory` (
`Id`, `DiscordId`, `SentMessageCount`, `ReceivedMessageCount`, `DeletedMessageCount`,
`ReceivedCommandsCount`, `MovedUsersCount`, `ServerId`, `Deleted`, `DateFrom`, `DateTo`
)
VALUES (
OLD.ClientId, OLD.DiscordClientId, OLD.SentMessageCount, OLD.ReceivedMessageCount, OLD.DeletedMessageCount,
OLD.ReceivedCommandsCount, OLD.MovedUsersCount, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6)
);
END;

View File

@@ -0,0 +1,117 @@
CREATE TABLE IF NOT EXISTS `CFG_ServerHistory`
(
`Id` BIGINT(20) NOT NULL,
`MessageDeleteTimer` BIGINT NOT NULL DEFAULT 6,
`NotificationChatId` BIGINT NOT NULL,
`MaxVoiceStateHours` BIGINT NOT NULL DEFAULT 6,
`XpPerMessage` BIGINT NOT NULL DEFAULT 1,
`XpPerReaction` BIGINT NOT NULL DEFAULT 1,
`MaxMessageXpPerHour` BIGINT NOT NULL DEFAULT 20,
`XpPerOntimeHour` BIGINT NOT NULL DEFAULT 10,
`XpPerEventParticipation` BIGINT NOT NULL DEFAULT 10,
`XpPerAchievement` BIGINT NOT NULL DEFAULT 10,
`AFKCommandChannelId` BIGINT NOT NULL,
`HelpVoiceChannelId` BIGINT NOT NULL,
`TeamChannelId` BIGINT NOT NULL,
`LoginMessageChannelId` BIGINT NOT NULL,
`ServerId` BIGINT NOT NULL,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
DROP TRIGGER IF EXISTS `TR_CFG_ServerUpdate`;
CREATE TRIGGER `TR_CFG_ServerUpdate`
AFTER UPDATE
ON `CFG_Server`
FOR EACH ROW
BEGIN
INSERT INTO `CFG_ServerHistory` (
`Id`,
`MessageDeleteTimer`,
`NotificationChatId`,
`MaxVoiceStateHours`,
`XpPerMessage`,
`XpPerReaction`,
`MaxMessageXpPerHour`,
`XpPerOntimeHour`,
`XpPerEventParticipation`,
`XpPerAchievement`,
`AFKCommandChannelId`,
`HelpVoiceChannelId`,
`TeamChannelId`,
`LoginMessageChannelId`,
`ServerId`,
`DateFrom`,
`DateTo`
)
VALUES (
OLD.Id,
OLD.MessageDeleteTimer,
OLD.NotificationChatId,
OLD.MaxVoiceStateHours,
OLD.XpPerMessage,
OLD.XpPerReaction,
OLD.MaxMessageXpPerHour,
OLD.XpPerOntimeHour,
OLD.XpPerEventParticipation,
OLD.XpPerAchievement,
OLD.AFKCommandChannelId,
OLD.HelpVoiceChannelId,
OLD.TeamChannelId,
OLD.LoginMessageChannelId,
OLD.ServerId,
OLD.LastModifiedAt,
CURRENT_TIMESTAMP(6)
);
END;
DROP TRIGGER IF EXISTS `TR_CFG_ServerDelete`;
CREATE TRIGGER `TR_CFG_ServerDelete`
AFTER DELETE
ON `CFG_Server`
FOR EACH ROW
BEGIN
INSERT INTO `CFG_ServerHistory` (
`Id`,
`MessageDeleteTimer`,
`NotificationChatId`,
`MaxVoiceStateHours`,
`XpPerMessage`,
`XpPerReaction`,
`MaxMessageXpPerHour`,
`XpPerOntimeHour`,
`XpPerEventParticipation`,
`XpPerAchievement`,
`AFKCommandChannelId`,
`HelpVoiceChannelId`,
`TeamChannelId`,
`LoginMessageChannelId`,
`ServerId`,
`Deleted`,
`DateFrom`,
`DateTo`
)
VALUES (
OLD.Id,
OLD.MessageDeleteTimer,
OLD.NotificationChatId,
OLD.MaxVoiceStateHours,
OLD.XpPerMessage,
OLD.XpPerReaction,
OLD.MaxMessageXpPerHour,
OLD.XpPerOntimeHour,
OLD.XpPerEventParticipation,
OLD.XpPerAchievement,
OLD.AFKCommandChannelId,
OLD.HelpVoiceChannelId,
OLD.TeamChannelId,
OLD.LoginMessageChannelId,
OLD.ServerId,
TRUE,
OLD.LastModifiedAt,
CURRENT_TIMESTAMP(6)
);
END;

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