Compare commits

...

108 Commits

Author SHA1 Message Date
9bed89ed60 Fixed level by server id
All checks were successful
Deploy prod on push / pre-build (push) Successful in 10s
Deploy prod on push / build-bot (push) Successful in 4m19s
Deploy prod on push / build-web (push) Successful in 2m49s
Deploy prod on push / deploy (push) Successful in 30s
2024-10-29 18:38:09 +01:00
35fdeb168f Updated docker compose
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 1m59s
Deploy prod on push / build-web (push) Successful in 1m46s
Deploy prod on push / deploy (push) Successful in 22s
2024-09-06 20:50:03 +02:00
e785bddf2e Guild & Level can be null
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 3m19s
Deploy prod on push / build-web (push) Successful in 1m58s
Deploy prod on push / deploy (push) Successful in 23s
2024-09-06 19:39:50 +02:00
b361a7b685 Fixed docker
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 2m17s
Deploy prod on push / build-web (push) Successful in 1m58s
Deploy prod on push / deploy (push) Successful in 23s
2024-06-08 17:25:15 +02:00
bdd0da38ab Check if guild is None in can user see check
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 7m20s
Deploy prod on push / build-web (push) Successful in 2m36s
Deploy prod on push / deploy (push) Successful in 1m29s
2024-02-25 13:42:09 +01:00
179c8a954b Check if guild is None in can user see check
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 3m38s
Deploy prod on push / build-web (push) Successful in 2m41s
Deploy prod on push / deploy (push) Successful in 26s
2024-02-25 13:25:14 +01:00
248d47c280 Fixed update level permission by db state on level seeding
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 3m14s
Deploy prod on push / build-web (push) Successful in 1m55s
Deploy prod on push / deploy (push) Successful in 25s
2024-02-12 14:59:36 +01:00
414720f53b Update level permission by db state on level seeding
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 3m15s
Deploy prod on push / build-web (push) Successful in 1m54s
Deploy prod on push / deploy (push) Successful in 24s
2024-02-12 14:19:31 +01:00
bb0ff1c560 Check if guild is None
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 3m4s
Deploy prod on push / build-web (push) Successful in 1m45s
Deploy prod on push / deploy (push) Successful in 22s
2024-02-09 08:48:49 +01:00
521a063fca Fixed technician check when not on the server /2
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 2m58s
Deploy prod on push / build-web (push) Successful in 1m43s
Deploy prod on push / deploy (push) Successful in 21s
2024-02-09 08:27:58 +01:00
dc5ae365bb Fixed technician check when not on the server
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 3m5s
Deploy prod on push / build-web (push) Successful in 1m46s
Deploy prod on push / deploy (push) Successful in 21s
2024-02-09 08:07:54 +01:00
3c21b68b0c Check user update username
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy staging on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 3m12s
Deploy prod on push / build-web (push) Successful in 1m53s
Deploy staging on push / build-bot (push) Successful in 2m1s
Deploy prod on push / deploy (push) Successful in 23s
Deploy staging on push / build-web (push) Successful in 2m1s
Deploy staging on push / deploy (push) Successful in 22s
2024-02-03 19:21:57 +01:00
df316fd53b Merge pull request 'Use db pools' (#470) from staging into master
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 2m3s
Deploy prod on push / build-web (push) Successful in 1m49s
Deploy prod on push / deploy (push) Successful in 23s
Reviewed-on: #470
2024-02-01 20:30:03 +01:00
0a18f26a51 Merge branch 'master' into staging
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 2m4s
Deploy staging on push / build-web (push) Successful in 2m0s
Deploy staging on push / deploy (push) Successful in 22s
2024-02-01 20:29:23 +01:00
995c498e54 Use db pools
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 3m12s
Deploy staging on push / build-web (push) Successful in 1m55s
Deploy staging on push / deploy (push) Successful in 22s
2024-02-01 20:20:05 +01:00
9353fa749c Merge pull request 'staging' (#469) from staging into master
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 2m12s
Deploy prod on push / build-web (push) Successful in 1m53s
Deploy prod on push / deploy (push) Successful in 21s
Reviewed-on: #469
2024-02-01 18:39:49 +01:00
dd4b9182f3 Set version 1.2.7
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 3m15s
Deploy staging on push / build-web (push) Successful in 2m10s
Deploy staging on push / deploy (push) Successful in 22s
2024-02-01 18:21:17 +01:00
1fc8d441ad Removed fatal from db error handling & improved web error handling 2024-02-01 18:19:31 +01:00
219fffc344 Fixed user warnings
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 3m7s
Deploy prod on push / build-web (push) Successful in 1m48s
Deploy prod on push / deploy (push) Successful in 21s
2024-01-26 19:20:49 +01:00
fbdac4f57a Fixed user warnings
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 3m1s
Deploy prod on push / build-web (push) Successful in 1m47s
Deploy prod on push / deploy (push) Successful in 21s
2024-01-26 17:02:52 +01:00
dfee6b0568 Merge pull request 'staging' (#468) from staging into master
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 1m55s
Deploy prod on push / build-web (push) Successful in 1m44s
Deploy prod on push / deploy (push) Successful in 20s
Reviewed-on: #468
2024-01-26 16:33:29 +01:00
9eb09fa3b2 Fixed configs
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 3m5s
Deploy staging on push / build-web (push) Successful in 1m49s
Deploy staging on push / deploy (push) Successful in 22s
2024-01-26 15:55:46 +01:00
60d81ce18b Resend confirmation mail
Some checks failed
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Failing after 22s
Deploy staging on push / build-web (push) Failing after 21s
Deploy staging on push / deploy (push) Has been skipped
2024-01-26 15:32:01 +01:00
a24fefd3e2 Fixed test mail & delete auth user 2024-01-26 14:03:47 +01:00
8cd5a0d040 Fixed mail 2024-01-26 12:41:26 +01:00
1b8a67e81b Merge pull request 'staging_1.2.6' (#467) from staging_1.2.6 into staging
All checks were successful
Deploy staging on push / pre-build (push) Successful in 3s
Deploy staging on push / build-bot (push) Successful in 3m25s
Deploy staging on push / build-web (push) Successful in 2m9s
Deploy staging on push / deploy (push) Successful in 23s
Reviewed-on: #467
2024-01-26 12:18:03 +01:00
8318dfe988 Fixed user avatar url 2024-01-26 12:16:13 +01:00
7185b087c9 Fixed level page 2024-01-26 12:13:53 +01:00
07fc512633 Made levels & Achievements public 2024-01-26 12:11:20 +01:00
ca5db6d397 Fixed achievement can see element 2024-01-26 11:53:51 +01:00
7888783b6a Fixed registration by discord 2024-01-26 11:46:48 +01:00
31c62b4108 Added missing translations 2024-01-26 11:37:36 +01:00
b0990b626c Fixed third user warning 2024-01-26 11:36:42 +01:00
df9c889c7e Fixed add new user warning 2024-01-26 11:32:42 +01:00
4d386759c0 Improved data import 2024-01-26 11:06:01 +01:00
3683f5f3d1 Set correct version 2024-01-25 19:28:56 +01:00
77f759a9ca Added user warnings to WI 2024-01-25 19:27:45 +01:00
f209e45905 Added level icons 2024-01-25 17:11:48 +01:00
a917803eff Updated config 2024-01-25 16:46:03 +01:00
acfa359eeb Fixed loading scheduled events 2024-01-25 16:45:05 +01:00
baf7b8d7de Merge pull request 'Fixed afk command' (#465) from staging into master
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 1m56s
Deploy prod on push / build-web (push) Successful in 1m52s
Deploy prod on push / deploy (push) Successful in 23s
Reviewed-on: #465
2024-01-13 15:17:01 +01:00
ee69ae58d1 Fixed afk command
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 3m21s
Deploy staging on push / build-web (push) Successful in 1m49s
Deploy staging on push / deploy (push) Successful in 23s
2024-01-13 15:16:39 +01:00
bc528f1474 Merge pull request 'staging' (#464) from staging into master
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 1m57s
Deploy prod on push / build-web (push) Successful in 1m49s
Deploy prod on push / deploy (push) Successful in 22s
Reviewed-on: #464
2024-01-13 15:06:06 +01:00
d67ba924dc Merge branch 'master' into staging
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 3m6s
Deploy staging on push / build-web (push) Successful in 1m43s
Deploy staging on push / deploy (push) Successful in 24s
2024-01-13 15:00:11 +01:00
e054c04c96 Tried to improve db connection
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 3m3s
Deploy staging on push / build-web (push) Successful in 1m49s
Deploy staging on push / deploy (push) Successful in 23s
2024-01-13 14:51:31 +01:00
c846614274 Set version 1.2.5 2024-01-13 13:36:47 +01:00
83764b3cee Added logic to remove short role name for all members by deleting
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 3m3s
Deploy staging on push / build-web (push) Successful in 1m57s
Deploy staging on push / deploy (push) Successful in 25s
2024-01-13 13:04:52 +01:00
4553490266 Add logic to other users to afk as mod 2024-01-11 20:56:19 +01:00
35aa2574f8 Fixed level order
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 3m17s
Deploy prod on push / build-web (push) Successful in 2m2s
Deploy prod on push / deploy (push) Successful in 27s
2023-12-17 11:36:49 +01:00
ccae285b81 Merge pull request 'Removed empty cp' (#463) from staging into master
All checks were successful
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 3m58s
Deploy prod on push / build-web (push) Successful in 2m4s
Deploy prod on push / deploy (push) Successful in 1m1s
Reviewed-on: #463
2023-12-17 01:10:40 +01:00
887a02a7af Removed empty cp
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 4m3s
Deploy staging on push / build-web (push) Successful in 1m47s
Deploy staging on push / deploy (push) Successful in 1m5s
2023-12-17 01:10:07 +01:00
f484c553b3 Merge pull request 'staging' (#462) from staging into master
Some checks failed
Deploy prod on push / pre-build (push) Successful in 1s
Deploy prod on push / build-bot (push) Successful in 4m4s
Deploy prod on push / build-web (push) Failing after 58s
Deploy prod on push / deploy (push) Has been skipped
Reviewed-on: #462
2023-12-17 01:03:13 +01:00
c5eca69db1 Merge pull request '#460' (#461) from #460 into staging
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 3m17s
Deploy staging on push / build-web (push) Successful in 1m54s
Deploy staging on push / deploy (push) Successful in 25s
Reviewed-on: #461
2023-12-15 15:40:12 +01:00
d1a04c537c Set correct frontend version #460 2023-12-15 15:39:14 +01:00
72715aac62 Added frontend implementation #460 2023-12-15 15:38:38 +01:00
e516def7ef Added reset member after rejoin setting to gql #460 2023-12-15 15:20:39 +01:00
f1f5954dfc Added reset member after rejoin setting to backend [untested] #460 2023-12-15 13:42:49 +01:00
266dacb301 Fixed deps
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 3m12s
Deploy staging on push / build-web (push) Successful in 2m1s
Deploy staging on push / deploy (push) Successful in 26s
Deploy dev on push / pre-build (push) Successful in 2s
Deploy dev on push / build-bot (push) Successful in 1m55s
Deploy dev on push / build-web (push) Successful in 1m46s
Deploy dev on push / deploy (push) Successful in 23s
2023-12-13 12:11:09 +01:00
280cd9827d shutdown correct stack
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 2m1s
Deploy staging on push / build-web (push) Successful in 1m57s
Deploy staging on push / deploy (push) Successful in 22s
2023-12-13 11:59:21 +01:00
36998470e8 Try filtering scheduled events
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 3m0s
Deploy staging on push / build-web (push) Successful in 2m7s
Deploy staging on push / deploy (push) Successful in 24s
2023-12-13 11:25:51 +01:00
53c6bf4208 Merge pull request 'Added gmod support #277' (#459) from #277 into staging
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 3m8s
Deploy staging on push / build-web (push) Successful in 1m47s
Deploy staging on push / deploy (push) Successful in 24s
Reviewed-on: #459
2023-12-12 11:49:43 +01:00
4e80e3ccb7 Added gmod support #277 2023-12-11 21:34:38 +01:00
ba173a6743 Improved xp knob #409
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 3m4s
Deploy staging on push / build-web (push) Successful in 1m56s
Deploy staging on push / deploy (push) Successful in 26s
2023-12-10 19:50:44 +01:00
84ff2a8a9b Fixed update user #455 2023-12-10 19:18:20 +01:00
13bc38fea8 Updated profile #409 2023-12-10 19:00:00 +01:00
dfdf0555d7 Added feature flag check for scheduled events #455
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 3m6s
Deploy staging on push / build-web (push) Successful in 1m57s
Deploy staging on push / deploy (push) Successful in 28s
2023-12-10 17:08:26 +01:00
39299eb11b Made watchers transient
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 3m46s
Deploy staging on push / build-web (push) Successful in 2m5s
Deploy staging on push / deploy (push) Successful in 28s
2023-12-10 13:13:24 +01:00
dfb6751bf9 Set event watcher loop from 12 to 3 hours
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 2m52s
Deploy staging on push / build-web (push) Successful in 1m53s
Deploy staging on push / deploy (push) Successful in 32s
2023-12-10 11:18:30 +01:00
4a75635a55 Fixed actions
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 1m47s
Deploy staging on push / build-web (push) Successful in 1m42s
Deploy staging on push / deploy (push) Successful in 22s
2023-12-09 22:48:37 +01:00
f6b2739394 Merge pull request 'Fixed actions' (#458) from dev into staging
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 1m52s
Deploy staging on push / build-web (push) Successful in 1m44s
Deploy staging on push / deploy (push) Successful in 23s
Reviewed-on: #458
2023-12-09 22:38:35 +01:00
36d2605655 Merge branch 'staging' into dev
All checks were successful
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Successful in 1m53s
Deploy dev on push / build-web (push) Successful in 1m47s
Deploy dev on push / deploy (push) Successful in 21s
2023-12-09 22:38:16 +01:00
af891fa588 Fixed actions
All checks were successful
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Successful in 1m51s
Deploy dev on push / build-web (push) Successful in 1m50s
Deploy dev on push / deploy (push) Successful in 23s
2023-12-09 22:33:14 +01:00
af348b85a4 Merge pull request 'dev into staging' (#457) from dev into staging
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 1m46s
Deploy staging on push / build-web (push) Successful in 1m44s
Deploy staging on push / deploy (push) Successful in 27s
Reviewed-on: #457
2023-12-09 22:23:06 +01:00
7ed621a25b Fixed actions
All checks were successful
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Successful in 1m52s
Deploy dev on push / build-web (push) Successful in 1m41s
Deploy dev on push / deploy (push) Successful in 21s
2023-12-09 22:17:56 +01:00
013f953a7f Fixed actions
All checks were successful
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Successful in 1m53s
Deploy dev on push / build-web (push) Successful in 1m42s
Deploy dev on push / deploy (push) Successful in 23s
2023-12-09 22:10:04 +01:00
4163532696 Fixed actions
All checks were successful
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Successful in 1m52s
Deploy dev on push / build-web (push) Successful in 1m57s
Deploy dev on push / deploy (push) Successful in 6s
2023-12-09 22:02:57 +01:00
b6a1172cc1 Fixed actions
All checks were successful
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Successful in 2m0s
Deploy dev on push / build-web (push) Successful in 1m47s
Deploy dev on push / deploy (push) Successful in 6s
2023-12-09 21:51:47 +01:00
20bdb6bd98 Updated compose files
All checks were successful
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Successful in 2m1s
Deploy dev on push / build-web (push) Successful in 1m42s
Deploy dev on push / deploy (push) Successful in 5s
2023-12-09 21:46:01 +01:00
3f13f65932 Updated other env actions 2023-12-09 21:43:34 +01:00
711e184895 Fixed dev action
All checks were successful
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Successful in 1m48s
Deploy dev on push / build-web (push) Successful in 1m53s
Deploy dev on push / deploy (push) Successful in 5s
2023-12-09 21:34:21 +01:00
7e3975f4be Fixed dev action
Some checks failed
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Successful in 2m13s
Deploy dev on push / build-web (push) Successful in 1m43s
Deploy dev on push / deploy (push) Failing after 1s
2023-12-09 21:28:15 +01:00
d4f4f39522 Fixed dev action
Some checks failed
Deploy dev on push / pre-build (push) Successful in 1s
Deploy dev on push / build-bot (push) Failing after 1m55s
Deploy dev on push / build-web (push) Failing after 1m45s
Deploy dev on push / deploy (push) Has been skipped
2023-12-09 21:22:00 +01:00
af9c55e4b1 Updated dev action
Some checks failed
Deploy dev on push / pre-build (push) Successful in 2s
Deploy dev on push / build-bot (push) Failing after 2m3s
Deploy dev on push / build-web (push) Failing after 2m5s
Deploy dev on push / deploy (push) Has been skipped
2023-12-09 21:00:20 +01:00
e3172d6f24 Fixed event logger
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 4m22s
2023-12-09 14:11:34 +01:00
0706579f62 Fixed set timestamp for scheduled events #456
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 4m9s
2023-12-09 14:05:35 +01:00
ad3fc94923 Improved logging for event_service
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 4m13s
2023-12-09 13:58:38 +01:00
69882af0bd Added event logger
Some checks reported warnings
Deploy staging on push / on-push-deploy_sh-edraft (push) Has been cancelled
2023-12-09 13:55:40 +01:00
560c7650bd Merge pull request 'Removed native password & disable ssl' (#454) from staging into master
All checks were successful
Deploy prod on push / on-push-deploy_sh-edraft (push) Successful in 3m24s
Reviewed-on: #454
2023-12-06 18:28:55 +01:00
b0fb12f841 Removed native password & disable ssl
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 5m13s
2023-12-06 17:59:23 +01:00
18386339b7 Merge pull request 'staging' (#453) from staging into master
All checks were successful
Deploy prod on push / on-push-deploy_sh-edraft (push) Successful in 3m21s
Reviewed-on: #453
2023-12-04 23:04:29 +01:00
4d980331e2 Merge pull request 'Added user activity score #451' (#452) from dev into staging
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 3m18s
Reviewed-on: #452
2023-12-04 22:55:03 +01:00
e6667c78c8 Added user activity score #451
All checks were successful
Deploy dev on push / on-push-deploy_sh-edraft (push) Successful in 4m14s
2023-12-04 22:48:26 +01:00
9976c59302 Fixed permission service
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 4m42s
Deploy dev on push / on-push-deploy_sh-edraft (push) Successful in 3m27s
2023-12-03 16:42:33 +01:00
293c8cd81c Merge pull request 'dev into staging' (#450) from dev into staging
All checks were successful
Deploy staging on push / on-push-deploy_sh-edraft (push) Successful in 3m34s
Reviewed-on: #450
2023-12-03 16:08:24 +01:00
8f4ea56184 Merge branch 'staging' into dev
All checks were successful
Deploy dev on push / on-push-deploy_sh-edraft (push) Successful in 4m2s
2023-12-03 16:07:29 +01:00
898e005978 Merge pull request 'Improved ontime loading & added game ontime #446' (#449) from #446 into dev
All checks were successful
Deploy dev on push / on-push-deploy_sh-edraft (push) Successful in 4m58s
Reviewed-on: #449
2023-12-03 16:06:50 +01:00
db3e6183ba Merge branch 'dev' into #446 2023-12-03 16:06:36 +01:00
0a47393510 Improved ontime loading & added game ontime #446 2023-12-03 16:04:56 +01:00
6c5b514b41 Set new version
All checks were successful
Deploy dev on push / on-push-deploy_sh-edraft (push) Successful in 5m20s
2023-12-03 15:31:29 +01:00
84f994fd58 Merge pull request '#446' (#448) from #446 into dev
Some checks reported warnings
Deploy dev on push / on-push-deploy_sh-edraft (push) Has been cancelled
Reviewed-on: #448
2023-12-03 15:28:07 +01:00
3d21123786 Fixed profile design #446 2023-12-03 15:24:53 +01:00
36887f1bdf Improved feature flag loading in frontend #446 2023-12-03 15:13:20 +01:00
0e4419312b Improved permission loading #446 2023-12-03 15:03:40 +01:00
94732b7227 Improved data integrity service loop #446 2023-12-03 13:14:10 +01:00
4233e089f8 Improved user message per hour check handling #446 2023-12-03 11:59:16 +01:00
0aa690b984 Changed normal data collection to list comprehensions p3 #446 2023-12-02 18:16:04 +01:00
b6b9bfabf5 Changed normal data collection to list comprehensions p2 #446 2023-12-02 17:53:23 +01:00
d927ab8fb7 Changed normal data collection to list comprehensions p1 #446 2023-12-02 17:37:50 +01:00
277 changed files with 3671 additions and 2351 deletions

View File

@ -6,9 +6,17 @@ on:
- dev - dev
jobs: jobs:
on-push-deploy_sh-edraft: pre-build:
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ] runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: sh-edraft.de/act-runner:latest container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Shutdown stack
run: docker stack rm sdb_dev
build-bot:
needs: pre-build
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps: steps:
- name: Setup docker - name: Setup docker
uses: https://github.com/papodaca/install-docker-action@main uses: https://github.com/papodaca/install-docker-action@main
@ -22,10 +30,44 @@ jobs:
- name: Prepare bot build - name: Prepare bot build
run: | run: |
cd bot
python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
cd bot
cpl i cpl i
- name: Build docker bot
run: |
cd bot
docker image prune -f
cpl build
docker build -t git.sh-edraft.de/sh-edraft.de/sdb-bot:$(cpl gv)-dev .
- name: Login to registry git.sh-edraft.de
uses: https://github.com/docker/login-action@v1
with:
registry: git.sh-edraft.de
username: ${{ secrets.CI_USERNAME }}
password: ${{ secrets.CI_ACCESS_TOKEN }}
- name: Push image
run: |
cd bot
docker push git.sh-edraft.de/sh-edraft.de/sdb-bot:$(cpl gv)-dev
build-web:
needs: pre-build
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Setup docker
uses: https://github.com/papodaca/install-docker-action@main
- run: docker -v
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
token: ${{ secrets.CI_ACCESS_TOKEN }}
submodules: true
- name: Setup node - name: Setup node
uses: https://github.com/actions/setup-node@v3 uses: https://github.com/actions/setup-node@v3
@ -35,29 +77,45 @@ jobs:
npm install -g ts-node npm install -g ts-node
npm ci npm ci
- name: Shutdown stack
run: docker stack rm sdb_dev
- name: Build docker bot
run: |
cd bot
docker image prune -f
cpl build
docker build -t sh-edraft.de/sdb-bot:$(cpl gv)-dev .
- name: Build docker web - name: Build docker web
run: | run: |
cd web cd web
docker image prune -f docker image prune -f
cp src/favicon.dev.ico src/favicon.ico cp src/favicon.dev.ico src/favicon.ico
npm run build npm run build
docker build -t sh-edraft.de/sdb-web:$(npm run -s gv)-dev . docker build -t git.sh-edraft.de/sh-edraft.de/sdb-web:$(npm run -s gv)-dev .
- name: Login to registry git.sh-edraft.de
uses: https://github.com/docker/login-action@v1
with:
registry: git.sh-edraft.de
username: ${{ secrets.CI_USERNAME }}
password: ${{ secrets.CI_ACCESS_TOKEN }}
- name: Push image
run: |
cd web
docker push git.sh-edraft.de/sh-edraft.de/sdb-web:$(npm run -s gv)-dev
deploy:
needs: [ build-bot, build-web ]
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
token: ${{ secrets.CI_ACCESS_TOKEN }}
submodules: true
- name: Install cpl
run: python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
- name: Set version - name: Set version
run: | run: |
cd bot/docker cd bot/docker
chmod +x ./set-docker-compose-image-version.sh chmod +x ./set-docker-compose-image-version.sh
./set-docker-compose-image-version.sh sh-edraft.de/sdb-bot:$(cd ../; cpl gv)-dev sh-edraft.de/sdb-web:$(cd ../../web; npm run -s gv;)-dev ./set-docker-compose-image-version.sh git.sh-edraft.de/sh-edraft.de/sdb-bot:$(cd ../; cpl gv)-dev git.sh-edraft.de/sh-edraft.de/sdb-web:$(cd ../../web; npm run -s gv;)-dev
- name: Deploy Stack to sh-edraft.de - name: Deploy Stack to sh-edraft.de
uses: https://github.com/kgierke/portainer-stack-deployment@v1 uses: https://github.com/kgierke/portainer-stack-deployment@v1

View File

@ -6,9 +6,17 @@ on:
- master - master
jobs: jobs:
on-push-deploy_sh-edraft: pre-build:
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ] runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: sh-edraft.de/act-runner:latest container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Shutdown stack
run: docker stack rm sdb_prod
build-bot:
needs: pre-build
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps: steps:
- name: Setup docker - name: Setup docker
uses: https://github.com/papodaca/install-docker-action@main uses: https://github.com/papodaca/install-docker-action@main
@ -22,10 +30,44 @@ jobs:
- name: Prepare bot build - name: Prepare bot build
run: | run: |
cd bot
python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
cd bot
cpl i cpl i
- name: Build docker bot
run: |
cd bot
docker image prune -f
cpl build
docker build -t git.sh-edraft.de/sh-edraft.de/sdb-bot:$(cpl gv) .
- name: Login to registry git.sh-edraft.de
uses: https://github.com/docker/login-action@v1
with:
registry: git.sh-edraft.de
username: ${{ secrets.CI_USERNAME }}
password: ${{ secrets.CI_ACCESS_TOKEN }}
- name: Push image
run: |
cd bot
docker push git.sh-edraft.de/sh-edraft.de/sdb-bot:$(cpl gv)
build-web:
needs: pre-build
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Setup docker
uses: https://github.com/papodaca/install-docker-action@main
- run: docker -v
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
token: ${{ secrets.CI_ACCESS_TOKEN }}
submodules: true
- name: Setup node - name: Setup node
uses: https://github.com/actions/setup-node@v3 uses: https://github.com/actions/setup-node@v3
@ -35,28 +77,44 @@ jobs:
npm install -g ts-node npm install -g ts-node
npm ci npm ci
- name: Shutdown stack
run: docker stack rm sdb_prod
- name: Build docker bot
run: |
cd bot
docker image prune -f
cpl build
docker build -t sh-edraft.de/sdb-bot:$(cpl gv) .
- name: Build docker web - name: Build docker web
run: | run: |
cd web cd web
docker image prune -f docker image prune -f
npm run build npm run build
docker build -t sh-edraft.de/sdb-web:$(npm run -s gv) . docker build -t git.sh-edraft.de/sh-edraft.de/sdb-web:$(npm run -s gv) .
- name: Login to registry git.sh-edraft.de
uses: https://github.com/docker/login-action@v1
with:
registry: git.sh-edraft.de
username: ${{ secrets.CI_USERNAME }}
password: ${{ secrets.CI_ACCESS_TOKEN }}
- name: Push image
run: |
cd web
docker push git.sh-edraft.de/sh-edraft.de/sdb-web:$(npm run -s gv)
deploy:
needs: [ build-bot, build-web ]
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
token: ${{ secrets.CI_ACCESS_TOKEN }}
submodules: true
- name: Install cpl
run: python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
- name: Set version - name: Set version
run: | run: |
cd bot/docker cd bot/docker
chmod +x ./set-docker-compose-image-version.sh chmod +x ./set-docker-compose-image-version.sh
./set-docker-compose-image-version.sh sh-edraft.de/sdb-bot:$(cd ../; cpl gv) sh-edraft.de/sdb-web:$(cd ../../web; npm run -s gv;) ./set-docker-compose-image-version.sh git.sh-edraft.de/sh-edraft.de/sdb-bot:$(cd ../; cpl gv) git.sh-edraft.de/sh-edraft.de/sdb-web:$(cd ../../web; npm run -s gv;)
- name: Deploy Stack to sh-edraft.de - name: Deploy Stack to sh-edraft.de
uses: https://github.com/kgierke/portainer-stack-deployment@v1 uses: https://github.com/kgierke/portainer-stack-deployment@v1

View File

@ -6,9 +6,17 @@ on:
- staging - staging
jobs: jobs:
on-push-deploy_sh-edraft: pre-build:
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ] runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: sh-edraft.de/act-runner:latest container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Shutdown stack
run: docker stack rm sdb_staging
build-bot:
needs: pre-build
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps: steps:
- name: Setup docker - name: Setup docker
uses: https://github.com/papodaca/install-docker-action@main uses: https://github.com/papodaca/install-docker-action@main
@ -22,10 +30,44 @@ jobs:
- name: Prepare bot build - name: Prepare bot build
run: | run: |
cd bot
python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
cd bot
cpl i cpl i
- name: Build docker bot
run: |
cd bot
docker image prune -f
cpl build
docker build -t git.sh-edraft.de/sh-edraft.de/sdb-bot:$(cpl gv)-staging .
- name: Login to registry git.sh-edraft.de
uses: https://github.com/docker/login-action@v1
with:
registry: git.sh-edraft.de
username: ${{ secrets.CI_USERNAME }}
password: ${{ secrets.CI_ACCESS_TOKEN }}
- name: Push image
run: |
cd bot
docker push git.sh-edraft.de/sh-edraft.de/sdb-bot:$(cpl gv)-staging
build-web:
needs: pre-build
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Setup docker
uses: https://github.com/papodaca/install-docker-action@main
- run: docker -v
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
token: ${{ secrets.CI_ACCESS_TOKEN }}
submodules: true
- name: Setup node - name: Setup node
uses: https://github.com/actions/setup-node@v3 uses: https://github.com/actions/setup-node@v3
@ -35,29 +77,45 @@ jobs:
npm install -g ts-node npm install -g ts-node
npm ci npm ci
- name: Shutdown stack
run: docker stack rm sdb_staging
- name: Build docker bot
run: |
cd bot
docker image prune -f
cpl build
docker build -t sh-edraft.de/sdb-bot:$(cpl gv)-staging .
- name: Build docker web - name: Build docker web
run: | run: |
cd web cd web
docker image prune -f docker image prune -f
cp src/favicon.staging.ico src/favicon.ico cp src/favicon.staging.ico src/favicon.ico
npm run build npm run build
docker build -t sh-edraft.de/sdb-web:$(npm run -s gv)-staging . docker build -t git.sh-edraft.de/sh-edraft.de/sdb-web:$(npm run -s gv)-staging .
- name: Login to registry git.sh-edraft.de
uses: https://github.com/docker/login-action@v1
with:
registry: git.sh-edraft.de
username: ${{ secrets.CI_USERNAME }}
password: ${{ secrets.CI_ACCESS_TOKEN }}
- name: Push image
run: |
cd web
docker push git.sh-edraft.de/sh-edraft.de/sdb-web:$(npm run -s gv)-staging
deploy:
needs: [ build-bot, build-web ]
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
token: ${{ secrets.CI_ACCESS_TOKEN }}
submodules: true
- name: Install cpl
run: python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
- name: Set version - name: Set version
run: | run: |
cd bot/docker cd bot/docker
chmod +x ./set-docker-compose-image-version.sh chmod +x ./set-docker-compose-image-version.sh
./set-docker-compose-image-version.sh sh-edraft.de/sdb-bot:$(cd ../; cpl gv)-staging sh-edraft.de/sdb-web:$(cd ../../web; npm run -s gv;)-staging ./set-docker-compose-image-version.sh git.sh-edraft.de/sh-edraft.de/sdb-bot:$(cd ../; cpl gv)-staging git.sh-edraft.de/sh-edraft.de/sdb-web:$(cd ../../web; npm run -s gv;)-staging
- name: Deploy Stack to sh-edraft.de - name: Deploy Stack to sh-edraft.de
uses: https://github.com/kgierke/portainer-stack-deployment@v1 uses: https://github.com/kgierke/portainer-stack-deployment@v1

View File

@ -14,7 +14,6 @@
"config": "src/modules/config/config.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",
"technician": "src/modules/technician/technician.json", "technician": "src/modules/technician/technician.json",
"short-role-name": "src/modules/short_role_name/short-role-name.json", "short-role-name": "src/modules/short_role_name/short-role-name.json",
"special-offers": "src/modules/special_offers/special-offers.json", "special-offers": "src/modules/special_offers/special-offers.json",

@ -1 +1 @@
Subproject commit b0bacce9f6cd20833560c4889289ac4320f643b6 Subproject commit fbcd9226c4d199529fdbce5169b38b1b23074adb

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -4,7 +4,7 @@
"Version": { "Version": {
"Major": "1", "Major": "1",
"Minor": "2", "Minor": "2",
"Micro": "2" "Micro": "8"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de", "AuthorEmail": "sven.heidemann@sh-edraft.de",
@ -16,7 +16,6 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"cpl-core==2023.10.0",
"cpl-translation==2023.4.0.post1", "cpl-translation==2023.4.0.post1",
"cpl-query==2023.10.0", "cpl-query==2023.10.0",
"cpl-discord==2023.10.0.post1", "cpl-discord==2023.10.0.post1",
@ -33,7 +32,9 @@
"cryptography==41.0.4", "cryptography==41.0.4",
"discord==2.3.2", "discord==2.3.2",
"bs4==0.0.1", "bs4==0.0.1",
"lxml==4.9.3" "lxml==4.9.3",
"python-valve==0.2.1",
"cpl-core==2023.10.2"
], ],
"DevDependencies": [ "DevDependencies": [
"cpl-cli==2023.4.0.post3", "cpl-cli==2023.4.0.post3",
@ -70,7 +71,6 @@
"../modules/config/config.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/short_role_name/short-role-name.json", "../modules/short_role_name/short-role-name.json",
"../modules/special_offers/special-offers.json", "../modules/special_offers/special-offers.json",
"../modules/technician/technician.json" "../modules/technician/technician.json"

@ -1 +1 @@
Subproject commit c11ca6f2e8e54bacdf16da677fbcf03705ff9780 Subproject commit eeebd13f80c6ceecc922ede5771e55212a884019

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -12,7 +12,6 @@ from modules.boot_log.boot_log_module import BootLogModule
from modules.config.config_module import ConfigModule 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.short_role_name.short_role_name_module import ShortRoleNameModule from modules.short_role_name.short_role_name_module import ShortRoleNameModule
from modules.special_offers.special_offers_module import SteamSpecialOffersModule from modules.special_offers.special_offers_module import SteamSpecialOffersModule
from modules.technician.technician_module import TechnicianModule from modules.technician.technician_module import TechnicianModule
@ -30,7 +29,6 @@ class ModuleList:
ConfigModule, # has to be before db check ConfigModule, # has to be before db check
DatabaseModule, DatabaseModule,
GraphQLModule, GraphQLModule,
PermissionModule,
AutoRoleModule, AutoRoleModule,
BaseModule, BaseModule,
LevelModule, LevelModule,

View File

@ -15,6 +15,7 @@ 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.logging.command_logger import CommandLogger from bot_core.logging.command_logger import CommandLogger
from bot_core.logging.database_logger import DatabaseLogger from bot_core.logging.database_logger import DatabaseLogger
from bot_core.logging.event_logger import EventLogger
from bot_core.logging.message_logger import MessageLogger from bot_core.logging.message_logger import MessageLogger
from bot_core.logging.task_logger import TaskLogger from bot_core.logging.task_logger import TaskLogger
from bot_data.db_context import DBContext from bot_data.db_context import DBContext
@ -45,6 +46,7 @@ class Startup(StartupABC):
services.add_singleton(CustomFileLoggerABC, DatabaseLogger) services.add_singleton(CustomFileLoggerABC, DatabaseLogger)
services.add_singleton(CustomFileLoggerABC, MessageLogger) services.add_singleton(CustomFileLoggerABC, MessageLogger)
services.add_singleton(CustomFileLoggerABC, TaskLogger) services.add_singleton(CustomFileLoggerABC, TaskLogger)
services.add_singleton(CustomFileLoggerABC, EventLogger)
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module): if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
services.add_singleton(CustomFileLoggerABC, ApiLogger) services.add_singleton(CustomFileLoggerABC, ApiLogger)

View File

@ -2,22 +2,22 @@
"api": { "api": {
"api": { "api": {
"test_mail": { "test_mail": {
"message": "Dies ist eine Test-Mail vom Krümelmonster Web Interface\nGesendet von {}-{}", "message": "Dies ist eine Test-Mail vom Krümelmonster Web Interface\r\nGesendet von {}-{}",
"subject": "Krümelmonster Web Interface Test-Mail" "subject": "Krümelmonster Web Interface Test-Mail"
} }
}, },
"auth": { "auth": {
"confirmation": { "confirmation": {
"message": "Öffne den Link, um die E-Mail zu bestätigen:\n{}auth/register/{}", "message": "Öffne den Link, um die E-Mail zu bestätigen:\r\n{}auth/register/{}",
"subject": "E-Mail für {} {} bestätigen" "subject": "E-Mail für {} {} bestätigen"
}, },
"forgot_password": { "forgot_password": {
"message": "Öffne den Link, um das Passwort zu ändern:\n{}auth/forgot-password/{}", "message": "Öffne den Link, um das Passwort zu ändern:\r\n{}auth/forgot-password/{}",
"subject": "Passwort für {} {} zurücksetzen" "subject": "Passwort für {} {} zurücksetzen"
} }
}, },
"mail": { "mail": {
"automatic_mail": "\n\nDies ist eine automatische E-Mail.\nGesendet von {}-{}@{}" "automatic_mail": "\r\n\r\nDies ist eine automatische E-Mail.\r\nGesendet von {}-{}@{}"
} }
}, },
"common": { "common": {

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -114,3 +114,7 @@ class AuthServiceABC(ABC):
@abstractmethod @abstractmethod
async def reset_password_async(self, rp_dto: ResetPasswordDTO): async def reset_password_async(self, rp_dto: ResetPasswordDTO):
pass pass
@abstractmethod
async def resend_confirmation_email_by_mail(self, mail: str):
pass

View File

@ -16,8 +16,8 @@ from werkzeug.exceptions import NotFound
from bot_api.configuration.api_settings import ApiSettings from bot_api.configuration.api_settings import ApiSettings
from bot_api.configuration.authentication_settings import AuthenticationSettings from bot_api.configuration.authentication_settings import AuthenticationSettings
from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_core.exception.service_error_code_enum import ServiceErrorCode
from bot_api.exception.service_exception import ServiceException from bot_core.exception.service_exception import ServiceException
from bot_api.logging.api_logger import ApiLogger from bot_api.logging.api_logger import ApiLogger
from bot_api.model.error_dto import ErrorDTO from bot_api.model.error_dto import ErrorDTO
from bot_api.route.route import Route from bot_api.route.route import Route

View File

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

@ -1 +1 @@
Subproject commit 521951b8abb0f784b59b6d3e0210606fa193e60a Subproject commit 12ffcbcd9b88612251a1e23cb6724e21562f74b8

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -84,13 +84,13 @@ class AuthController:
self._auth_service.add_auth_user(dto) self._auth_service.add_auth_user(dto)
return "", 200 return "", 200
@Route.post(f"{BasePath}/resend-confirmation-email-by-mail/<mail>")
async def resend_confirmation_email_by_user_id(self, mail: str):
await self._auth_service.resend_confirmation_email_by_mail(mail)
return "", 200
@Route.post(f"{BasePath}/register-by-id/<id>") @Route.post(f"{BasePath}/register-by-id/<id>")
async def register_id(self, id: str): async def register_id(self, id: str):
if not FeatureFlagsSettings.get_flag_from_dict(
self._technician_config.feature_flags, FeatureFlagsEnum.basic_registration
):
return
result = await self._auth_service.confirm_email_async(id) result = await self._auth_service.confirm_email_async(id)
return jsonify(result) return jsonify(result)

View File

@ -16,6 +16,7 @@ from bot_api.api import Api
from bot_api.configuration.discord_authentication_settings import ( from bot_api.configuration.discord_authentication_settings import (
DiscordAuthenticationSettings, DiscordAuthenticationSettings,
) )
from bot_core.exception.service_exception import ServiceException
from bot_api.logging.api_logger import ApiLogger from bot_api.logging.api_logger import ApiLogger
from bot_api.model.auth_user_dto import AuthUserDTO from bot_api.model.auth_user_dto import AuthUserDTO
from bot_api.route.route import Route from bot_api.route.route import Route
@ -90,5 +91,10 @@ class AuthDiscordController:
AuthRoleEnum.normal, AuthRoleEnum.normal,
) )
result = await self._auth_service.login_discord_async(dto, response["id"]) try:
return jsonify(result.to_dict()) result = await self._auth_service.login_discord_async(dto, response["id"])
return jsonify(result.to_dict())
except ServiceException as e:
r = jsonify({"email": dto.email})
r.status_code = 403
return r

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
"""
bot sh-edraft.de Discord bot
~~~~~~~~~~~~~~~~~~~
Discord bot for customers of sh-edraft.de
:copyright: (c) 2022 - 2023 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = "bot_api.exception"
__author__ = "Sven Heidemann"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.2"
from collections import namedtuple
# imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="2")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -1,10 +1,7 @@
import traceback
from typing import Optional from typing import Optional
from cpl_core.console import Console
from bot_api.abc.dto_abc import DtoABC from bot_api.abc.dto_abc import DtoABC
from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_core.exception.service_error_code_enum import ServiceErrorCode
class ErrorDTO(DtoABC): class ErrorDTO(DtoABC):

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -8,8 +8,8 @@ from flask import request, jsonify
from flask_cors import cross_origin from flask_cors import cross_origin
from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.abc.auth_service_abc import AuthServiceABC
from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_core.exception.service_error_code_enum import ServiceErrorCode
from bot_api.exception.service_exception import ServiceException from bot_core.exception.service_exception import ServiceException
from bot_api.model.error_dto import ErrorDTO from bot_api.model.error_dto import ErrorDTO
from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -1,6 +1,5 @@
import hashlib import hashlib
import re import re
import textwrap
import uuid import uuid
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from threading import Thread from threading import Thread
@ -19,8 +18,8 @@ from flask import request
from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.abc.auth_service_abc import AuthServiceABC
from bot_api.configuration.authentication_settings import AuthenticationSettings from bot_api.configuration.authentication_settings import AuthenticationSettings
from bot_api.configuration.frontend_settings import FrontendSettings from bot_api.configuration.frontend_settings import FrontendSettings
from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_core.exception.service_error_code_enum import ServiceErrorCode
from bot_api.exception.service_exception import ServiceException from bot_core.exception.service_exception import ServiceException
from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria
from bot_api.logging.api_logger import ApiLogger from bot_api.logging.api_logger import ApiLogger
from bot_api.model.auth_user_dto import AuthUserDTO from bot_api.model.auth_user_dto import AuthUserDTO
@ -172,11 +171,7 @@ class AuthService(AuthServiceABC):
mail.add_header("Content-Transfer-Encoding: quoted-printable") mail.add_header("Content-Transfer-Encoding: quoted-printable")
mail.add_receiver(str(email)) mail.add_receiver(str(email))
mail.subject = subject mail.subject = subject
mail.body = textwrap.dedent( mail.body = f"{message}\r\n{self._t.transform('api.mail.automatic_mail').format(self._environment.application_name, self._environment.environment_name, self._environment.host_name)}"
f"""{message}
{self._t.transform('api.mail.automatic_mail').format(self._environment.application_name, self._environment.environment_name, self._environment.host_name)}
"""
)
thr = Thread(target=self._mailer.send_mail, args=[mail]) thr = Thread(target=self._mailer.send_mail, args=[mail])
thr.start() thr.start()
@ -599,3 +594,12 @@ class AuthService(AuthServiceABC):
user.forgot_password_id = None user.forgot_password_id = None
self._auth_users.update_auth_user(user) self._auth_users.update_auth_user(user)
self._db.save_changes() self._db.save_changes()
async def resend_confirmation_email_by_mail(self, mail: str):
user = self._auth_users.find_auth_user_by_email(mail)
if user is None:
raise ServiceException(ServiceErrorCode.InvalidUser, f"User not found")
if user.confirmation_id is None:
raise ServiceException(ServiceErrorCode.DataAlreadyExists, f"User already confirmed")
self._send_confirmation_id_to_user(user)

View File

@ -4,8 +4,8 @@ from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List from cpl_query.extension import List
from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.abc.auth_service_abc import AuthServiceABC
from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_core.exception.service_error_code_enum import ServiceErrorCode
from bot_api.exception.service_exception import ServiceException from bot_core.exception.service_exception import ServiceException
from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria
from bot_api.model.discord.server_dto import ServerDTO from bot_api.model.discord.server_dto import ServerDTO
from bot_api.model.discord.server_filtered_result_dto import ServerFilteredResultDTO from bot_api.model.discord.server_filtered_result_dto import ServerFilteredResultDTO

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -10,7 +10,7 @@ from bot_api.model.user_dto import UserDTO
from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_role_enum import AuthRoleEnum
from bot_data.model.auth_user import AuthUser from bot_data.model.auth_user import AuthUser
from bot_data.model.user import User from bot_data.model.user import User
from modules.permission.abc.permission_service_abc import PermissionServiceABC from bot_core.abc.permission_service_abc import PermissionServiceABC
class AuthUserTransformer(TransformerABC): class AuthUserTransformer(TransformerABC):
@ -35,21 +35,37 @@ class AuthUserTransformer(TransformerABC):
@ServiceProviderABC.inject @ServiceProviderABC.inject
def _is_technician(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): def _is_technician(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
guild = bot.get_guild(user.server.discord_id) guild = bot.get_guild(user.server.discord_id)
if guild is None:
return permissions.is_member_technician_by_id(user.discord_id)
member = guild.get_member(user.discord_id) member = guild.get_member(user.discord_id)
if member is None:
return permissions.is_member_technician_by_id(user.discord_id)
return permissions.is_member_technician(member) return permissions.is_member_technician(member)
@staticmethod @staticmethod
@ServiceProviderABC.inject @ServiceProviderABC.inject
def _is_admin(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): def _is_admin(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
guild = bot.get_guild(user.server.discord_id) guild = bot.get_guild(user.server.discord_id)
if guild is None:
return False
member = guild.get_member(user.discord_id) member = guild.get_member(user.discord_id)
if member is None:
return False
return permissions.is_member_admin(member) return permissions.is_member_admin(member)
@staticmethod @staticmethod
@ServiceProviderABC.inject @ServiceProviderABC.inject
def _is_moderator(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): def _is_moderator(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
guild = bot.get_guild(user.server.discord_id) guild = bot.get_guild(user.server.discord_id)
if guild is None:
return False
member = guild.get_member(user.discord_id) member = guild.get_member(user.discord_id)
if member is None:
return False
return permissions.is_member_moderator(member) return permissions.is_member_moderator(member)
@classmethod @classmethod

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -48,6 +48,16 @@ class ClientUtilsABC(ABC):
def get_auto_complete_list(self, _l: List, current: str, select: Callable = None) -> List: def get_auto_complete_list(self, _l: List, current: str, select: Callable = None) -> List:
pass pass
@abstractmethod
def update_user_message_xp_count_by_hour(
self,
created_at: datetime,
user: User,
settings: ServerConfig,
is_reaction: bool = False,
):
pass
@abstractmethod @abstractmethod
def is_message_xp_count_by_hour_higher_that_max_message_count_per_hour( def is_message_xp_count_by_hour_higher_that_max_message_count_per_hour(
self, self,

View File

@ -19,3 +19,7 @@ class PermissionServiceABC(ABC):
@abstractmethod @abstractmethod
def is_member_technician(self, member: discord.Member) -> bool: def is_member_technician(self, member: discord.Member) -> bool:
pass pass
@abstractmethod
def is_member_technician_by_id(self, member_id: int) -> bool:
pass

View File

@ -4,7 +4,7 @@
"Version": { "Version": {
"Major": "1", "Major": "1",
"Minor": "2", "Minor": "2",
"Micro": "2" "Micro": "8"
}, },
"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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -15,7 +15,6 @@ class FeatureFlagsEnum(Enum):
database_module = "DatabaseModule" database_module = "DatabaseModule"
level_module = "LevelModule" level_module = "LevelModule"
moderator_module = "ModeratorModule" moderator_module = "ModeratorModule"
permission_module = "PermissionModule"
short_role_name_module = "ShortRoleNameModule" short_role_name_module = "ShortRoleNameModule"
steam_special_offers_module = "SteamSpecialOffersModule" steam_special_offers_module = "SteamSpecialOffersModule"
# features # features

View File

@ -16,7 +16,6 @@ class FeatureFlagsSettings(ConfigurationModelABC):
FeatureFlagsEnum.data_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.database_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48 FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48
FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.config_module.value: True, # 19.07.2023 #127 FeatureFlagsEnum.config_module.value: True, # 19.07.2023 #127
FeatureFlagsEnum.short_role_name_module.value: True, # 28.09.2023 #378 FeatureFlagsEnum.short_role_name_module.value: True, # 28.09.2023 #378
FeatureFlagsEnum.steam_special_offers_module.value: True, # 11.10.2023 #188 FeatureFlagsEnum.steam_special_offers_module.value: True, # 11.10.2023 #188

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -9,7 +9,7 @@ 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.helper.command_checks import CommandChecks from bot_core.helper.command_checks import CommandChecks
from bot_core.helper.event_checks import EventChecks from bot_core.helper.event_checks import EventChecks
from modules.permission.abc.permission_service_abc import PermissionServiceABC from bot_core.abc.permission_service_abc import PermissionServiceABC
class CoreExtension(ApplicationExtensionABC): class CoreExtension(ApplicationExtensionABC):

View File

@ -1,20 +1,18 @@
import asyncio
from cpl_core.configuration import ConfigurationABC from cpl_core.configuration import ConfigurationABC
from cpl_core.logging import LoggerABC
from cpl_discord.events import OnReadyABC from cpl_discord.events import OnReadyABC
from cpl_discord.service import DiscordBotServiceABC from cpl_discord.service import DiscordBotServiceABC
from cpl_translation import TranslatePipe from cpl_translation import TranslatePipe
from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.client_utils_abc import ClientUtilsABC
from bot_core.environment_variables import MAINTENANCE from bot_core.environment_variables import MAINTENANCE
from bot_core.logging.event_logger import EventLogger
class CoreExtensionOnReadyEvent(OnReadyABC): class CoreExtensionOnReadyEvent(OnReadyABC):
def __init__( def __init__(
self, self,
config: ConfigurationABC, config: ConfigurationABC,
logger: LoggerABC, logger: EventLogger,
bot: DiscordBotServiceABC, bot: DiscordBotServiceABC,
client_utils: ClientUtilsABC, client_utils: ClientUtilsABC,
t: TranslatePipe, t: TranslatePipe,

View File

@ -7,6 +7,7 @@ from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
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.abc.message_service_abc import MessageServiceABC
from bot_core.abc.module_abc import ModuleABC from bot_core.abc.module_abc import ModuleABC
from bot_core.abc.permission_service_abc import PermissionServiceABC
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum 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
@ -14,6 +15,7 @@ from bot_core.service.client_utils_service import ClientUtilsService
from bot_core.service.config_service import ConfigService from bot_core.service.config_service import ConfigService
from bot_core.service.data_integrity_service import DataIntegrityService 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
from bot_core.service.permission_service import PermissionService
class CoreModule(ModuleABC): class CoreModule(ModuleABC):
@ -28,6 +30,7 @@ class CoreModule(ModuleABC):
services.add_transient(MessageServiceABC, MessageService) services.add_transient(MessageServiceABC, MessageService)
services.add_transient(ClientUtilsABC, ClientUtilsService) services.add_transient(ClientUtilsABC, ClientUtilsService)
services.add_transient(DataIntegrityService) services.add_transient(DataIntegrityService)
services.add_singleton(PermissionServiceABC, PermissionService)
# 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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -1,15 +1,15 @@
from cpl_core.logging import LoggerABC
from cpl_discord.events import OnReadyABC from cpl_discord.events import OnReadyABC
from cpl_discord.service import DiscordBotServiceABC from cpl_discord.service import DiscordBotServiceABC
from cpl_translation import TranslatePipe from cpl_translation import TranslatePipe
from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.client_utils_abc import ClientUtilsABC
from bot_core.logging.event_logger import EventLogger
class CoreOnReadyEvent(OnReadyABC): class CoreOnReadyEvent(OnReadyABC):
def __init__( def __init__(
self, self,
logger: LoggerABC, logger: EventLogger,
bot: DiscordBotServiceABC, bot: DiscordBotServiceABC,
client_utils: ClientUtilsABC, client_utils: ClientUtilsABC,
t: TranslatePipe, t: TranslatePipe,

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -1,4 +1,4 @@
from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_core.exception.service_error_code_enum import ServiceErrorCode
class ServiceException(Exception): class ServiceException(Exception):

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -7,7 +7,7 @@ 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.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 from bot_core.abc.permission_service_abc import PermissionServiceABC
class CommandChecks: class CommandChecks:

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -0,0 +1,15 @@
from cpl_core.configuration import ConfigurationABC
from cpl_core.environment import ApplicationEnvironmentABC
from cpl_core.time import TimeFormatSettings
from bot_core.abc.custom_file_logger_abc import CustomFileLoggerABC
class EventLogger(CustomFileLoggerABC):
def __init__(
self,
config: ConfigurationABC,
time_format: TimeFormatSettings,
env: ApplicationEnvironmentABC,
):
CustomFileLoggerABC.__init__(self, "Event", config, time_format, env)

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -143,14 +143,13 @@ class ClientUtilsService(ClientUtilsABC):
return _l.take(25) return _l.take(25)
def is_message_xp_count_by_hour_higher_that_max_message_count_per_hour( def update_user_message_xp_count_by_hour(
self, self,
created_at: datetime, created_at: datetime,
user: User, user: User,
settings: ServerConfig, settings: ServerConfig,
is_reaction: bool = False, is_reaction: bool = False,
) -> bool: ):
umcph = None
try: try:
umcph = self._umcphs.find_user_message_count_per_hour_by_user_id_and_date(user.id, created_at) umcph = self._umcphs.find_user_message_count_per_hour_by_user_id_and_date(user.id, created_at)
if umcph is None: if umcph is None:
@ -162,44 +161,50 @@ class ClientUtilsService(ClientUtilsABC):
user, user,
) )
) )
self._db.save_changes() self._db.save_changes()
umcph = self._umcphs.get_user_message_count_per_hour_by_user_id_and_date(user.id, created_at) umcph = self._umcphs.get_user_message_count_per_hour_by_user_id_and_date(user.id, created_at)
except Exception as e:
self._logger.error(
__name__,
f"Cannot add user message count per hour with id {umcph.id}",
e,
)
return False
try:
if is_reaction:
umcph.xp_count += settings.xp_per_reaction
else:
umcph.xp_count += settings.xp_per_message
umcph.xp_count += settings.xp_per_reaction if is_reaction else settings.xp_per_message
self._umcphs.update_user_message_count_per_hour(umcph) self._umcphs.update_user_message_count_per_hour(umcph)
self._db.save_changes() self._db.save_changes()
except Exception as e: except Exception as e:
self._logger.error( self._logger.error(
__name__, __name__,
f"Cannot update user message count per hour with id {umcph.id}", f"Cannot update user message count per hour {created_at}",
e, e,
) )
return False return False
if umcph.xp_count is None: def is_message_xp_count_by_hour_higher_that_max_message_count_per_hour(
return False self,
created_at: datetime,
user: User,
settings: ServerConfig,
is_reaction: bool = False,
) -> bool:
try:
umcph = self._umcphs.find_user_message_count_per_hour_by_user_id_and_date(user.id, created_at)
if umcph is None or umcph.xp_count is None:
return False
return umcph.xp_count > settings.max_message_xp_per_hour return umcph.xp_count > settings.max_message_xp_per_hour
except Exception as e:
self._logger.error(
__name__,
f"Cannot add user message count per hour with",
e,
)
return False
def get_ontime_for_user(self, user: User) -> float: def get_ontime_for_user(self, user: User) -> float:
return round( return round(
self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.id) sum(
.where(lambda x: x.leaved_on is not None and x.joined_on is not None) [
.sum(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600), (join.leaved_on - join.joined_on).total_seconds() / 3600
for join in self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.id)
if join.leaved_on is not None and join.joined_on is not None
]
),
2, 2,
) )
@ -214,7 +219,7 @@ class ClientUtilsService(ClientUtilsABC):
guild: Guild = self._bot.guilds.where(lambda g: g == guild).single() guild: Guild = self._bot.guilds.where(lambda g: g == guild).single()
channel = guild.get_channel(discord_channel_id) channel = guild.get_channel(discord_channel_id)
message = await channel.fetch_message(discord_message_id) message = await channel.fetch_message(discord_message_id)
emoji = List(discord.Emoji, guild.emojis).where(lambda x: x.name == rule.emoji_name).single() emoji = List(discord.Emoji, [x for x in guild.emojis if x.name == rule.emoji_name]).single()
if emoji is None: if emoji is None:
self._logger.debug(__name__, f"Emoji {rule.emoji_name} not found") self._logger.debug(__name__, f"Emoji {rule.emoji_name} not found")

View File

@ -1,9 +1,8 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Union
import discord
from cpl_core.configuration import ConfigurationABC from cpl_core.configuration import ConfigurationABC
from cpl_core.database.context import DatabaseContextABC from cpl_core.database.context import DatabaseContextABC
from cpl_discord.container import Member, Guild
from cpl_discord.service import DiscordBotServiceABC from cpl_discord.service import DiscordBotServiceABC
from bot_core.abc.client_utils_abc import ClientUtilsABC from bot_core.abc.client_utils_abc import ClientUtilsABC
@ -66,356 +65,255 @@ class DataIntegrityService:
self._is_for_shutdown = False self._is_for_shutdown = False
def _check_known_users(self): async def check_data_integrity(self, is_for_shutdown=False):
self._logger.debug(__name__, f"Start checking KnownUsers table, {len(self._bot.users)}") self._logger.info(__name__, f"Data integrity service started")
for u in self._bot.users: if is_for_shutdown != self._is_for_shutdown:
u: discord.User = u self._is_for_shutdown = is_for_shutdown
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) try:
if user is not None: for g in self._bot.guilds:
continue self._logger.debug(__name__, f"Start check for server: {g.id}")
s = self._get_or_create_server(g)
self._logger.debug(__name__, f"Start check for clients")
self._check_clients(g.id, s)
self._logger.warn(__name__, f"Unknown user: {u.id}") for m in [m for m in g.members if not m.bot]:
self._logger.debug(__name__, f"Add user: {u.id}") await self._check_default_role(m)
self._known_users.add_user(KnownUser(u.id)) self._check_known_user(m.id)
self._db_context.save_changes()
user = self._known_users.find_user_by_discord_id(u.id) self._logger.debug(__name__, f"Start check for member: {g.id}@{m.id}")
if user is None: u = self._get_or_create_user(s, m.id)
self._logger.fatal(__name__, f"Cannot add user: {u.id}")
self._logger.debug(__name__, f"Added user: {u.id}") self._logger.debug(__name__, f"Start check for user joined server: {g.id}@{m.id}")
except Exception as e: self._check_user_join(g, m, u)
self._logger.error(__name__, f"Cannot get user", e)
def check_servers(self): self._logger.debug(__name__, f"Start check for user joined voice channels: {g.id}@{m.id}")
self._logger.debug(__name__, f"Start checking Servers table") self._check_user_joined_vc(g.id, m, u)
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"Start check for user joined game servers: {g.id}@{m.id}")
self._logger.debug(__name__, f"Add server: {g.id}") self._check_user_joined_gs(g.id, m.id, u)
self._servers.add_server(Server(g.id))
self._db_context.save_changes()
server = self._servers.find_server_by_discord_id(g.id) self._logger.debug(__name__, f"Start check for user got achievements: {g.id}@{m.id}")
if server is None: await self._check_for_user_achievements(u)
self._logger.fatal(__name__, f"Cannot add server: {g.id}")
self._logger.debug(__name__, f"Added server: {g.id}") for m in [m for m in g.members if m.bot]:
except Exception as e: u = self._users.find_user_by_discord_id_and_server_id(m.id, s.id)
self._logger.error(__name__, f"Cannot get server", e) if u is None:
continue
self._remove_bot(u)
self._logger.info(__name__, f"Data integrity service finished")
except Exception as e:
self._logger.fatal(__name__, f"Checking data integrity failed", e)
def _get_or_create_server(self, guild: Guild) -> Server:
try:
server = self._servers.find_server_by_discord_id(guild.id)
if server is not None:
return server
self._logger.warn(__name__, f"Server not found in database: {guild.id}")
self._logger.debug(__name__, f"Add server: {guild.id}")
self._servers.add_server(Server(guild.id))
self._db_context.save_changes()
server = self._servers.find_server_by_discord_id(guild.id)
if server is None:
self._logger.fatal(__name__, f"Cannot add server: {guild.id}")
self._logger.trace(__name__, f"Added server: {guild.id}")
return server
except Exception as e:
self._logger.error(__name__, f"Cannot get server", e)
def _check_clients(self, guild_id: int, server: Server):
try:
client = self._clients.find_client_by_server_id(server.id)
if client is not None:
return
self._logger.warn(
__name__,
f"Client for server {guild_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 {guild_id}",
)
self._logger.trace(__name__, f"Added client: {guild_id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get client", e)
results = self._servers.get_servers() results = self._servers.get_servers()
if results is None or len(results) == 0: if results is None or len(results) == 0:
self._logger.error(__name__, f"Table Servers is empty!") self._logger.error(__name__, f"Table Servers is empty!")
def _check_clients(self): def _check_known_user(self, member_id: int):
self._logger.debug(__name__, f"Start checking Clients table") try:
for g in self._bot.guilds: if self._known_users.find_user_by_discord_id(member_id) is not None:
g: discord.Guild = g return
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) self._logger.warn(__name__, f"Unknown user: {member_id}")
if client is not None: self._logger.trace(__name__, f"Add known user: {member_id}")
self._known_users.add_user(KnownUser(member_id))
self._db_context.save_changes()
user = self._known_users.find_user_by_discord_id(member_id)
if user is None:
self._logger.fatal(__name__, f"Cannot add user: {member_id}")
self._logger.trace(__name__, f"Added known user: {member_id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get user", e)
def _get_or_create_user(self, server: Server, member_id: int) -> User:
try:
user = self._users.find_user_by_discord_id_and_server_id(member_id, server.id)
if user is not None:
return user
self._logger.warn(__name__, f"User not found in database: {member_id}")
self._logger.debug(__name__, f"Add user: {member_id}")
self._users.add_user(User(member_id, 0, 0, 0, None, server))
self._db_context.save_changes()
self._logger.trace(__name__, f"Added User: {member_id}")
return self._users.get_user_by_discord_id_and_server_id(member_id, server.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_join(self, guild: Guild, member: Member, user: User):
try:
join = self._user_joins.find_active_user_joined_server_by_user_id(user.id)
if join is not None:
return
self._logger.warn(
__name__,
f"Active UserJoinedServer not found in database: {guild.id}:{member.id}@{member.joined_at}",
)
self._logger.debug(
__name__,
f"Add UserJoinedServer: {guild.id}:{member.id}@{member.joined_at}",
)
self._user_joins.add_user_joined_server(UserJoinedServer(user, self._dtp.transform(member.joined_at), None))
self._db_context.save_changes()
self._logger.trace(__name__, f"Added UserJoinedServer: {member.id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get UserJoinedServer", e)
try:
joins = self._user_joins.get_user_joined_servers()
for join in [x for x in joins if x.user.server.discord_id == guild.id and x.leaved_on is None]:
dc_user = guild.get_member(join.user.discord_id)
if dc_user is not None:
continue continue
self._logger.warn( self._logger.warn(
__name__, __name__,
f"Client for server {g.id} not found in database: {self._bot.user.id}", f"User {join.user.discord_id} already left the server.",
) )
self._logger.debug(__name__, f"Add client: {self._bot.user.id}") join.leaved_on = datetime.now()
self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server)) self._user_joins.update_user_joined_server(join)
self._db_context.save_changes() self._db_context.save_changes()
except Exception as e:
self._logger.error(__name__, f"Cannot update UserJoinedServer", e)
client = self._clients.find_client_by_server_id(server.id) def _check_user_joined_vc(self, guild_id: int, member: Member, user: User):
if client is None: settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild_id}")
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}") try:
except Exception as e: # close open voice states
self._logger.error(__name__, f"Cannot get client", e) joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.id)
if joins is None or len(joins) == 0:
return
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, None, 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: for join in joins:
join: UserJoinedServer = join self._logger.warn(
if join.user.server.discord_id != guild.id: __name__,
continue f"Active UserJoinedVoiceChannel found in database: {guild_id}:{member.id}@{join.joined_on}",
)
join.leaved_on = datetime.now()
if join.leaved_on is not None: if ((join.leaved_on - join.joined_on).total_seconds() / 60 / 60) > settings.max_voice_state_hours:
continue join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours)
dc_user = guild.get_member(join.user.discord_id) self._user_joins_vc.update_user_joined_voice_channel(join)
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() if self._is_for_shutdown:
user.xp += round(join.time * settings.xp_per_ontime_hour)
self._users.update_user(user)
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_default_role(self):
for guild in self._bot.guilds:
for member in guild.members:
await self._client_utils.check_default_role(member)
def _check_for_bots(self):
for guild in self._bot.guilds:
server = self._servers.get_server_by_discord_id(guild.id)
for member in guild.members.where(lambda x: x.bot):
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id)
if user is None:
continue
for join in self._user_joins.get_user_joined_servers_by_user_id(user.id):
self._user_joins.delete_user_joined_server(join)
self._user_joins_vc.delete_user_joined_voice_channel_by_user_id(user.id)
self._users.delete_user(user)
self._db_context.save_changes() self._db_context.save_changes()
if self._is_for_shutdown:
return
async def check_data_integrity(self, is_for_shutdown=False): # add open voice states
if is_for_shutdown != self._is_for_shutdown: if member.voice is None or member.voice.channel.id in settings.afk_channel_ids:
self._is_for_shutdown = is_for_shutdown return
await self._check_default_role() join = UserJoinedVoiceChannel(user, member.voice.channel.id, datetime.now())
self._check_known_users() self._user_joins_vc.add_user_joined_voice_channel(join)
self.check_servers() self._db_context.save_changes()
self._check_clients() except Exception as e:
self._check_users() self._logger.error(__name__, f"Cannot get UserJoinedVoiceChannel", e)
self._check_user_joins()
self._check_user_joins_vc() def _check_user_joined_gs(self, guild_id: int, member_id: int, user: User):
self._check_user_joined_gs() try:
await self._check_for_user_achievements() joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.id)
self._check_for_bots() if joins is None or len(joins) == 0:
return
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.time > 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, user: User):
try:
await self._achievements.validate_achievements_for_user(user)
except Exception as e:
self._logger.error(__name__, f"Cannot check UserGotAchievement for {user.id}", e)
async def _check_default_role(self, member: Member):
await self._client_utils.check_default_role(member)
def _remove_bot(self, user: User):
known_user = self._known_users.find_user_by_discord_id(user.discord_id)
if known_user is not None:
self._known_users.delete_user(known_user)
for join in self._user_joins.get_user_joined_servers_by_user_id(user.id):
self._user_joins.delete_user_joined_server(join)
self._user_joins_vc.delete_user_joined_voice_channel_by_user_id(user.id)
self._users.delete_user(user)
self._db_context.save_changes()

View File

@ -0,0 +1,129 @@
from typing import Optional
import discord
from cpl_core.configuration import ConfigurationABC
from cpl_core.logging import LoggerABC
from cpl_discord.service import DiscordBotServiceABC
from bot_core.abc.permission_service_abc import PermissionServiceABC
from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.abc.technician_config_repository_abc import TechnicianConfigRepositoryABC
from bot_data.model.team_member_type_enum import TeamMemberTypeEnum
class PermissionService(PermissionServiceABC):
def __init__(
self,
logger: LoggerABC,
bot: DiscordBotServiceABC,
config: ConfigurationABC,
servers: ServerRepositoryABC,
server_configs: ServerConfigRepositoryABC,
technician_configs: TechnicianConfigRepositoryABC,
):
PermissionServiceABC.__init__(self)
self._logger = logger
self._bot = bot
self._config = config
self._servers = servers
self._server_configs = server_configs
self._technician_configs = technician_configs
# member_id: {team_member_type: {guild_id: bool}}
self._cache: dict[int, dict[TeamMemberTypeEnum, dict[int, bool]]] = {}
def reset_cache(self):
self._cache = {}
def get_cached_permission(
self, member_id: int, team_member_type: TeamMemberTypeEnum, guild_id: int = None
) -> Optional[bool]:
if member_id not in self._cache:
self._cache[member_id] = {}
if team_member_type not in self._cache[member_id]:
self._cache[member_id][team_member_type] = {}
return None
if guild_id not in self._cache[member_id][team_member_type]:
return None
return self._cache[member_id][team_member_type][guild_id]
def set_cached_permission(
self, value: bool, member_id: int, team_member_type: TeamMemberTypeEnum, guild_id: int = None
):
if member_id not in self._cache:
self._cache[member_id] = {}
if team_member_type not in self._cache[member_id]:
self._cache[member_id][team_member_type] = {}
self._cache[member_id][team_member_type][guild_id] = value
def _has_member_role(self, member: discord.Member, team_member_type: TeamMemberTypeEnum) -> bool:
if member is None or member.guild is None:
return False
try:
has_permission_cached = self.get_cached_permission(member.id, team_member_type, member.guild.id)
if has_permission_cached is not None:
return has_permission_cached
self._logger.debug(__name__, f"Checking is member {member.name} {team_member_type.value}")
has_permission = True in [
member.guild.get_role(x.role_id) in member.roles
for x in self._server_configs.get_server_config_by_server(
self._servers.get_server_by_discord_id(member.guild.id).id
).team_role_ids
if x.team_member_type == team_member_type
]
self.set_cached_permission(has_permission, member.id, team_member_type, member.guild.id)
return has_permission
except Exception as e:
self._logger.error(__name__, "Permission check failed", e)
return False
def is_member_admin(self, member: discord.Member) -> bool:
return self._has_member_role(member, TeamMemberTypeEnum.admin)
def is_member_moderator(self, member: discord.Member) -> bool:
return self._has_member_role(member, TeamMemberTypeEnum.moderator) or self._has_member_role(
member, TeamMemberTypeEnum.admin
)
def is_member_technician(self, member: discord.Member) -> bool:
if member is None or member.guild is None:
return False
has_permission_cached = self.get_cached_permission(member.id, TeamMemberTypeEnum.technician)
if has_permission_cached is not None:
return has_permission_cached
self._logger.debug(__name__, f"Checking is member {member.name} technician")
try:
has_permission = member.id in self._technician_configs.get_technician_config().technician_ids
self.set_cached_permission(has_permission, member.id, TeamMemberTypeEnum.technician)
return has_permission
except Exception as e:
self._logger.error(__name__, "Permission check failed", e)
return False
def is_member_technician_by_id(self, member_id: int):
has_permission_cached = self.get_cached_permission(member_id, TeamMemberTypeEnum.technician)
if has_permission_cached is not None:
return has_permission_cached
self._logger.debug(__name__, f"Checking is member {member_id} technician")
try:
has_permission = member_id in self._technician_configs.get_technician_config().technician_ids
self.set_cached_permission(has_permission, member_id, TeamMemberTypeEnum.technician)
return has_permission
except Exception as e:
self._logger.error(__name__, "Permission check failed", e)
return False

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

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.2.2" __version__ = "1.2.8"
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="2", micro="2") version_info = VersionInfo(major="1", minor="2", micro="8")

View File

@ -19,10 +19,6 @@ class UserJoinedServerRepositoryABC(ABC):
def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer: def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer:
pass pass
@abstractmethod
def get_user_joined_server_by_server_id(self, server_id: int) -> UserJoinedServer:
pass
@abstractmethod @abstractmethod
def get_user_joined_servers_by_user_id(self, user_id: int) -> list[UserJoinedServer]: def get_user_joined_servers_by_user_id(self, user_id: int) -> list[UserJoinedServer]:
pass pass

View File

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

View File

@ -18,6 +18,10 @@ class UserWarningsRepositoryABC(ABC):
def get_user_warnings_by_id(self, id: int) -> UserWarnings: def get_user_warnings_by_id(self, id: int) -> UserWarnings:
pass pass
@abstractmethod
def get_user_warnings_by_server_id(self, server_id: int) -> List[UserWarnings]:
pass
@abstractmethod @abstractmethod
def get_user_warnings_by_user_id(self, user_id: int) -> List[UserWarnings]: def get_user_warnings_by_user_id(self, user_id: int) -> List[UserWarnings]:
pass pass

View File

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

View File

@ -0,0 +1,50 @@
from typing import Optional
from cpl_core.database import DatabaseSettings
from cpl_core.database.connection import DatabaseConnectionABC
from mysql.connector.abstracts import MySQLConnectionAbstract
from mysql.connector.cursor import MySQLCursorBuffered
class DBConnection(DatabaseConnectionABC):
def __init__(self):
DatabaseConnectionABC.__init__(self)
self._database: Optional[MySQLConnectionAbstract] = None
self._cursor: Optional[MySQLCursorBuffered] = None
@property
def server(self) -> MySQLConnectionAbstract:
return self._database
@property
def cursor(self) -> MySQLCursorBuffered:
return self._cursor
def connect(self, settings: DatabaseSettings):
# connection = sql.connect(
# host=settings.host,
# port=settings.port,
# user=settings.user,
# passwd=CredentialManager.decrypt(settings.password),
# charset=settings.charset,
# use_unicode=settings.use_unicode,
# buffered=settings.buffered,
# auth_plugin=settings.auth_plugin,
# ssl_disabled=settings.ssl_disabled,
# )
# connection.cursor().execute(f"CREATE DATABASE IF NOT EXISTS `{settings.database}`;")
# self._database = sql.connect(
# host=settings.host,
# port=settings.port,
# user=settings.user,
# passwd=CredentialManager.decrypt(settings.password),
# db=settings.database,
# charset=settings.charset,
# use_unicode=settings.use_unicode,
# buffered=settings.buffered,
# auth_plugin=settings.auth_plugin,
# ssl_disabled=settings.ssl_disabled,
# )
self._
self._cursor = self._database.cursor()

View File

@ -1,9 +1,12 @@
import time import uuid
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
from bot_core.exception.service_error_code_enum import ServiceErrorCode
from bot_core.exception.service_exception import ServiceException
from bot_core.logging.database_logger import DatabaseLogger from bot_core.logging.database_logger import DatabaseLogger
from bot_data.mysql_pool import MySQLPool
class DBContext(DatabaseContext): class DBContext(DatabaseContext):
@ -11,36 +14,45 @@ class DBContext(DatabaseContext):
self._logger = logger self._logger = logger
DatabaseContext.__init__(self) DatabaseContext.__init__(self)
self._pool: MySQLPool = None
self._fails = 0 self._fails = 0
def connect(self, database_settings: DatabaseSettings): def connect(self, database_settings: DatabaseSettings):
try: try:
self._logger.debug(__name__, "Connecting to database") self._logger.debug(__name__, "Connecting to database")
self._db.connect(database_settings) self._pool = MySQLPool(database_settings)
self._pool.execute(f"CREATE DATABASE IF NOT EXISTS `{database_settings.database}`;", commit=True)
self._logger.info(__name__, "Connected to database") self._logger.info(__name__, "Connected to database")
except Exception as e: except Exception as e:
self._logger.fatal(__name__, "Connecting to database failed", e) self._logger.fatal(__name__, "Connecting to database failed", e)
@property
def cursor(self):
return self
def save_changes(self): def save_changes(self):
try: pass
self._logger.trace(__name__, "Save changes")
super(DBContext, self).save_changes()
self._logger.debug(__name__, "Saved changes")
except Exception as e:
self._logger.error(__name__, "Saving changes failed", e)
def select(self, statement: str) -> list[tuple]: def select(self, statement: str) -> list[tuple]:
try: try:
return super(DBContext, self).select(statement) return self._pool.execute(statement)
except Exception as e: except Exception as e:
if self._fails >= 3: 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)
uid = uuid.uuid4()
raise ServiceException(
ServiceErrorCode.Unknown,
f"Query failed three times with {type(e).__name__}. Contact an admin and give them the UID: {uid}",
)
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 self._fails += 1
try: try:
time.sleep(0.5) self._logger.debug(__name__, "Retry select")
return self.select(statement) return self.select(statement)
except Exception as e: except Exception as e:
pass pass
return [] return []
def execute(self, statement: str):
return self._pool.execute(statement, commit=True)

View File

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

View File

@ -258,6 +258,15 @@ class AuthUser(TableABC):
""" """
) )
@property
def delete_relations_string(self) -> str:
return str(
f"""
DELETE FROM `AuthUserUsersRelations`
WHERE `AuthUserId` = {self._auth_user_id};
"""
)
@property @property
def delete_string(self) -> str: def delete_string(self) -> str:
return str( return str(

View File

@ -1,4 +1,5 @@
from datetime import datetime from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
@ -48,8 +49,10 @@ class AutoRoleRule(TableABC):
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def role_name(self, bot: DiscordBotServiceABC) -> str: def role_name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.auto_role.server.discord_id) guild = bot.get_guild(self.auto_role.server.discord_id)
if guild is None:
return None
return guild.get_role(self.role_id).name return guild.get_role(self.role_id).name
@role_id.setter @role_id.setter

View File

@ -1,3 +1,5 @@
from typing import Optional
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
@ -43,6 +45,8 @@ class AutoRoleRuleHistory(HistoryTableABC):
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def role_name(self, bot: DiscordBotServiceABC) -> str: def role_name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.auto_role.server.discord_id) guild = bot.get_guild(self.auto_role.server.discord_id)
if guild is None:
return None
return guild.get_role(self.role_id).name return guild.get_role(self.role_id).name

View File

@ -2,6 +2,10 @@ from datetime import datetime
from typing import Optional from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List
from discord import Role
from bot_data.model.server import Server from bot_data.model.server import Server
@ -33,6 +37,15 @@ class Level(TableABC):
def id(self) -> int: def id(self) -> int:
return self._id return self._id
@property
@ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.server.discord_id)
if guild is None:
return None
role = List(Role, guild.roles).where(lambda x: x.name == self._name).first_or_default()
return None if role is None else role.icon
@property @property
def name(self) -> str: def name(self) -> str:
return self._name return self._name

View File

@ -1,4 +1,5 @@
from datetime import datetime from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
@ -30,14 +31,18 @@ class Server(TableABC):
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str: def name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.discord_id) guild = bot.get_guild(self.discord_id)
if guild is None:
return None
return None if guild is None else guild.name return None if guild is None else guild.name
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> str: def icon_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.discord_id) guild = bot.get_guild(self.discord_id)
if guild is None:
return None
return None if guild is None else guild.icon.url return None if guild is None else guild.icon.url
@staticmethod @staticmethod

View File

@ -32,6 +32,7 @@ class ServerConfig(TableABC, ConfigurationModelABC):
default_role_id: Optional[int], default_role_id: Optional[int],
short_role_name_only_set_highest_role: bool, short_role_name_only_set_highest_role: bool,
game_offer_notification_chat_id: int, game_offer_notification_chat_id: int,
reset_member_after_rejoin: bool,
feature_flags: dict[FeatureFlagsEnum], feature_flags: dict[FeatureFlagsEnum],
server: Server, server: Server,
afk_channel_ids: List[int], afk_channel_ids: List[int],
@ -58,6 +59,7 @@ class ServerConfig(TableABC, ConfigurationModelABC):
self._default_role_id = default_role_id self._default_role_id = default_role_id
self._short_role_name_only_set_highest_role = short_role_name_only_set_highest_role self._short_role_name_only_set_highest_role = short_role_name_only_set_highest_role
self._game_offer_notification_chat_id = game_offer_notification_chat_id self._game_offer_notification_chat_id = game_offer_notification_chat_id
self._reset_member_after_rejoin = reset_member_after_rejoin
self._feature_flags = feature_flags self._feature_flags = feature_flags
self._server = server self._server = server
@ -88,6 +90,7 @@ class ServerConfig(TableABC, ConfigurationModelABC):
None, None,
False, False,
guild.system_channel.id, guild.system_channel.id,
False,
{}, {},
server, server,
List(int), List(int),
@ -234,6 +237,14 @@ class ServerConfig(TableABC, ConfigurationModelABC):
def game_offer_notification_chat_id(self, value: int): def game_offer_notification_chat_id(self, value: int):
self._game_offer_notification_chat_id = value self._game_offer_notification_chat_id = value
@property
def reset_member_after_rejoin(self) -> bool:
return self._reset_member_after_rejoin
@reset_member_after_rejoin.setter
def reset_member_after_rejoin(self, value: bool):
self._reset_member_after_rejoin = value
@property @property
def feature_flags(self) -> dict[FeatureFlagsEnum]: def feature_flags(self) -> dict[FeatureFlagsEnum]:
return self._feature_flags return self._feature_flags
@ -310,6 +321,7 @@ class ServerConfig(TableABC, ConfigurationModelABC):
`DefaultRoleId`, `DefaultRoleId`,
`ShortRoleNameSetOnlyHighest`, `ShortRoleNameSetOnlyHighest`,
`GameOfferNotificationChatId`, `GameOfferNotificationChatId`,
`ResetMemberAfterRejoin`,
`FeatureFlags`, `FeatureFlags`,
`ServerId` `ServerId`
) VALUES ( ) VALUES (
@ -330,6 +342,7 @@ class ServerConfig(TableABC, ConfigurationModelABC):
{"NULL" if self._default_role_id is None else self._default_role_id}, {"NULL" if self._default_role_id is None else self._default_role_id},
{self._short_role_name_only_set_highest_role}, {self._short_role_name_only_set_highest_role},
{self._game_offer_notification_chat_id}, {self._game_offer_notification_chat_id},
{self._reset_member_after_rejoin},
'{json.dumps(self._feature_flags)}', '{json.dumps(self._feature_flags)}',
{self._server.id} {self._server.id}
); );
@ -357,7 +370,8 @@ class ServerConfig(TableABC, ConfigurationModelABC):
`LoginMessageChannelId` = {self._login_message_channel_id}, `LoginMessageChannelId` = {self._login_message_channel_id},
`DefaultRoleId` = {"NULL" if self._default_role_id is None else self._default_role_id}, `DefaultRoleId` = {"NULL" if self._default_role_id is None else self._default_role_id},
`ShortRoleNameSetOnlyHighest` = {self._short_role_name_only_set_highest_role}, `ShortRoleNameSetOnlyHighest` = {self._short_role_name_only_set_highest_role},
`GameOfferNotificationChatId` = {self._game_offer_notification_chat_id}, `GameOfferNotificationChatId` = {"NULL" if self._game_offer_notification_chat_id is None else self._game_offer_notification_chat_id},
`ResetMemberAfterRejoin` = {self._reset_member_after_rejoin},
`FeatureFlags` = '{json.dumps(self._feature_flags)}', `FeatureFlags` = '{json.dumps(self._feature_flags)}',
`ServerId` = {self._server.id} `ServerId` = {self._server.id}
WHERE `Id` = {self._id}; WHERE `Id` = {self._id};

View File

@ -1,3 +1,5 @@
from typing import Optional
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
@ -32,12 +34,16 @@ class ServerHistory(HistoryTableABC):
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str: def name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.discord_id) guild = bot.get_guild(self.discord_id)
if guild is None:
return None
return None if guild is None else guild.name return None if guild is None else guild.name
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> str: def icon_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.discord_id) guild = bot.get_guild(self.discord_id)
if guild is None:
return None
return None if guild is None else guild.icon.url return None if guild is None else guild.icon.url

View File

@ -1,4 +1,5 @@
from datetime import datetime from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
@ -51,8 +52,10 @@ class ShortRoleName(TableABC):
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def role_name(self, bot: DiscordBotServiceABC) -> str: def role_name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self._server.discord_id) guild = bot.get_guild(self._server.discord_id)
if guild is None:
return None
return guild.get_role(self.role_id).name return guild.get_role(self.role_id).name
@property @property

View File

@ -1,3 +1,5 @@
from typing import Optional
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
@ -47,8 +49,10 @@ class ShortRoleNameHistory(HistoryTableABC):
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def role_name(self, bot: DiscordBotServiceABC) -> str: def role_name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self._server.discord_id) guild = bot.get_guild(self._server.discord_id)
if guild is None:
return None
return guild.get_role(self.role_id).name return guild.get_role(self.role_id).name
@property @property

View File

@ -4,3 +4,4 @@ from enum import Enum
class TeamMemberTypeEnum(Enum): class TeamMemberTypeEnum(Enum):
moderator = "Moderator" moderator = "Moderator"
admin = "Admin" admin = "Admin"
technician = "Technician"

View File

@ -2,6 +2,7 @@ from datetime import datetime, date
from typing import Optional from typing import Optional
from cpl_core.database import TableABC from cpl_core.database import TableABC
from cpl_core.database.context import DatabaseContextABC
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 cpl_query.extension import List from cpl_query.extension import List
@ -31,10 +32,17 @@ class User(TableABC):
self._birthday = birthday self._birthday = birthday
self._server = server self._server = server
self._activity = 0
TableABC.__init__(self) TableABC.__init__(self)
self._created_at = created_at if created_at is not None else self._created_at 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 self._modified_at = modified_at if modified_at is not None else self._modified_at
def reset(self):
self._xp = 0
self._message_count = 0
self._reaction_count = 0
@property @property
def id(self) -> int: def id(self) -> int:
return self._user_id return self._user_id
@ -45,15 +53,19 @@ class User(TableABC):
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str: def name(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.server.discord_id) guild = bot.get_guild(self.server.discord_id)
if guild is None:
return None
user = guild.get_member(self.discord_id) user = guild.get_member(self.discord_id)
return None if user is None else user.name return None if user is None else user.name
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def icon_url(self, bot: DiscordBotServiceABC) -> str: def icon_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.server.discord_id) guild = bot.get_guild(self.server.discord_id)
if guild is None:
return None
user = guild.get_member(self.discord_id) user = guild.get_member(self.discord_id)
return None if user is None else user.display_icon return None if user is None else user.display_icon
@ -92,14 +104,44 @@ class User(TableABC):
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def ontime(self, services: ServiceProviderABC) -> float: def ontime(self, services: ServiceProviderABC) -> float:
from bot_core.abc.client_utils_abc import ClientUtilsABC db: DatabaseContextABC = services.get_service(DatabaseContextABC)
result = db.select(
client_utils: ClientUtilsABC = services.get_service(ClientUtilsABC) f"""
return client_utils.get_ontime_for_user(self) SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(UserJoinedVoiceChannel.LeavedOn, UserJoinedVoiceChannel.JoinedOn)) / 3600),2)
FROM UserJoinedVoiceChannel
WHERE UserId = {self._user_id};
"""
)[0][0]
if result is None:
return 0
return float(result)
@property @property
@ServiceProviderABC.inject @ServiceProviderABC.inject
def level(self, services: ServiceProviderABC) -> Level: def game_ontime(self, services: ServiceProviderABC) -> float:
db: DatabaseContextABC = services.get_service(DatabaseContextABC)
result = db.select(
f"""
SELECT ROUND(SUM(TIME_TO_SEC(TIMEDIFF(UserJoinedGameServer.LeavedOn, UserJoinedGameServer.JoinedOn)) / 3600),2)
FROM UserJoinedGameServer
WHERE UserId = {self._user_id};
"""
)[0][0]
if result is None:
return 0
return float(result)
@property
def activity(self) -> int:
return self._activity
@activity.setter
def activity(self, value: int):
self._activity = value
@property
@ServiceProviderABC.inject
def level(self, services: ServiceProviderABC) -> Optional[Level]:
from modules.level.service.level_service import LevelService from modules.level.service.level_service import LevelService
levels: LevelService = services.get_service(LevelService) levels: LevelService = services.get_service(LevelService)
@ -135,6 +177,15 @@ class User(TableABC):
game_idents_repo: UserGameIdentRepositoryABC = services.get_service(UserGameIdentRepositoryABC) game_idents_repo: UserGameIdentRepositoryABC = services.get_service(UserGameIdentRepositoryABC)
return game_idents_repo.get_user_game_idents_by_user_id(self.id) return game_idents_repo.get_user_game_idents_by_user_id(self.id)
@property
@ServiceProviderABC.inject
def profile_picture_url(self, bot: DiscordBotServiceABC) -> Optional[str]:
guild = bot.get_guild(self.server.discord_id)
if guild is None:
return None
user = guild.get_member(self._discord_id)
return None if user is None or user.avatar is None else user.avatar.url
@staticmethod @staticmethod
def get_select_all_string() -> str: def get_select_all_string() -> str:
return str( return str(

View File

@ -67,15 +67,6 @@ class UserJoinedServer(TableABC):
""" """
) )
@staticmethod
def get_select_by_server_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `UserJoinedServers`
WHERE `ServerId` = {id};
"""
)
@staticmethod @staticmethod
def get_select_by_user_id_string(id: int) -> str: def get_select_by_user_id_string(id: int) -> str:
return str( return str(

View File

@ -59,6 +59,17 @@ class UserWarnings(TableABC):
""" """
) )
@staticmethod
def get_select_by_server_id_string(id: int) -> str:
return str(
f"""
SELECT `UserWarnings`.* FROM `UserWarnings`
INNER JOIN `Users`
ON `Users`.`UserId` = `UserWarnings`.`UserId`
WHERE `Users`.`ServerId` = {id};
"""
)
@staticmethod @staticmethod
def get_select_by_user_id_string(id: int) -> str: def get_select_by_user_id_string(id: int) -> str:
return str( return str(

View File

@ -0,0 +1,104 @@
# https://stackoverflow.com/questions/32658679/how-to-create-a-mysql-connection-pool-or-any-better-way-to-initialize-the-multip
import mysql.connector as sql
from cpl_core.database import DatabaseSettings
from cpl_core.utils import CredentialManager
class MySQLPool(object):
"""
create a pool when connect mysql, which will decrease the time spent in
request connection, create connection and close connection.
"""
def __init__(
self,
database_settings: DatabaseSettings,
pool_size=5,
):
res = {
"host": database_settings.host,
"port": database_settings.port,
"user": database_settings.user,
"password": CredentialManager.decrypt(database_settings.password),
"database": database_settings.database,
}
self.dbconfig = res
self.pool = self.create_pool(pool_name="MySqlPool", pool_size=pool_size)
def create_pool(self, pool_name="MySqlPool", pool_size=3):
"""
Create a connection pool, after created, the request of connecting
MySQL could get a connection from this pool instead of request to
create a connection.
:param pool_name: the name of pool, default is "mypool"
:param pool_size: the size of pool, default is 3
:return: connection pool
"""
pool = sql.pooling.MySQLConnectionPool(
pool_name=pool_name, pool_size=pool_size, pool_reset_session=True, **self.dbconfig
)
return pool
def close(self, conn, cursor):
"""
A method used to close connection of mysql.
:param conn:
:param cursor:
:return:
"""
cursor.close()
conn.close()
def execute(self, sql, args=None, commit=False):
"""
Execute a sql, it could be with args and with out args. The usage is
similar with execute() function in module pymysql.
:param sql: sql clause
:param args: args need by sql clause
:param commit: whether to commit
:return: if commit, return None, else, return result
"""
# get connection form connection pool instead of create one.
conn = self.pool.get_connection()
cursor = conn.cursor()
if args:
cursor.execute(sql, args)
else:
cursor.execute(sql)
if commit is True:
conn.commit()
self.close(conn, cursor)
return None
else:
res = cursor.fetchall()
self.close(conn, cursor)
return res
def executemany(self, sql, args, commit=False):
"""
Execute with many args. Similar with executemany() function in pymysql.
args should be a sequence.
:param sql: sql clause
:param args: args
:param commit: commit or not.
:return: if commit, return None, else, return result
"""
# get connection form connection pool instead of create one.
conn = self.pool.get_connection()
cursor = conn.cursor()
cursor.executemany(sql, args)
if commit is True:
conn.commit()
self.close(conn, cursor)
return None
else:
res = cursor.fetchall()
self.close(conn, cursor)
return res
def commit(self):
conn = self.pool.get_connection()
conn.commit()
cursor = conn.cursor()
self.close(conn, cursor)

View File

@ -0,0 +1,7 @@
ALTER TABLE CFG_Server
DROP COLUMN ResetMemberAfterRejoin;
ALTER TABLE CFG_ServerHistory
DROP COLUMN ResetMemberAfterRejoin;

View File

@ -0,0 +1,116 @@
ALTER TABLE CFG_Server
ADD ResetMemberAfterRejoin BOOLEAN NOT NULL DEFAULT FALSE AFTER GameOfferNotificationChatId;
ALTER TABLE CFG_ServerHistory
ADD ResetMemberAfterRejoin BOOLEAN NOT NULL DEFAULT FALSE AFTER GameOfferNotificationChatId;
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`,
`DefaultRoleId`,
`ShortRoleNameSetOnlyHighest`,
`GameOfferNotificationChatId`,
`ResetMemberAfterRejoin`,
`FeatureFlags`,
`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.DefaultRoleId,
OLD.ShortRoleNameSetOnlyHighest,
OLD.GameOfferNotificationChatId,
OLD.ResetMemberAfterRejoin,
OLD.FeatureFlags,
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`,
`DefaultRoleId`,
`ShortRoleNameSetOnlyHighest`,
`GameOfferNotificationChatId`,
`ResetMemberAfterRejoin`,
`ServerId`,
`FeatureFlags`,
`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.DefaultRoleId,
OLD.ShortRoleNameSetOnlyHighest,
OLD.GameOfferNotificationChatId,
OLD.ResetMemberAfterRejoin,
OLD.FeatureFlags,
OLD.ServerId,
TRUE,
OLD.LastModifiedAt,
CURRENT_TIMESTAMP(6));
END;;

View File

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

View File

@ -48,66 +48,60 @@ class AchievementRepositoryService(AchievementRepositoryABC):
) )
def get_achievements(self) -> List[Achievement]: def get_achievements(self) -> List[Achievement]:
achievements = List(Achievement)
self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_all_string()}")
results = self._context.select(Achievement.get_select_all_string())
for result in results:
self._logger.trace(__name__, f"Get user with id {result[0]}")
achievements.append(self._from_result(result))
return achievements return List(
Achievement,
[self._from_result(result) for result in self._context.select(Achievement.get_select_all_string())],
)
def get_achievement_by_id(self, id: int) -> Achievement: def get_achievement_by_id(self, id: int) -> Achievement:
self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_by_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_by_id_string(id)}")
result = self._context.select(Achievement.get_select_by_id_string(id))[0] return self._from_result(self._context.select(Achievement.get_select_by_id_string(id))[0])
return self._from_result(result)
def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]: def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]:
achievements = List(Achievement)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {Achievement.get_select_by_server_id_string(server_id)}", f"Send SQL command: {Achievement.get_select_by_server_id_string(server_id)}",
) )
results = self._context.select(Achievement.get_select_by_server_id_string(server_id))
for result in results:
self._logger.trace(__name__, f"Get user with id {result[0]}")
achievements.append(self._from_result(result))
return achievements return List(
Achievement,
[
self._from_result(result)
for result in self._context.select(Achievement.get_select_by_server_id_string(server_id))
],
)
def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]: def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]:
achievements = List(Achievement)
achievements_joins = List(UserGotAchievement)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {UserGotAchievement.get_select_by_user_id_string(user_id)}", f"Send SQL command: {UserGotAchievement.get_select_by_user_id_string(user_id)}",
) )
results = self._context.select(UserGotAchievement.get_select_by_user_id_string(user_id))
for result in results:
self._logger.trace(__name__, f"Got UserGotAchievement with id {result[0]}")
achievements_joins.append(self._join_from_result(result))
for achievements_join in achievements_joins: return List(
results = self._context.select(Achievement.get_select_by_id_string(achievements_join.achievement.id)) UserGotAchievement,
for result in results: [
self._logger.trace(__name__, f"Got Achievement with id {result[0]}") self._join_from_result(result).achievement
achievements.append(self._from_result(result)) for result in self._context.select(UserGotAchievement.get_select_by_user_id_string(user_id))
],
return achievements )
def get_user_got_achievements_by_achievement_id(self, achievement_id: int) -> List[Achievement]: def get_user_got_achievements_by_achievement_id(self, achievement_id: int) -> List[Achievement]:
achievements_joins = List(UserGotAchievement)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {UserGotAchievement.get_select_by_achievement_id_string(achievement_id)}", f"Send SQL command: {UserGotAchievement.get_select_by_achievement_id_string(achievement_id)}",
) )
results = self._context.select(UserGotAchievement.get_select_by_achievement_id_string(achievement_id))
for result in results:
self._logger.trace(__name__, f"Got UserGotAchievement with id {result[0]}")
achievements_joins.append(self._join_from_result(result))
return achievements_joins return List(
UserGotAchievement,
[
self._join_from_result(result)
for result in self._context.select(
UserGotAchievement.get_select_by_achievement_id_string(achievement_id)
)
],
)
def add_achievement(self, achievement: Achievement): def add_achievement(self, achievement: Achievement):
self._logger.trace(__name__, f"Send SQL command: {achievement.insert_string}") self._logger.trace(__name__, f"Send SQL command: {achievement.insert_string}")

