125 Commits

Author SHA1 Message Date
aa0bed80ce fixed typo
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 2m42s
Deploy prod on push / build-web (push) Successful in 1m54s
Deploy prod on push / deploy (push) Successful in 20s
2025-01-23 21:48:57 +01:00
d0b4a390f0 Handle realm names better
All checks were successful
Deploy prod on push / pre-build (push) Successful in 2s
Deploy prod on push / build-bot (push) Successful in 2m34s
Deploy prod on push / build-web (push) Successful in 1m25s
Deploy prod on push / deploy (push) Successful in 20s
2025-01-10 15:34:21 +01:00
65d04785b1 Merge pull request 'staging' (#483) 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 1m30s
Deploy prod on push / build-web (push) Successful in 1m29s
Deploy prod on push / deploy (push) Successful in 19s
Reviewed-on: #483
2025-01-10 15:05:37 +01:00
614a60bd2b Fixed project structure
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 2m50s
Deploy staging on push / build-web (push) Successful in 1m39s
Deploy staging on push / deploy (push) Successful in 30s
2025-01-10 14:59:58 +01:00
e5b03e7219 Added project structure
Some checks failed
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-web (push) Has been cancelled
Deploy staging on push / build-bot (push) Failing after 1m23s
Deploy staging on push / deploy (push) Has been skipped
2025-01-10 14:35:39 +01:00
09c8f41b05 Removed docker build
All checks were successful
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Successful in 2m55s
Deploy staging on push / build-web (push) Successful in 1m51s
Deploy staging on push / deploy (push) Successful in 24s
2025-01-10 14:26:26 +01:00
bebecb5ec6 Merge pull request '#481' (#482) from #481 into staging
Some checks failed
Deploy staging on push / pre-build (push) Successful in 2s
Deploy staging on push / build-bot (push) Failing after 11s
Deploy staging on push / build-web (push) Failing after 38s
Deploy staging on push / deploy (push) Has been skipped
Reviewed-on: #482
2025-01-10 14:22:18 +01:00
5a31ea5f76 Set cpl version #481 2025-01-10 14:20:49 +01:00
6216bcf917 Build app #481 2025-01-10 14:19:29 +01:00
f060d62039 Updated builds #481 2025-01-10 14:16:03 +01:00
5d30f551fd Data integrity check for realms #481 2025-01-07 18:24:04 +01:00
6e74e9b190 Handle category updates #481 2025-01-07 17:56:56 +01:00
352ede1667 Fixed realm group #481 2025-01-07 16:40:26 +01:00
405055edf5 Added realm management #481 2025-01-07 16:40:06 +01:00
3abd145ce2 Fixed on message for new member #481 2025-01-07 15:53:19 +01:00
2bb22c0297 Updated staging deploy
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 4m33s
Deploy staging on push / build-web (push) Successful in 2m11s
Deploy staging on push / deploy (push) Successful in 1m4s
2024-11-16 03:23:23 +01:00
1d4e99de46 Update permission service cache when roles for member changed
All checks were successful
Deploy staging on push / pre-build (push) Successful in 1s
Deploy staging on push / build-bot (push) Successful in 6m13s
Deploy staging on push / build-web (push) Successful in 2m50s
Deploy staging on push / deploy (push) Successful in 47s
2024-11-16 02:42:29 +01:00
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
291 changed files with 5051 additions and 2252 deletions

View File

@@ -6,14 +6,18 @@ on:
- dev
jobs:
on-push-deploy_sh-edraft:
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: sh-edraft.de/act-runner:latest
pre-build:
runs-on: [ dobby ]
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: Shutdown stack
run: docker stack rm sdb_dev
build-bot:
needs: pre-build
runs-on: [ dobby ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
@@ -22,10 +26,40 @@ jobs:
- name: Prepare bot build
run: |
cd bot
python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
cd bot
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 ]
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: Setup node
uses: https://github.com/actions/setup-node@v3
@@ -35,29 +69,45 @@ jobs:
npm install -g ts-node
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
run: |
cd web
docker image prune -f
cp src/favicon.dev.ico src/favicon.ico
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 ]
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
run: |
cd bot/docker
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
uses: https://github.com/kgierke/portainer-stack-deployment@v1

View File

@@ -6,14 +6,18 @@ on:
- master
jobs:
on-push-deploy_sh-edraft:
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: sh-edraft.de/act-runner:latest
pre-build:
runs-on: [ dobby ]
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: Shutdown stack
run: docker stack rm sdb_prod
build-bot:
needs: pre-build
runs-on: [ dobby ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
@@ -22,10 +26,40 @@ jobs:
- name: Prepare bot build
run: |
cd bot
python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
cd bot
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 ]
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: Setup node
uses: https://github.com/actions/setup-node@v3
@@ -35,28 +69,44 @@ jobs:
npm install -g ts-node
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
run: |
cd web
docker image prune -f
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 ]
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
run: |
cd bot/docker
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
uses: https://github.com/kgierke/portainer-stack-deployment@v1

View File

@@ -6,14 +6,18 @@ on:
- staging
jobs:
on-push-deploy_sh-edraft:
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: sh-edraft.de/act-runner:latest
pre-build:
runs-on: [ dobby ]
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: Shutdown stack
run: docker stack rm sdb_staging
build-bot:
needs: pre-build
runs-on: [ dobby ]
container: git.sh-edraft.de/sh-edraft.de/act-runner:latest
steps:
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
@@ -22,10 +26,40 @@ jobs:
- name: Prepare bot build
run: |
cd bot
python3.10 -m pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
cd bot
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 ]
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: Setup node
uses: https://github.com/actions/setup-node@v3
@@ -35,29 +69,45 @@ jobs:
npm install -g ts-node
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
run: |
cd web
docker image prune -f
cp src/favicon.staging.ico src/favicon.ico
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 ]
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
run: |
cd bot/docker
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
uses: https://github.com/kgierke/portainer-stack-deployment@v1

View File

@@ -14,7 +14,7 @@
"config": "src/modules/config/config.json",
"database": "src/modules/database/database.json",
"level": "src/modules/level/level.json",
"permission": "src/modules/permission/permission.json",
"realms": "src/modules/realms/realms.json",
"technician": "src/modules/technician/technician.json",
"short-role-name": "src/modules/short_role_name/short-role-name.json",
"special-offers": "src/modules/special_offers/special-offers.json",

View File

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

View File

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

View File

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

View File

@@ -12,7 +12,7 @@ from modules.boot_log.boot_log_module import BootLogModule
from modules.config.config_module import ConfigModule
from modules.database.database_module import DatabaseModule
from modules.level.level_module import LevelModule
from modules.permission.permission_module import PermissionModule
from modules.realms.reams_module import RealmsModule
from modules.short_role_name.short_role_name_module import ShortRoleNameModule
from modules.special_offers.special_offers_module import SteamSpecialOffersModule
from modules.technician.technician_module import TechnicianModule
@@ -30,7 +30,6 @@ class ModuleList:
ConfigModule, # has to be before db check
DatabaseModule,
GraphQLModule,
PermissionModule,
AutoRoleModule,
BaseModule,
LevelModule,
@@ -39,6 +38,7 @@ class ModuleList:
AchievementsModule,
ShortRoleNameModule,
SteamSpecialOffersModule,
RealmsModule,
# has to be last!
BootLogModule,
CoreExtensionModule,

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

View File

@@ -2,22 +2,22 @@
"api": {
"api": {
"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"
}
},
"auth": {
"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"
},
"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"
}
},
"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": {
@@ -95,6 +95,56 @@
}
},
"modules": {
"realm": {
"list": {
"title": "Level:",
"description": "Konfigurierte Level:",
"realm_names": "Realm-Namen",
"error": {
"nothing_found": "Keine Einträge gefunden."
}
},
"add": {
"error": {
"role_exists": "Die Rolle {} existiert bereits.",
"category_exists": "Die Kategorie {} existiert bereits.",
"realm_exists": "Das Realm {} existiert bereits.",
"realm_create": "Fehler beim Erstellen des Realms {}."
},
"success": "Das Realm {} wurde erfolgreich erstellt."
},
"edit": {
"error": {
"realm_not_found": "Das Realm {} wurde nicht gefunden."
},
"success": "Das Realm {} wurde erfolgreich in {} umbenannt."
},
"error": {
"not_moderator": "Du bist kein Moderator des Realms {}."
},
"delete": {
"error": {
"realm_not_found": "Das Realm {} wurde nicht gefunden."
},
"success": "Das Realm {} wurde erfolgreich gelöscht."
},
"member": {
"add": {
"success": "{} wurde erfolgreich zum Realm {} hinzugefügt."
},
"remove": {
"success": "{} wurde erfolgreich aus dem Realm {} entfernt."
}
},
"moderator": {
"add": {
"success": "{} wurde erfolgreich zum Moderator des Realms {} hinzugefügt."
},
"remove": {
"success": "{} wurde erfolgreich als Moderator des Realms {} entfernt."
}
}
},
"special_offers": {
"price": "Preis",
"discount": "Rabatt",
@@ -236,7 +286,7 @@
},
"user": {
"birthday": {
"has_birthday": "Alles Gute zum Geburtag {} :D",
"has_birthday": "Alles Gute zum Geburtstag {} :D",
"success": "Dein Geburtstag wurde eingetragen.",
"success_team": "{} hat seinen Geburtstag eingetragen: {}"
},

View File

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

View File

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

View File

@@ -114,3 +114,7 @@ class AuthServiceABC(ABC):
@abstractmethod
async def reset_password_async(self, rp_dto: ResetPasswordDTO):
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.authentication_settings import AuthenticationSettings
from bot_api.exception.service_error_code_enum import ServiceErrorCode
from bot_api.exception.service_exception import ServiceException
from bot_core.exception.service_error_code_enum import ServiceErrorCode
from bot_core.exception.service_exception import ServiceException
from bot_api.logging.api_logger import ApiLogger
from bot_api.model.error_dto import ErrorDTO
from bot_api.route.route import Route

View File

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

View File

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

View File

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

View File

@@ -84,13 +84,13 @@ class AuthController:
self._auth_service.add_auth_user(dto)
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>")
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)
return jsonify(result)

View File

@@ -16,6 +16,7 @@ from bot_api.api import Api
from bot_api.configuration.discord_authentication_settings import (
DiscordAuthenticationSettings,
)
from bot_core.exception.service_exception import ServiceException
from bot_api.logging.api_logger import ApiLogger
from bot_api.model.auth_user_dto import AuthUserDTO
from bot_api.route.route import Route
@@ -90,5 +91,10 @@ class AuthDiscordController:
AuthRoleEnum.normal,
)
result = await self._auth_service.login_discord_async(dto, response["id"])
return jsonify(result.to_dict())
try:
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"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.2"
__version__ = "1.2.11"
from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="2")
version_info = VersionInfo(major="1", minor="2", micro="11")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,10 +1,7 @@
import traceback
from typing import Optional
from cpl_core.console import Console
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):

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
import hashlib
import re
import textwrap
import uuid
from datetime import datetime, timedelta, timezone
from threading import Thread
@@ -19,8 +18,8 @@ from flask import request
from bot_api.abc.auth_service_abc import AuthServiceABC
from bot_api.configuration.authentication_settings import AuthenticationSettings
from bot_api.configuration.frontend_settings import FrontendSettings
from bot_api.exception.service_error_code_enum import ServiceErrorCode
from bot_api.exception.service_exception import ServiceException
from bot_core.exception.service_error_code_enum import ServiceErrorCode
from bot_core.exception.service_exception import ServiceException
from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria
from bot_api.logging.api_logger import ApiLogger
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_receiver(str(email))
mail.subject = subject
mail.body = textwrap.dedent(
f"""{message}
{self._t.transform('api.mail.automatic_mail').format(self._environment.application_name, self._environment.environment_name, self._environment.host_name)}
"""
)
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)}"
thr = Thread(target=self._mailer.send_mail, args=[mail])
thr.start()
@@ -599,3 +594,12 @@ class AuthService(AuthServiceABC):
user.forgot_password_id = None
self._auth_users.update_auth_user(user)
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 bot_api.abc.auth_service_abc import AuthServiceABC
from bot_api.exception.service_error_code_enum import ServiceErrorCode
from bot_api.exception.service_exception import ServiceException
from bot_core.exception.service_error_code_enum import ServiceErrorCode
from bot_core.exception.service_exception import ServiceException
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_filtered_result_dto import ServerFilteredResultDTO