View File

@ -44,13 +44,12 @@ class ApiKeyRepositoryService(ApiKeyRepositoryABC):
return api_key return api_key
def get_api_keys(self) -> List[ApiKey]: def get_api_keys(self) -> List[ApiKey]:
api_keys = List(ApiKey)
self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_all_string()}")
results = self._context.select(ApiKey.get_select_all_string())
for result in results:
api_keys.append(self._api_key_from_result(result))
return api_keys return List(
ApiKey,
[self._api_key_from_result(result) for result in self._context.select(ApiKey.get_select_all_string())],
)
def get_api_key(self, identifier: str, key: str) -> ApiKey: def get_api_key(self, identifier: str, key: str) -> ApiKey:
self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_string(identifier, key)}") self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_string(identifier, key)}")

View File

@ -64,23 +64,16 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
__name__, __name__,
f"Send SQL command: {auth_user.get_select_user_id_from_relations()}", f"Send SQL command: {auth_user.get_select_user_id_from_relations()}",
) )
relation_ids = List(int)
results = self._context.select(auth_user.get_select_user_id_from_relations())
for result in results:
self._logger.trace(__name__, f"Got auth user relation with id {result[0]}")
relation_ids.append(result[0])
return relation_ids return List(int, [result[0] for result in self._context.select(auth_user.get_select_user_id_from_relations())])
def get_all_auth_users(self) -> List[AuthUser]: def get_all_auth_users(self) -> List[AuthUser]:
users = List(AuthUser)
self._logger.trace(__name__, f"Send SQL command: {AuthUser.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {AuthUser.get_select_all_string()}")
results = self._context.select(AuthUser.get_select_all_string())
for result in results:
self._logger.trace(__name__, f"Get auth user with id {result[0]}")
users.append(self._user_from_result(result))
return users return List(
AuthUser,
[self._user_from_result(result) for result in self._context.select(AuthUser.get_select_all_string())],
)
def get_filtered_auth_users(self, criteria: AuthUserSelectCriteria) -> FilteredResult: def get_filtered_auth_users(self, criteria: AuthUserSelectCriteria) -> FilteredResult:
users = self.get_all_auth_users() users = self.get_all_auth_users()
@ -129,8 +122,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
def get_auth_user_by_email(self, email: str) -> AuthUser: def get_auth_user_by_email(self, email: str) -> AuthUser:
self._logger.trace(__name__, f"Send SQL command: {AuthUser.get_select_by_email_string(email)}") self._logger.trace(__name__, f"Send SQL command: {AuthUser.get_select_by_email_string(email)}")
result = self._context.select(AuthUser.get_select_by_email_string(email))[0] return self._user_from_result(self._context.select(AuthUser.get_select_by_email_string(email))[0])
return self._user_from_result(result)
def find_auth_user_by_email(self, email: str) -> Optional[AuthUser]: def find_auth_user_by_email(self, email: str) -> Optional[AuthUser]:
self._logger.trace(__name__, f"Send SQL command: {AuthUser.get_select_by_email_string(email)}") self._logger.trace(__name__, f"Send SQL command: {AuthUser.get_select_by_email_string(email)}")
@ -138,9 +130,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
if result is None or len(result) == 0: if result is None or len(result) == 0:
return None return None
result = result[0] return self._user_from_result(result[0])
return self._user_from_result(result)
def find_auth_user_by_confirmation_id(self, id: str) -> Optional[AuthUser]: def find_auth_user_by_confirmation_id(self, id: str) -> Optional[AuthUser]:
self._logger.trace( self._logger.trace(
@ -151,9 +141,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
if result is None or len(result) == 0: if result is None or len(result) == 0:
return None return None
result = result[0] return self._user_from_result(result[0])
return self._user_from_result(result)
def find_auth_user_by_forgot_password_id(self, id: str) -> Optional[AuthUser]: def find_auth_user_by_forgot_password_id(self, id: str) -> Optional[AuthUser]:
self._logger.trace( self._logger.trace(
@ -164,9 +152,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
if result is None or len(result) == 0: if result is None or len(result) == 0:
return None return None
result = result[0] return self._user_from_result(result[0])
return self._user_from_result(result)
def add_auth_user(self, user: AuthUser): def add_auth_user(self, user: AuthUser):
self._logger.trace(__name__, f"Send SQL command: {user.insert_string}") self._logger.trace(__name__, f"Send SQL command: {user.insert_string}")
@ -178,6 +164,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
def delete_auth_user(self, user: AuthUser): def delete_auth_user(self, user: AuthUser):
self._logger.trace(__name__, f"Send SQL command: {user.delete_string}") self._logger.trace(__name__, f"Send SQL command: {user.delete_string}")
self._context.cursor.execute(user.delete_relations_string)
self._context.cursor.execute(user.delete_string) self._context.cursor.execute(user.delete_string)
def add_auth_user_user_rel(self, rel: AuthUserUsersRelation): def add_auth_user_user_rel(self, rel: AuthUserUsersRelation):

View File

@ -23,27 +23,7 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
AutoRoleRepositoryABC.__init__(self) AutoRoleRepositoryABC.__init__(self)
def get_auto_roles(self) -> List[AutoRole]: def _from_result(self, result: tuple) -> AutoRole:
auto_roles = List(AutoRole)
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_all_string()}")
results = self._context.select(AutoRole.get_select_all_string())
for result in results:
auto_roles.append(
AutoRole(
self._servers.get_server_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
)
return auto_roles
def get_auto_role_by_id(self, id: int) -> AutoRole:
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}")
result = self._context.select(AutoRole.get_select_by_id_string(id))[0]
return AutoRole( return AutoRole(
self._servers.get_server_by_id(result[1]), self._servers.get_server_by_id(result[1]),
result[2], result[2],
@ -53,55 +33,37 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
id=result[0], id=result[0],
) )
def get_auto_roles(self) -> List[AutoRole]:
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_all_string()}")
return List(
AutoRole, [self._from_result(result) for result in self._context.select(AutoRole.get_select_all_string())]
)
def get_auto_role_by_id(self, id: int) -> AutoRole:
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}")
return self._from_result(self._context.select(AutoRole.get_select_by_id_string(id))[0])
def find_auto_role_by_id(self, id: int) -> Optional[AutoRole]: def find_auto_role_by_id(self, id: int) -> Optional[AutoRole]:
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}")
result = self._context.select(AutoRole.get_select_by_id_string(id)) result = self._context.select(AutoRole.get_select_by_id_string(id))
if result is None or len(result) == 0: if result is None or len(result) == 0:
return None return None
result = result[0] return self._from_result(result[0])
return AutoRole(
self._servers.get_server_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
def get_auto_roles_by_server_id(self, id: int) -> List[AutoRole]: def get_auto_roles_by_server_id(self, id: int) -> List[AutoRole]:
self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_server_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_server_id_string(id)}")
auto_roles = List(AutoRole) return List(
results = self._context.select(AutoRole.get_select_by_server_id_string(id)) AutoRole,
for result in results: [self._from_result(result) for result in self._context.select(AutoRole.get_select_by_server_id_string(id))],
auto_roles.append( )
AutoRole(
self._servers.get_server_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
)
return auto_roles
def get_auto_role_by_message_id(self, id: int) -> AutoRole: def get_auto_role_by_message_id(self, id: int) -> AutoRole:
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {AutoRole.get_select_by_message_id_string(id)}", f"Send SQL command: {AutoRole.get_select_by_message_id_string(id)}",
) )
result = self._context.select(AutoRole.get_select_by_message_id_string(id))[0] return self._from_result(self._context.select(AutoRole.get_select_by_message_id_string(id))[0])
return AutoRole(
self._servers.get_server_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
def find_auto_role_by_message_id(self, id: int) -> Optional[AutoRole]: def find_auto_role_by_message_id(self, id: int) -> Optional[AutoRole]:
self._logger.trace( self._logger.trace(
@ -112,16 +74,7 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
if result is None or len(result) == 0: if result is None or len(result) == 0:
return None return None
result = result[0] return self._from_result(result[0])
return AutoRole(
self._servers.get_server_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
def add_auto_role(self, auto_role: AutoRole): def add_auto_role(self, auto_role: AutoRole):
self._logger.trace(__name__, f"Send SQL command: {auto_role.insert_string}") self._logger.trace(__name__, f"Send SQL command: {auto_role.insert_string}")
@ -135,27 +88,7 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
self._logger.trace(__name__, f"Send SQL command: {auto_role.delete_string}") self._logger.trace(__name__, f"Send SQL command: {auto_role.delete_string}")
self._context.cursor.execute(auto_role.delete_string) self._context.cursor.execute(auto_role.delete_string)
def get_auto_role_rules(self) -> List[AutoRoleRule]: def _rule_from_result(self, result: tuple) -> AutoRoleRule:
auto_role_rules = List(AutoRoleRule)
self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_all_string()}")
results = self._context.select(AutoRoleRule.get_select_all_string())
for result in results:
auto_role_rules.append(
AutoRoleRule(
self.get_auto_role_by_id(result[1]),
result[2],
result[3],
result[4],
result[5],
id=result[0],
)
)
return auto_role_rules
def get_auto_role_rule_by_id(self, id: int) -> AutoRoleRule:
self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_by_id_string(id)}")
result = self._context.select(AutoRoleRule.get_select_by_id_string(id))[0]
return AutoRoleRule( return AutoRoleRule(
self.get_auto_role_by_id(result[1]), self.get_auto_role_by_id(result[1]),
result[2], result[2],
@ -165,26 +98,29 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC):
id=result[0], id=result[0],
) )
def get_auto_role_rules(self) -> List[AutoRoleRule]:
self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_all_string()}")
return List(
AutoRoleRule,
[self._rule_from_result(result) for result in self._context.select(AutoRoleRule.get_select_all_string())],
)
def get_auto_role_rule_by_id(self, id: int) -> AutoRoleRule:
self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_by_id_string(id)}")
return self._rule_from_result(self._context.select(AutoRoleRule.get_select_by_id_string(id))[0])
def get_auto_role_rules_by_auto_role_id(self, id: int) -> List[AutoRoleRule]: def get_auto_role_rules_by_auto_role_id(self, id: int) -> List[AutoRoleRule]:
auto_role_rules = List(AutoRoleRule)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {AutoRoleRule.get_select_by_auto_role_id_string(id)}", f"Send SQL command: {AutoRoleRule.get_select_by_auto_role_id_string(id)}",
) )
results = self._context.select(AutoRoleRule.get_select_by_auto_role_id_string(id)) return List(
for result in results: AutoRoleRule,
auto_role_rules.append( [
AutoRoleRule( self._rule_from_result(result)
self.get_auto_role_by_id(result[1]), for result in self._context.select(AutoRoleRule.get_select_by_auto_role_id_string(id))
result[2], ],
result[3], )
result[4],
result[5],
id=result[0],
)
)
return auto_role_rules
def add_auto_role_rule(self, auto_role_rule: AutoRoleRule): def add_auto_role_rule(self, auto_role_rule: AutoRoleRule):
self._logger.trace(__name__, f"Send SQL command: {auto_role_rule.insert_string}") self._logger.trace(__name__, f"Send SQL command: {auto_role_rule.insert_string}")