View File

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

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_user import AuthUser
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):
@@ -35,21 +35,37 @@ class AuthUserTransformer(TransformerABC):
@ServiceProviderABC.inject
def _is_technician(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
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)
if member is None:
return permissions.is_member_technician_by_id(user.discord_id)
return permissions.is_member_technician(member)
@staticmethod
@ServiceProviderABC.inject
def _is_admin(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
guild = bot.get_guild(user.server.discord_id)
if guild is None:
return False
member = guild.get_member(user.discord_id)
if member is None:
return False
return permissions.is_member_admin(member)
@staticmethod
@ServiceProviderABC.inject
def _is_moderator(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
guild = bot.get_guild(user.server.discord_id)
if guild is None:
return False
member = guild.get_member(user.discord_id)
if member is None:
return False
return permissions.is_member_moderator(member)
@classmethod

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,9 +15,9 @@ class FeatureFlagsEnum(Enum):
database_module = "DatabaseModule"
level_module = "LevelModule"
moderator_module = "ModeratorModule"
permission_module = "PermissionModule"
short_role_name_module = "ShortRoleNameModule"
steam_special_offers_module = "SteamSpecialOffersModule"
realm_module = "RealmModule"
# features
api_only = "ApiOnly"
presence = "Presence"

View File

@@ -16,10 +16,10 @@ class FeatureFlagsSettings(ConfigurationModelABC):
FeatureFlagsEnum.data_module.value: True, # 03.10.2022 #56
FeatureFlagsEnum.database_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48
FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48
FeatureFlagsEnum.config_module.value: True, # 19.07.2023 #127
FeatureFlagsEnum.short_role_name_module.value: True, # 28.09.2023 #378
FeatureFlagsEnum.steam_special_offers_module.value: True, # 11.10.2023 #188
FeatureFlagsEnum.realm_module.value: True, # 07.01.2025 #481
# features
FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70
FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56

View File

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

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.helper.command_checks import CommandChecks
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):

View File

@@ -1,20 +1,18 @@
import asyncio
from cpl_core.configuration import ConfigurationABC
from cpl_core.logging import LoggerABC
from cpl_discord.events import OnReadyABC
from cpl_discord.service import DiscordBotServiceABC
from cpl_translation import TranslatePipe
from bot_core.abc.client_utils_abc import ClientUtilsABC
from bot_core.environment_variables import MAINTENANCE
from bot_core.logging.event_logger import EventLogger
class CoreExtensionOnReadyEvent(OnReadyABC):
def __init__(
self,
config: ConfigurationABC,
logger: LoggerABC,
logger: EventLogger,
bot: DiscordBotServiceABC,
client_utils: ClientUtilsABC,
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.message_service_abc import MessageServiceABC
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.events.core_on_ready_event import CoreOnReadyEvent
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.data_integrity_service import DataIntegrityService
from bot_core.service.message_service import MessageService
from bot_core.service.permission_service_with_cache import PermissionServiceWithCache
class CoreModule(ModuleABC):
@@ -28,6 +30,7 @@ class CoreModule(ModuleABC):
services.add_transient(MessageServiceABC, MessageService)
services.add_transient(ClientUtilsABC, ClientUtilsService)
services.add_transient(DataIntegrityService)
services.add_singleton(PermissionServiceABC, PermissionServiceWithCache)
# pipes
services.add_transient(DateTimeOffsetPipe)

View File

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

View File

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

View File

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

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

View File

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

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.message_service_abc import MessageServiceABC
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:

View File

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

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"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.2"
__version__ = "1.2.11"
from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="2")
version_info = VersionInfo(major="1", minor="2", micro="11")

View File

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

View File

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

View File

@@ -1,9 +1,8 @@
from datetime import datetime, timedelta
from typing import Union
import discord
from cpl_core.configuration import ConfigurationABC
from cpl_core.database.context import DatabaseContextABC
from cpl_discord.container import Member, Guild
from cpl_discord.service import DiscordBotServiceABC
from bot_core.abc.client_utils_abc import ClientUtilsABC
@@ -28,6 +27,7 @@ from bot_data.model.user_joined_server import UserJoinedServer
from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
from bot_data.service.user_repository_service import ServerRepositoryABC
from modules.achievements.achievement_service import AchievementService
from modules.realms.realm_utils import RealmUtils
class DataIntegrityService:
@@ -47,6 +47,7 @@ class DataIntegrityService:
achievement_service: AchievementService,
client_utils: ClientUtilsABC,
dtp: DateTimeOffsetPipe,
ream_utils: RealmUtils,
):
self._config = config
@@ -63,359 +64,262 @@ class DataIntegrityService:
self._achievements = achievement_service
self._client_utils = client_utils
self._dtp = dtp
self._realm_utils = ream_utils
self._is_for_shutdown = False
def _check_known_users(self):
self._logger.debug(__name__, f"Start checking KnownUsers table, {len(self._bot.users)}")
for u in self._bot.users:
u: discord.User = u
try:
if u.bot:
self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot")
continue
async def check_data_integrity(self, is_for_shutdown=False):
self._logger.info(__name__, f"Data integrity service started")
if is_for_shutdown != self._is_for_shutdown:
self._is_for_shutdown = is_for_shutdown
user = self._known_users.find_user_by_discord_id(u.id)
if user is not None:
continue
try:
for g in self._bot.guilds:
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}")
self._logger.debug(__name__, f"Add user: {u.id}")
self._known_users.add_user(KnownUser(u.id))
self._db_context.save_changes()
for m in [m for m in g.members if not m.bot]:
await self._check_default_role(m)
self._check_known_user(m.id)
user = self._known_users.find_user_by_discord_id(u.id)
if user is None:
self._logger.fatal(__name__, f"Cannot add user: {u.id}")
self._logger.debug(__name__, f"Start check for member: {g.id}@{m.id}")
u = self._get_or_create_user(s, m.id)
self._logger.debug(__name__, f"Added user: {u.id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get user", e)
self._logger.debug(__name__, f"Start check for user joined server: {g.id}@{m.id}")
self._check_user_join(g, m, u)
def check_servers(self):
self._logger.debug(__name__, f"Start checking Servers table")
for g in self._bot.guilds:
g: discord.Guild = g
try:
server = self._servers.find_server_by_discord_id(g.id)
if server is not None:
continue
self._logger.debug(__name__, f"Start check for user joined voice channels: {g.id}@{m.id}")
self._check_user_joined_vc(g.id, m, u)
self._logger.warn(__name__, f"Server not found in database: {g.id}")
self._logger.debug(__name__, f"Add server: {g.id}")
self._servers.add_server(Server(g.id))
self._db_context.save_changes()
self._logger.debug(__name__, f"Start check for user joined game servers: {g.id}@{m.id}")
self._check_user_joined_gs(g.id, m.id, u)
server = self._servers.find_server_by_discord_id(g.id)
if server is None:
self._logger.fatal(__name__, f"Cannot add server: {g.id}")
self._logger.debug(__name__, f"Start check for user got achievements: {g.id}@{m.id}")
await self._check_for_user_achievements(u)
self._logger.debug(__name__, f"Added server: {g.id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get server", e)
self._logger.debug(__name__, f"Start check for user got achievements: {g.id}@{m.id}")
await self._realm_utils.check_integrity(s, g)
for m in [m for m in g.members if m.bot]:
u = self._users.find_user_by_discord_id_and_server_id(m.id, s.id)
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()
if results is None or len(results) == 0:
self._logger.error(__name__, f"Table Servers is empty!")
def _check_clients(self):
self._logger.debug(__name__, f"Start checking Clients table")
for g in self._bot.guilds:
g: discord.Guild = g
try:
server: Server = self._servers.find_server_by_discord_id(g.id)
if server is None:
self._logger.fatal(__name__, f"Server not found in database: {g.id}")
def _check_known_user(self, member_id: int):
try:
if self._known_users.find_user_by_discord_id(member_id) is not None:
return
client = self._clients.find_client_by_server_id(server.id)
if client is not None:
self._logger.warn(__name__, f"Unknown user: {member_id}")
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
self._logger.warn(
__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}")
self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server))
join.leaved_on = datetime.now()
self._user_joins.update_user_joined_server(join)
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)
if client is None:
self._logger.fatal(
__name__,
f"Cannot add client {self._bot.user.id} for server {g.id}",
)
def _check_user_joined_vc(self, guild_id: int, member: Member, user: User):
settings: ServerConfig = self._config.get_configuration(f"ServerConfig_{guild_id}")
self._logger.debug(__name__, f"Added client: {g.id}")
except Exception as e:
self._logger.error(__name__, f"Cannot get client", e)
try:
# close open voice states
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:
join: UserJoinedServer = join
if join.user.server.discord_id != guild.id:
continue
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 is not None:
continue
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)
dc_user = guild.get_member(join.user.discord_id)
if dc_user is None:
self._logger.warn(
__name__,
f"User {join.user.discord_id} already left the server.",
)
join.leaved_on = datetime.now()
self._user_joins.update_user_joined_server(join)
self._user_joins_vc.update_user_joined_voice_channel(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()
if self._is_for_shutdown:
return
async def check_data_integrity(self, is_for_shutdown=False):
if is_for_shutdown != self._is_for_shutdown:
self._is_for_shutdown = is_for_shutdown
# add open voice states
if member.voice is None or member.voice.channel.id in settings.afk_channel_ids:
return
await self._check_default_role()
self._check_known_users()
self.check_servers()
self._check_clients()
self._check_users()
self._check_user_joins()
self._check_user_joins_vc()
self._check_user_joined_gs()
await self._check_for_user_achievements()
self._check_for_bots()
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, guild_id: int, member_id: int, user: User):
try:
joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.id)
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 PermissionServiceWithCache(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"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.2"
__version__ = "1.2.11"
from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="2")
version_info = VersionInfo(major="1", minor="2", micro="11")