View File

@ -23,32 +23,7 @@ class ClientRepositoryService(ClientRepositoryABC):
ClientRepositoryABC.__init__(self) ClientRepositoryABC.__init__(self)
def get_clients(self) -> List[Client]: def _from_result(self, result: tuple) -> Client:
clients = List(Client)
self._logger.trace(__name__, f"Send SQL command: {Client.get_select_all_string()}")
results = self._context.select(Client.get_select_all_string())
for result in results:
self._logger.trace(__name__, f"Get client with id {result[0]}")
clients.append(
Client(
result[1],
result[2],
result[3],
result[4],
result[5],
result[6],
self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0],
)
)
return clients
def get_client_by_id(self, client_id: int) -> Client:
self._logger.trace(__name__, f"Send SQL command: {Client.get_select_by_id_string(client_id)}")
result = self._context.select(Client.get_select_by_id_string(client_id))
return Client( return Client(
result[1], result[1],
result[2], result[2],
@ -62,49 +37,37 @@ class ClientRepositoryService(ClientRepositoryABC):
id=result[0], id=result[0],
) )
def get_clients(self) -> List[Client]:
self._logger.trace(__name__, f"Send SQL command: {Client.get_select_all_string()}")
return List(
Client, [self._from_result(result) for result in self._context.select(Client.get_select_all_string())]
)
def get_client_by_id(self, client_id: int) -> Client:
self._logger.trace(__name__, f"Send SQL command: {Client.get_select_by_id_string(client_id)}")
return self._from_result(self._context.select(Client.get_select_by_id_string(client_id))[0])
def get_clients_by_server_id(self, server_id: int) -> List[Client]: def get_clients_by_server_id(self, server_id: int) -> List[Client]:
clients = List(Client)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {Client.get_select_by_server_id_string(server_id)}", f"Send SQL command: {Client.get_select_by_server_id_string(server_id)}",
) )
results = self._context.select(Client.get_select_by_server_id_string(server_id))
for result in results:
clients.append(
Client(
result[1],
result[2],
result[3],
result[4],
result[5],
result[6],
self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0],
)
)
return clients return List(
Client,
[
self._from_result(result)
for result in self._context.select(Client.get_select_by_server_id_string(server_id))
],
)
def get_client_by_discord_id(self, discord_id: int) -> Client: def get_client_by_discord_id(self, discord_id: int) -> Client:
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {Client.get_select_by_discord_id_string(discord_id)}", f"Send SQL command: {Client.get_select_by_discord_id_string(discord_id)}",
) )
result = self._context.select(Client.get_select_by_discord_id_string(discord_id))[0] return self._from_result(self._context.select(Client.get_select_by_discord_id_string(discord_id))[0])
return Client(
result[1],
result[2],
result[3],
result[4],
result[5],
result[6],
self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0],
)
def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]:
self._logger.trace( self._logger.trace(
@ -115,20 +78,7 @@ class ClientRepositoryService(ClientRepositoryABC):
if result is None or len(result) == 0: if result is None or len(result) == 0:
return None return None
result = result[0] return self._from_result(result[0])
return Client(
result[1],
result[2],
result[3],
result[4],
result[5],
result[6],
self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0],
)
def find_client_by_server_id(self, discord_id: int) -> Optional[Client]: def find_client_by_server_id(self, discord_id: int) -> Optional[Client]:
self._logger.trace( self._logger.trace(
@ -139,20 +89,7 @@ class ClientRepositoryService(ClientRepositoryABC):
if result is None or len(result) == 0: if result is None or len(result) == 0:
return None return None
result = result[0] return self._from_result(result[0])
return Client(
result[1],
result[2],
result[3],
result[4],
result[5],
result[6],
self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0],
)
def find_client_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[Client]: def find_client_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[Client]:
self._logger.trace( self._logger.trace(
@ -163,20 +100,7 @@ class ClientRepositoryService(ClientRepositoryABC):
if result is None or len(result) == 0: if result is None or len(result) == 0:
return None return None
result = result[0] return self._from_result(result[0])
return Client(
result[1],
result[2],
result[3],
result[4],
result[5],
result[6],
self._servers.get_server_by_id(result[7]),
result[8],
result[9],
id=result[0],
)
def add_client(self, client: Client): def add_client(self, client: Client):
self._logger.trace(__name__, f"Send SQL command: {client.insert_string}") self._logger.trace(__name__, f"Send SQL command: {client.insert_string}")

View File

@ -35,49 +35,49 @@ class GameServerRepositoryService(GameServerRepositoryABC):
) )
def get_game_servers(self) -> List[GameServer]: def get_game_servers(self) -> List[GameServer]:
game_servers = List(GameServer)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {GameServer.get_select_all_string()}", f"Send SQL command: {GameServer.get_select_all_string()}",
) )
results = self._context.select(GameServer.get_select_all_string())
for result in results:
self._logger.trace(__name__, f"Get user-joined-game-server with id {result[0]}")
game_servers.append(self._from_result(result))
return game_servers return List(
GameServer,
[self._from_result(result) for result in self._context.select(GameServer.get_select_all_string())],
)
def get_game_servers_by_server_id(self, id: int) -> List[GameServer]: def get_game_servers_by_server_id(self, id: int) -> List[GameServer]:
game_servers = List(GameServer)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {GameServer.get_select_by_server_id_string(id)}", f"Send SQL command: {GameServer.get_select_by_server_id_string(id)}",
) )
results = self._context.select(GameServer.get_select_by_server_id_string(id))
for result in results:
self._logger.trace(__name__, f"Get user-joined-game-server with id {result[0]}")
game_servers.append(self._from_result(result))
return game_servers return List(
GameServer,
[
self._from_result(result)
for result in self._context.select(GameServer.get_select_by_server_id_string(id))
],
)
def get_game_server_by_id(self, id: int) -> GameServer: def get_game_server_by_id(self, id: int) -> GameServer:
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {GameServer.get_select_by_id_string(id)}", f"Send SQL command: {GameServer.get_select_by_id_string(id)}",
) )
result = self._context.select(GameServer.get_select_by_id_string(id))[0] return self._from_result(self._context.select(GameServer.get_select_by_id_string(id))[0])
return self._from_result(result)
def get_game_servers_by_api_key_id(self, id: int) -> List[GameServer]: def get_game_servers_by_api_key_id(self, id: int) -> List[GameServer]:
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {GameServer.get_select_by_api_key_id_string(id)}", f"Send SQL command: {GameServer.get_select_by_api_key_id_string(id)}",
) )
game_servers = List(GameServer) return List(
results = self._context.select(GameServer.get_select_by_api_key_id_string(id)) GameServer,
for result in results: [
game_servers.append(self._from_result(result)) self._from_result(result)
return game_servers for result in self._context.select(GameServer.get_select_by_api_key_id_string(id))
],
)
def add_game_server(self, game_server: GameServer): def add_game_server(self, game_server: GameServer):
self._logger.trace(__name__, f"Send SQL command: {game_server.insert_string}") self._logger.trace(__name__, f"Send SQL command: {game_server.insert_string}")