View File

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

View File

@@ -0,0 +1,69 @@
from abc import ABC, abstractmethod
from typing import Optional
from cpl_query.extension import List
from bot_data.model.realm import Realm
from bot_data.model.realm_moderator import RealmModerator
class RealmRepositoryABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def get_all(self) -> List[Realm]:
pass
@abstractmethod
def get_realm_by_id(self, id: int) -> Realm:
pass
@abstractmethod
def find_realm_by_id(self, id: int) -> Optional[Realm]:
pass
@abstractmethod
def find_realm_by_name(self, name: str) -> Optional[Realm]:
pass
@abstractmethod
def get_realms_by_server_id(self, id: int) -> List[Realm]:
pass
@abstractmethod
def add_realm(self, realm: Realm):
pass
@abstractmethod
def update_realm(self, realm: Realm):
pass
@abstractmethod
def delete_realm(self, realm: Realm):
pass
@abstractmethod
def get_realm_moderators(self) -> List[RealmModerator]:
pass
@abstractmethod
def get_realm_moderator_by_id(self, id: int) -> RealmModerator:
pass
@abstractmethod
def get_realm_moderators_by_realm_id(self, id: int) -> List[RealmModerator]:
pass
@abstractmethod
def add_realm_moderator(self, realm: RealmModerator):
pass
@abstractmethod
def update_realm_moderator(self, realm: RealmModerator):
pass
@abstractmethod
def delete_realm_moderator(self, realm: RealmModerator):
pass

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,6 +14,7 @@ from bot_data.abc.data_seeder_abc import DataSeederABC
from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC
from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC
from bot_data.abc.level_repository_abc import LevelRepositoryABC
from bot_data.abc.realm_repository_abc import RealmRepositoryABC
from bot_data.abc.scheduled_event_repository_abc import ScheduledEventRepositoryABC
from bot_data.abc.server_config_repository_abc import ServerConfigRepositoryABC
from bot_data.abc.server_repository_abc import ServerRepositoryABC
@@ -46,6 +47,7 @@ from bot_data.service.client_repository_service import ClientRepositoryService
from bot_data.service.game_server_repository_service import GameServerRepositoryService
from bot_data.service.known_user_repository_service import KnownUserRepositoryService
from bot_data.service.level_repository_service import LevelRepositoryService
from bot_data.service.realm_repository_service import RealmRepositoryService
from bot_data.service.scheduled_event_repository_service import ScheduledEventRepositoryService
from bot_data.service.seeder_service import SeederService
from bot_data.service.server_config_repository_service import (
@@ -118,6 +120,7 @@ class DataModule(ModuleABC):
services.add_transient(ShortRoleNameRepositoryABC, ShortRoleNameRepositoryService)
services.add_transient(SteamSpecialOfferRepositoryABC, SteamSpecialOfferRepositoryService)
services.add_transient(ScheduledEventRepositoryABC, ScheduledEventRepositoryService)
services.add_transient(RealmRepositoryABC, RealmRepositoryService)
services.add_transient(SeederService)
services.add_transient(DataSeederABC, TechnicianConfigSeeder)

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.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_data.mysql_pool import MySQLPool
class DBContext(DatabaseContext):
@@ -11,36 +14,45 @@ class DBContext(DatabaseContext):
self._logger = logger
DatabaseContext.__init__(self)
self._pool: MySQLPool = None
self._fails = 0
def connect(self, database_settings: DatabaseSettings):
try:
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")
except Exception as e:
self._logger.fatal(__name__, "Connecting to database failed", e)
@property
def cursor(self):
return self
def save_changes(self):
try:
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)
pass
def select(self, statement: str) -> list[tuple]:
try:
return super(DBContext, self).select(statement)
return self._pool.execute(statement)
except Exception as e:
if self._fails >= 3:
self._logger.fatal(__name__, f"Database error caused by {statement}", e)
self._logger.error(__name__, f"Database error caused by {statement}", e)
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._fails += 1
try:
time.sleep(0.5)
self._logger.debug(__name__, "Retry select")
return self.select(statement)
except Exception as e:
pass
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"
__license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.2"
__version__ = "1.2.11"
from collections import namedtuple
@@ -23,4 +23,4 @@ from collections import namedtuple
# imports
VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="2")
version_info = VersionInfo(major="1", minor="2", micro="11")

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
def delete_string(self) -> str:
return str(

View File

@@ -1,4 +1,5 @@
from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
@@ -48,8 +49,10 @@ class AutoRoleRule(TableABC):
@property
@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)
if guild is None:
return None
return guild.get_role(self.role_id).name
@role_id.setter