View File

@ -4,8 +4,8 @@ from cpl_core.database.context import DatabaseContextABC
from cpl_query.extension import List from cpl_query.extension import List
from bot_core.logging.database_logger import DatabaseLogger from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.abc.level_repository_abc import LevelRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.model.level import Level from bot_data.model.level import Level
@ -37,24 +37,21 @@ class LevelRepositoryService(LevelRepositoryABC):
int(self._get_value_from_result(sql_result[3])), # min xp int(self._get_value_from_result(sql_result[3])), # min xp
int(self._get_value_from_result(sql_result[4])), # permissions int(self._get_value_from_result(sql_result[4])), # permissions
self._servers.get_server_by_id(sql_result[5]), # server self._servers.get_server_by_id(sql_result[5]), # server
sql_result[6], # created_at
sql_result[7], # modified_at
id=self._get_value_from_result(sql_result[0]), # id id=self._get_value_from_result(sql_result[0]), # id
) )
def get_levels(self) -> List[Level]: def get_levels(self) -> List[Level]:
levels = List(Level)
self._logger.trace(__name__, f"Send SQL command: {Level.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {Level.get_select_all_string()}")
results = self._context.select(Level.get_select_all_string()) return List(
for result in results: Level, [self._level_from_result(result) for result in self._context.select(Level.get_select_all_string())]
self._logger.trace(__name__, f"Get level with id {result[0]}") )
levels.append(self._level_from_result(result))
return levels
def get_level_by_id(self, id: int) -> Level: def get_level_by_id(self, id: int) -> Level:
self._logger.trace(__name__, f"Send SQL command: {Level.get_select_by_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {Level.get_select_by_id_string(id)}")
result = self._context.select(Level.get_select_by_id_string(id))[0]
return self._level_from_result(result) return self._level_from_result(self._context.select(Level.get_select_by_id_string(id))[0])
def find_level_by_id(self, id: int) -> Optional[Level]: def find_level_by_id(self, id: int) -> Optional[Level]:
self._logger.trace(__name__, f"Send SQL command: {Level.get_select_by_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {Level.get_select_by_id_string(id)}")
@ -65,21 +62,19 @@ class LevelRepositoryService(LevelRepositoryABC):
return self._level_from_result(result[0]) return self._level_from_result(result[0])
def get_levels_by_server_id(self, server_id: int) -> List[Level]: def get_levels_by_server_id(self, server_id: int) -> List[Level]:
levels = List(Level)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {Level.get_select_by_server_id_string(server_id)}", f"Send SQL command: {Level.get_select_by_server_id_string(server_id)}",
) )
results = self._context.select(Level.get_select_by_server_id_string(server_id)) return List(
Level,
for result in results: [
self._logger.trace(__name__, f"Get level with id {result[0]}") self._level_from_result(result)
levels.append(self._level_from_result(result)) for result in self._context.select(Level.get_select_by_server_id_string(server_id))
],
return levels )
def find_levels_by_server_id(self, server_id: int) -> Optional[List[Level]]: def find_levels_by_server_id(self, server_id: int) -> Optional[List[Level]]:
levels = List(Level)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {Level.get_select_by_server_id_string(server_id)}", f"Send SQL command: {Level.get_select_by_server_id_string(server_id)}",
@ -88,11 +83,10 @@ class LevelRepositoryService(LevelRepositoryABC):
if results is None or len(results) == 0: if results is None or len(results) == 0:
return None return None
for result in results: return List(
self._logger.trace(__name__, f"Get level with id {result[0]}") Level,
levels.append(self._level_from_result(result)) [self._level_from_result(result) for result in results],
)
return levels
def add_level(self, level: Level): def add_level(self, level: Level):
self._logger.trace(__name__, f"Send SQL command: {level.insert_string}") self._logger.trace(__name__, f"Send SQL command: {level.insert_string}")