View File

@@ -1,3 +1,5 @@
from typing import Optional
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
@@ -43,6 +45,8 @@ class AutoRoleRuleHistory(HistoryTableABC):
@property
@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)
if guild is None:
return None
return guild.get_role(self.role_id).name

View File

@@ -2,6 +2,10 @@ from datetime import datetime
from typing import Optional
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
@@ -33,6 +37,15 @@ class Level(TableABC):
def id(self) -> int:
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
def name(self) -> str:
return self._name

View File

@@ -0,0 +1,120 @@
from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC
from bot_data.model.server import Server
class Realm(TableABC):
def __init__(
self,
name: str,
role_id: int,
server: Optional[Server],
created_at: datetime = None,
modified_at: datetime = None,
id=0,
):
self._id = id
self._name = name.replace("'", "")
self._role_id = role_id
self._server = server
TableABC.__init__(self)
self._created_at = created_at if created_at is not None else self._created_at
self._modified_at = modified_at if modified_at is not None else self._modified_at
@property
def id(self) -> int:
return self._id
@property
def name(self) -> str:
return self._name.replace("'", "")
@name.setter
def name(self, value: str):
self._name = value.replace("'", "")
@property
def role_id(self) -> int:
return self._role_id
@role_id.setter
def role_id(self, value: int):
self._role_id = value
@property
def server(self) -> Server:
return self._server
@staticmethod
def get_select_all_string() -> str:
return str(
f"""
SELECT * FROM `Realms`;
"""
)
@staticmethod
def get_select_by_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `Realms`
WHERE `RealmId` = {id};
"""
)
@staticmethod
def get_select_by_server_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `Realms`
WHERE `ServerId` = {id};
"""
)
@staticmethod
def get_select_by_name_string(name: str) -> str:
return str(
f"""
SELECT * FROM `Realms`
WHERE `Name` = '{name}';
"""
)
@property
def insert_string(self) -> str:
return str(
f"""
INSERT INTO `Realms` (
`ServerId`, `Name`, `RoleId`
) VALUES (
{self._server.id},
'{self._name}',
{self._role_id}
);
"""
)
@property
def udpate_string(self) -> str:
return str(
f"""
UPDATE `Realms`
SET `ServerId` = {self._server.id},
`Name` = '{self._name}',
`RoleId` = {self._role_id}
WHERE `RealmId` = {self._id};
"""
)
@property
def delete_string(self) -> str:
return str(
f"""
DELETE FROM `Realms`
WHERE `RealmId` = {self._id};
"""
)