View File

@ -1,13 +1,13 @@
import glob import glob
import os import os
from cpl_core.database.context import DatabaseContextABC
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
from cpl_query.extension import List from cpl_query.extension import List
from packaging import version from packaging import version
import bot import bot
from bot_core.logging.database_logger import DatabaseLogger from bot_core.logging.database_logger import DatabaseLogger
from bot_data.db_context import DBContext
from bot_data.model.migration import Migration from bot_data.model.migration import Migration
from bot_data.model.migration_history import MigrationHistory from bot_data.model.migration_history import MigrationHistory
@ -17,13 +17,12 @@ class MigrationService:
self, self,
logger: DatabaseLogger, logger: DatabaseLogger,
services: ServiceProviderABC, services: ServiceProviderABC,
db: DatabaseContextABC, db: DBContext,
): ):
self._logger = logger self._logger = logger
self._services = services self._services = services
self._db = db self._db = db
self._cursor = db.cursor
def _get_migration_history(self) -> List[MigrationHistory]: def _get_migration_history(self) -> List[MigrationHistory]:
results = self._db.select( results = self._db.select(
@ -42,7 +41,7 @@ class MigrationService:
return return
self._logger.debug(__name__, f"Migrate new migration {migration.migration_id} to old method") self._logger.debug(__name__, f"Migrate new migration {migration.migration_id} to old method")
self._cursor.execute(migration.change_id_string(f"{migration.migration_id}Migration")) self._db.execute(migration.change_id_string(f"{migration.migration_id}Migration"))
self._db.save_changes() self._db.save_changes()
def _migration_migrations_to_new(self, migration: MigrationHistory): def _migration_migrations_to_new(self, migration: MigrationHistory):
@ -50,12 +49,11 @@ class MigrationService:
return return
self._logger.debug(__name__, f"Migrate old migration {migration.migration_id} to new method") self._logger.debug(__name__, f"Migrate old migration {migration.migration_id} to new method")
self._cursor.execute(migration.change_id_string(migration.migration_id.replace("Migration", ""))) self._db.execute(migration.change_id_string(migration.migration_id.replace("Migration", "")))
self._db.save_changes() self._db.save_changes()
def _migrate_from_old_to_new(self): def _migrate_from_old_to_new(self):
self._cursor.execute("SHOW TABLES LIKE 'MigrationHistory'") result = self._db.select("SHOW TABLES LIKE 'MigrationHistory'")
result = self._cursor.fetchone()
if not result: if not result:
return return
@ -120,8 +118,7 @@ class MigrationService:
active_statement = "" active_statement = ""
try: try:
# check if table exists # check if table exists
self._cursor.execute("SHOW TABLES LIKE 'MigrationHistory'") result = self._db.select("SHOW TABLES LIKE 'MigrationHistory'")
result = self._cursor.fetchone()
if result: if result:
# there is a table named "tableName" # there is a table named "tableName"
self._logger.trace( self._logger.trace(
@ -142,9 +139,9 @@ class MigrationService:
if statement in ["", "\n"]: if statement in ["", "\n"]:
continue continue
active_statement = statement active_statement = statement
self._cursor.execute(statement + ";") self._db.execute(statement + ";")
self._cursor.execute( self._db.execute(
MigrationHistory(migration.name).insert_string MigrationHistory(migration.name).insert_string
if upgrade if upgrade
else MigrationHistory(migration.name).delete_string else MigrationHistory(migration.name).delete_string

View File

@ -5,8 +5,8 @@ from cpl_query.extension import List
from discord import EntityType from discord import EntityType
from bot_core.logging.database_logger import DatabaseLogger from bot_core.logging.database_logger import DatabaseLogger
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.abc.scheduled_event_repository_abc import ScheduledEventRepositoryABC from bot_data.abc.scheduled_event_repository_abc import ScheduledEventRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from bot_data.model.scheduled_event import ScheduledEvent from bot_data.model.scheduled_event import ScheduledEvent
from bot_data.model.scheduled_event_interval_enum import ScheduledEventIntervalEnum from bot_data.model.scheduled_event_interval_enum import ScheduledEventIntervalEnum
@ -49,34 +49,34 @@ class ScheduledEventRepositoryService(ScheduledEventRepositoryABC):
) )
def get_scheduled_events(self) -> List[ScheduledEvent]: def get_scheduled_events(self) -> List[ScheduledEvent]:
scheduled_events = List(ScheduledEvent)
self._logger.trace(__name__, f"Send SQL command: {ScheduledEvent.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {ScheduledEvent.get_select_all_string()}")
results = self._context.select(ScheduledEvent.get_select_all_string())
for result in results:
self._logger.trace(__name__, f"Get scheduled_event with id {result[0]}")
scheduled_events.append(self._scheduled_event_from_result(result))
return scheduled_events return List(
ScheduledEvent,
[
self._scheduled_event_from_result(result)
for result in self._context.select(ScheduledEvent.get_select_all_string())
],
)
def get_scheduled_event_by_id(self, id: int) -> ScheduledEvent: def get_scheduled_event_by_id(self, id: int) -> ScheduledEvent:
self._logger.trace(__name__, f"Send SQL command: {ScheduledEvent.get_select_by_id_string(id)}") self._logger.trace(__name__, f"Send SQL command: {ScheduledEvent.get_select_by_id_string(id)}")
result = self._context.select(ScheduledEvent.get_select_by_id_string(id))[0]
return self._scheduled_event_from_result(result) return self._scheduled_event_from_result(self._context.select(ScheduledEvent.get_select_by_id_string(id))[0])
def get_scheduled_events_by_server_id(self, server_id: int) -> List[ScheduledEvent]: def get_scheduled_events_by_server_id(self, server_id: int) -> List[ScheduledEvent]:
scheduled_events = List(ScheduledEvent)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {ScheduledEvent.get_select_by_server_id_string(server_id)}", f"Send SQL command: {ScheduledEvent.get_select_by_server_id_string(server_id)}",
) )
results = self._context.select(ScheduledEvent.get_select_by_server_id_string(server_id))
for result in results: return List(
self._logger.trace(__name__, f"Get scheduled_event with id {result[0]}") ScheduledEvent,
scheduled_events.append(self._scheduled_event_from_result(result)) [
self._scheduled_event_from_result(result)
return scheduled_events for result in self._context.select(ScheduledEvent.get_select_by_server_id_string(server_id))
],
)
def add_scheduled_event(self, scheduled_event: ScheduledEvent): def add_scheduled_event(self, scheduled_event: ScheduledEvent):
self._logger.trace(__name__, f"Send SQL command: {scheduled_event.insert_string}") self._logger.trace(__name__, f"Send SQL command: {scheduled_event.insert_string}")

View File

@ -26,15 +26,14 @@ class ServerConfigRepositoryService(ServerConfigRepositoryABC):
self._servers = servers self._servers = servers
def _get_team_role_ids(self, server_id: int) -> List[ServerTeamRoleIdsConfig]: def _get_team_role_ids(self, server_id: int) -> List[ServerTeamRoleIdsConfig]:
ids = List(ServerTeamRoleIdsConfig)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {ServerTeamRoleIdsConfig.get_select_by_server_id_string(server_id)}", f"Send SQL command: {ServerTeamRoleIdsConfig.get_select_by_server_id_string(server_id)}",
) )
results = self._context.select(ServerTeamRoleIdsConfig.get_select_by_server_id_string(server_id))
for result in results: return List(
self._logger.trace(__name__, f"Got ServerTeamRoleIdsConfig with id {result[0]}") ServerTeamRoleIdsConfig,
ids.append( [
ServerTeamRoleIdsConfig( ServerTeamRoleIdsConfig(
result[1], result[1],
TeamMemberTypeEnum(result[2]), TeamMemberTypeEnum(result[2]),
@ -43,22 +42,23 @@ class ServerConfigRepositoryService(ServerConfigRepositoryABC):
result[5], result[5],
id=result[0], id=result[0],
) )
) for result in self._context.select(ServerTeamRoleIdsConfig.get_select_by_server_id_string(server_id))
],
return ids )
def _get_afk_channel_ids(self, server_id: int) -> List[int]: def _get_afk_channel_ids(self, server_id: int) -> List[int]:
urls = List(int)
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {ServerAFKChannelIdsConfig.get_select_by_server_id_string(server_id)}", f"Send SQL command: {ServerAFKChannelIdsConfig.get_select_by_server_id_string(server_id)}",
) )
results = self._context.select(ServerAFKChannelIdsConfig.get_select_by_server_id_string(server_id))
for result in results:
self._logger.trace(__name__, f"Got ServerAFKChannelIdsConfig with id {result[0]}")
urls.append(result[1])
return urls return List(
int,
[
result[1]
for result in self._context.select(ServerAFKChannelIdsConfig.get_select_by_server_id_string(server_id))
],
)
def _from_result(self, result: tuple) -> ServerConfig: def _from_result(self, result: tuple) -> ServerConfig:
return ServerConfig( return ServerConfig(
@ -79,12 +79,13 @@ class ServerConfigRepositoryService(ServerConfigRepositoryABC):
result[15], result[15],
result[16], result[16],
result[17], result[17],
json.loads(result[18]), result[18],
self._servers.get_server_by_id(result[19]), json.loads(result[19]),
self._get_afk_channel_ids(result[19]), self._servers.get_server_by_id(result[20]),
self._get_team_role_ids(result[19]), self._get_afk_channel_ids(result[20]),
result[20], self._get_team_role_ids(result[20]),
result[21], result[21],
result[22],
id=result[0], id=result[0],
) )
@ -102,18 +103,14 @@ class ServerConfigRepositoryService(ServerConfigRepositoryABC):
__name__, __name__,
f"Send SQL command: {ServerConfig.get_select_by_server_id_string(server_id)}", f"Send SQL command: {ServerConfig.get_select_by_server_id_string(server_id)}",
) )
result = self._context.select(ServerConfig.get_select_by_server_id_string(server_id))[0] return self._from_result(self._context.select(ServerConfig.get_select_by_server_id_string(server_id))[0])
return self._from_result(result)
def get_server_config_by_id(self, config_id: int) -> ServerConfig: def get_server_config_by_id(self, config_id: int) -> ServerConfig:
self._logger.trace( self._logger.trace(
__name__, __name__,
f"Send SQL command: {ServerConfig.get_select_by_id_string(config_id)}", f"Send SQL command: {ServerConfig.get_select_by_id_string(config_id)}",
) )
result = self._context.select(ServerConfig.get_select_by_id_string(config_id))[0] return self._from_result(self._context.select(ServerConfig.get_select_by_id_string(config_id))[0])
return self._from_result(result)
def add_server_config(self, server_config: ServerConfig): def add_server_config(self, server_config: ServerConfig):
self._logger.trace(__name__, f"Send SQL command: {server_config.insert_string}") self._logger.trace(__name__, f"Send SQL command: {server_config.insert_string}")