View File

@@ -0,0 +1,43 @@
from typing import Optional
from bot_data.abc.history_table_abc import HistoryTableABC
from bot_data.model.server import Server
class Realm(HistoryTableABC):
def __init__(
self,
server: Optional[Server],
name: str,
role_id: int,
deleted: bool,
date_from: str,
date_to: str,
id=0,
):
HistoryTableABC.__init__(self)
self._id = id
self._server = server
self._name = name
self._role_id = role_id
self._deleted = deleted
self._date_from = date_from
self._date_to = date_to
@property
def id(self) -> int:
return self._id
@property
def server(self) -> Server:
return self._server
@property
def name(self) -> str:
return self._name
@property
def role_id(self) -> int:
return self._role_id

View File

@@ -0,0 +1,106 @@
from datetime import datetime
from cpl_core.database import TableABC
from bot_data.model.realm import Realm
from bot_data.model.user import User
class RealmModerator(TableABC):
def __init__(
self,
realm: Realm,
user: User,
created_at: datetime = None,
modified_at: datetime = None,
id=0,
):
self._join_id = id
self._realm = realm
self._user = user
TableABC.__init__(self)
self._created_at = created_at if created_at is not None else self._created_at
self._modified_at = modified_at if modified_at is not None else self._modified_at
@property
def id(self) -> int:
return self._join_id
@property
def realm(self) -> Realm:
return self._realm
@property
def user(self) -> User:
return self._user
@staticmethod
def get_select_all_string() -> str:
return str(
f"""
SELECT * FROM `RealmModerators`;
"""
)
@staticmethod
def get_select_by_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `RealmModerators`
WHERE `Id` = {id};
"""
)
@staticmethod
def get_select_by_realm_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `RealmModerators`
WHERE `RealmId` = {id};
"""
)
@staticmethod
def get_select_by_user_id_string(id: int) -> str:
return str(
f"""
SELECT * FROM `RealmModerators`
WHERE `UserId` = {id};
"""
)
@property
def insert_string(self) -> str:
return str(
f"""
INSERT INTO `RealmModerators` (
`UserId`, `RealmId`
) VALUES (
{self._user.id},
{self._realm.id}
);
"""
)
@property
def udpate_string(self) -> str:
return str(f"""""")
@property
def delete_string(self) -> str:
return str(
f"""
DELETE FROM `RealmModerators`
WHERE `Id` = {self._join_id};
"""
)
@staticmethod
def delete_by_user_id_string(id: int) -> str:
return str(
f"""
DELETE FROM `RealmModerators`
WHERE `UserId` = {id}
"""
)