View File

@ -25,12 +25,15 @@ class ServerRepositoryService(ServerRepositoryABC):
ServerRepositoryABC.__init__(self) ServerRepositoryABC.__init__(self)
def get_servers(self) -> List[Server]: def get_servers(self) -> List[Server]:
servers = List(Server)
self._logger.trace(__name__, f"Send SQL command: {Server.get_select_all_string()}") self._logger.trace(__name__, f"Send SQL command: {Server.get_select_all_string()}")
results = self._context.select(Server.get_select_all_string())
for result in results:
servers.append(Server(result[1], result[2], result[3], id=result[0]))
servers = List(
Server,
[
Server(result[1], result[2], result[3], id=result[0])
for result in self._context.select(Server.get_select_all_string())
],
)
self._cache.add_servers(servers) self._cache.add_servers(servers)
return servers return servers
@ -96,9 +99,7 @@ class ServerRepositoryService(ServerRepositoryABC):
if result is None or len(result) == 0: if result is None or len(result) == 0:
return None return None
result = result[0] return Server(result[0][1], result[0][2], result[0][3], id=result[0][0])
return Server(result[1], result[2], result[3], id=result[0])
def add_server(self, server: Server): def add_server(self, server: Server):
self._logger.trace(__name__, f"Send SQL command: {server.insert_string}") self._logger.trace(__name__, f"Send SQL command: {server.insert_string}")

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