View File

@@ -0,0 +1,36 @@
from bot_data.abc.history_table_abc import HistoryTableABC
from bot_data.model.realm import Realm
from bot_data.model.user import User
class RealmModerator(HistoryTableABC):
def __init__(
self,
realm: Realm,
user: User,
deleted: bool,
date_from: str,
date_to: str,
id=0,
):
HistoryTableABC.__init__(self)
self._join_id = id
self._realm = realm
self._user = user
self._deleted = deleted
self._date_from = date_from
self._date_to = date_to
@property
def id(self) -> int:
return self._join_id
@property
def realm(self) -> Realm:
return self._realm
@property
def user(self) -> User:
return self._user

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,5 @@
from datetime import datetime
from typing import Optional
from cpl_core.database import TableABC
from cpl_core.dependency_injection import ServiceProviderABC
@@ -51,8 +52,10 @@ class ShortRoleName(TableABC):
@property
@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)
if guild is None:
return None
return guild.get_role(self.role_id).name
@property

View File

@@ -1,3 +1,5 @@
from typing import Optional
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
@@ -47,8 +49,10 @@ class ShortRoleNameHistory(HistoryTableABC):
@property
@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)
if guild is None:
return None
return guild.get_role(self.role_id).name
@property

View File

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

View File

@@ -2,6 +2,7 @@ from datetime import datetime, date
from typing import Optional
from cpl_core.database import TableABC
from cpl_core.database.context import DatabaseContextABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_discord.service import DiscordBotServiceABC
from cpl_query.extension import List
@@ -31,10 +32,17 @@ class User(TableABC):
self._birthday = birthday
self._server = server
self._activity = 0
TableABC.__init__(self)
self._created_at = created_at if created_at is not None else self._created_at
self._modified_at = modified_at if modified_at is not None else self._modified_at
def reset(self):
self._xp = 0
self._message_count = 0
self._reaction_count = 0
@property
def id(self) -> int:
return self._user_id
@@ -45,15 +53,19 @@ class User(TableABC):
@property
@ServiceProviderABC.inject
def name(self, bot: DiscordBotServiceABC) -> str:
def name(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 else user.name
@property
@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)
if guild is None:
return None
user = guild.get_member(self.discord_id)
return None if user is None else user.display_icon
@@ -92,14 +104,44 @@ class User(TableABC):
@property
@ServiceProviderABC.inject
def ontime(self, services: ServiceProviderABC) -> float:
from bot_core.abc.client_utils_abc import ClientUtilsABC
client_utils: ClientUtilsABC = services.get_service(ClientUtilsABC)
return client_utils.get_ontime_for_user(self)
db: DatabaseContextABC = services.get_service(DatabaseContextABC)
result = db.select(
f"""
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
@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
levels: LevelService = services.get_service(LevelService)
@@ -135,6 +177,15 @@ class User(TableABC):
game_idents_repo: UserGameIdentRepositoryABC = services.get_service(UserGameIdentRepositoryABC)
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
def get_select_all_string() -> 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
def get_select_by_user_id_string(id: int) -> 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
def get_select_by_user_id_string(id: int) -> 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

@@ -0,0 +1,4 @@
DROP TABLE IF EXISTS `Realms`;
DROP TABLE IF EXISTS `RealmsHistory`;
DROP TABLE IF EXISTS `RealmModerators`;
DROP TABLE IF EXISTS `RealmModeratorsHistory`;

View File

@@ -0,0 +1,97 @@
CREATE TABLE IF NOT EXISTS `Realms`
(
`RealmId` BIGINT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(255) NOT NULL,
`RoleId` BIGINT NOT NULL,
`ServerId` BIGINT,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (`RealmId`),
FOREIGN KEY (`ServerId`) REFERENCES `Servers` (`ServerId`)
);
CREATE TABLE IF NOT EXISTS `RealmsHistory`
(
`RealmId` BIGINT(20) NOT NULL,
`Name` VARCHAR(255) NOT NULL,
`RoleId` BIGINT NOT NULL,
`ServerId` BIGINT(20) DEFAULT NULL,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
DROP TRIGGER IF EXISTS `TR_RealmsUpdate`;
CREATE TRIGGER `TR_RealmsUpdate`
AFTER UPDATE
ON `Realms`
FOR EACH ROW
BEGIN
INSERT INTO `RealmsHistory` (`RealmId`, `Name`, `RoleId`, `ServerId`, `DateFrom`, `DateTo`)
VALUES (OLD.RealmId, OLD.Name, OLD.RoleId, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6));
END;
DROP TRIGGER IF EXISTS `TR_RealmsDelete`;
CREATE TRIGGER `TR_RealmsDelete`
AFTER DELETE
ON `Realms`
FOR EACH ROW
BEGIN
INSERT INTO `RealmsHistory` (`RealmId`, `Name`, `RoleId`, `ServerId`, `Deleted`, `DateFrom`, `DateTo`)
VALUES (OLD.RealmId, OLD.Name, OLD.RoleId, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6));
END;
-- Realm moderators
CREATE TABLE IF NOT EXISTS `RealmModerators`
(
`Id` BIGINT NOT NULL AUTO_INCREMENT,
`RealmId` BIGINT NOT NULL,
`UserId` BIGINT NOT NULL,
`ServerId` BIGINT,
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (`Id`),
FOREIGN KEY (`RealmId`) REFERENCES `Realms` (`RealmId`),
FOREIGN KEY (`UserId`) REFERENCES `Users` (`UserId`),
FOREIGN KEY (`ServerId`) REFERENCES `Servers` (`ServerId`)
);
CREATE TABLE IF NOT EXISTS `RealmModeratorsHistory`
(
`Id` BIGINT(20) NOT NULL,
`RealmId` BIGINT NOT NULL,
`UserId` BIGINT NOT NULL,
`ServerId` BIGINT(20) DEFAULT NULL,
`Deleted` BOOL DEFAULT FALSE,
`DateFrom` DATETIME(6) NOT NULL,
`DateTo` DATETIME(6) NOT NULL
);
DROP TRIGGER IF EXISTS `TR_RealmModeratorsUpdate`;
CREATE TRIGGER `TR_RealmModeratorsUpdate`
AFTER UPDATE
ON `RealmModerators`
FOR EACH ROW
BEGIN
INSERT INTO `RealmModeratorsHistory` (`Id`, `RealmId`, `UserId`, `ServerId`, `DateFrom`, `DateTo`)
VALUES (OLD.Id, OLD.RealmId, OLD.UserId, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6));
END;
DROP TRIGGER IF EXISTS `TR_RealmModeratorsDelete`;
CREATE TRIGGER `TR_RealmModeratorsDelete`
AFTER DELETE
ON `RealmModerators`
FOR EACH ROW
BEGIN
INSERT INTO `RealmModeratorsHistory` (`Id`, `RealmId`, `UserId`, `ServerId`, `Deleted`, `DateFrom`, `DateTo`)
VALUES (OLD.Id, OLD.RealmId, OLD.UserId, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6));
END;

View File

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

View File

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

View File

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

View File

@@ -64,23 +64,16 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
__name__,
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]:
users = List(AuthUser)
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:
users = self.get_all_auth_users()
@@ -129,8 +122,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
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)}")
result = self._context.select(AuthUser.get_select_by_email_string(email))[0]
return self._user_from_result(result)
return self._user_from_result(self._context.select(AuthUser.get_select_by_email_string(email))[0])
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)}")
@@ -138,9 +130,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
if result is None or len(result) == 0:
return None
result = result[0]
return self._user_from_result(result)
return self._user_from_result(result[0])
def find_auth_user_by_confirmation_id(self, id: str) -> Optional[AuthUser]:
self._logger.trace(
@@ -151,9 +141,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
if result is None or len(result) == 0:
return None
result = result[0]
return self._user_from_result(result)
return self._user_from_result(result[0])
def find_auth_user_by_forgot_password_id(self, id: str) -> Optional[AuthUser]:
self._logger.trace(
@@ -164,9 +152,7 @@ class AuthUserRepositoryService(AuthUserRepositoryABC):
if result is None or len(result) == 0:
return None
result = result[0]
return self._user_from_result(result)
return self._user_from_result(result[0])
def add_auth_user(self, user: AuthUser):
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):
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)
def add_auth_user_user_rel(self, rel: AuthUserUsersRelation):

View File

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

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