Compare commits
103 Commits
1.1.6
...
dd6b609094
Author | SHA1 | Date | |
---|---|---|---|
dd6b609094 | |||
3810dec927 | |||
a87380f6f8 | |||
98ac7835b6 | |||
0a76068604 | |||
f9caf59180 | |||
284318bb10 | |||
6130cac6fe | |||
3a64c51600 | |||
90fce5a79a | |||
d448ad7707 | |||
19791ff9d8 | |||
3cba8de675 | |||
b7ff070676 | |||
c88e07d743 | |||
f5b978b231 | |||
0e2b7d03fc | |||
c7f5ab0161 | |||
01e8e4256d | |||
75adc2285e | |||
9e12d84ba0 | |||
d3b503d3ef | |||
dd86c3a657 | |||
aba6e48e2b | |||
73848c3141 | |||
33d6015088 | |||
7e962e05f6 | |||
c73c6876b2 | |||
8e949c3e1a | |||
472a76d563 | |||
f5d88ec94c | |||
2182c021b9 | |||
a9c9880fd4 | |||
d91c76467d | |||
2f10ace27f | |||
3b79a61bb6 | |||
ef0fab1178 | |||
189b6370a9 | |||
0ed93c56d0 | |||
4d18dd3845 | |||
7b7cbb20db | |||
84c2f5c2c4 | |||
c85c6df784 | |||
d5d898fa07 | |||
ef5ebabf81 | |||
f89b4c4ef5 | |||
8b277a2d19 | |||
a84e77e055 | |||
892c983e1e | |||
1d3809c986 | |||
3117f617d9 | |||
7e6053768f | |||
3d9cd0a2fc | |||
8d90768594 | |||
7e8a9482d4 | |||
bf7d29e6ab | |||
608001e0e1 | |||
0dd9558f33 | |||
7acd850e68 | |||
ecd3ea96b1 | |||
d869bcfd3a | |||
818e021761 | |||
b286322247 | |||
661b057e85 | |||
9be4e344f6 | |||
ebc782e266 | |||
887a46fa7f | |||
0cc8d6f2c7 | |||
3546d38f75 | |||
376cb76036 | |||
8e8da46a54 | |||
94e003312d | |||
fe42d46a38 | |||
4c0a4bc1ae | |||
4161d3a38a | |||
4a763e4e03 | |||
9783424066 | |||
290b5f38a7 | |||
5bfd04722c | |||
12f956f4c3 | |||
0b767fcb68 | |||
a303108da2 | |||
5e9cca5b1d | |||
d1c79c95b2 | |||
378d2c3dc9 | |||
a8ea9f5e49 | |||
957a54ccf3 | |||
0037a30c11 | |||
77e079d91c | |||
25137c6923 | |||
0a0401dd87 | |||
74f3ee2f08 | |||
69fc75fc97 | |||
5a85232374 | |||
5892b209d3 | |||
6715ecacd6 | |||
d72715d51b | |||
a7f9fa5818 | |||
c45916aaee | |||
8bbd57e82f | |||
987a1a664b | |||
99bfa9874a | |||
2e0c1babe4 |
17
.gitea/issue_template.md
Normal file
17
.gitea/issue_template.md
Normal file
@@ -0,0 +1,17 @@
|
||||
#### Beschreibung
|
||||
|
||||
Als Produktmanager muss ich nun dieses Ticket ausfüllen.
|
||||
|
||||
#### Aktuelles Verhalten
|
||||
|
||||
* Was macht die Software aktuell?
|
||||
|
||||
#### Gewünschtes Verhalten
|
||||
|
||||
* Was soll die Software anders machen?
|
||||
|
||||
#### Akzeptanzkriterien
|
||||
|
||||
* Was muss erfüllt sein, damit das Ticket als abgeschlossen angesehen werden kann?
|
||||
|
||||
#### Anmerkungen
|
7
.gitea/pull_request_template.md
Normal file
7
.gitea/pull_request_template.md
Normal file
@@ -0,0 +1,7 @@
|
||||
#### Ticket Referenz:
|
||||
|
||||
#1
|
||||
|
||||
#### Gibt es etwas beim Review zu beachten?
|
||||
|
||||
Nein
|
65
.gitea/workflows/deploy_dev.yaml
Normal file
65
.gitea/workflows/deploy_dev.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
name: Deploy dev on push
|
||||
run-name: Deploy dev on push
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
on-push-deploy_sh-edraft:
|
||||
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
|
||||
container: catthehacker/ubuntu:act-latest
|
||||
steps:
|
||||
- name: Setup Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10.12"
|
||||
- run: python -v
|
||||
|
||||
- name: Setup docker
|
||||
uses: https://github.com/papodaca/install-docker-action@main
|
||||
- run: docker -v
|
||||
|
||||
- name: Clone Repository
|
||||
uses: https://github.com/actions/checkout@v3
|
||||
|
||||
- name: Shutdown stack
|
||||
run: docker stack rm kdb_staging
|
||||
|
||||
- name: Prepare bot build
|
||||
run: |
|
||||
cd kdb-bot
|
||||
pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
|
||||
cpl i
|
||||
|
||||
- name: Build docker bot
|
||||
run: |
|
||||
cd kdb-bot
|
||||
docker image prune -f
|
||||
cpl docker-build
|
||||
|
||||
- name: Setup node
|
||||
uses: https://github.com/actions/setup-node@v3
|
||||
|
||||
- name: Prepare web build
|
||||
run: |
|
||||
cd kdb-web
|
||||
npm install -g ts-node
|
||||
npm i
|
||||
|
||||
- name: Build docker web
|
||||
run: |
|
||||
cd kdb-web
|
||||
docker image prune -f
|
||||
npm run docker-build
|
||||
|
||||
- name: Deploy Stack to sh-edraft.de
|
||||
uses: https://github.com/kgierke/portainer-stack-deployment@v1
|
||||
with:
|
||||
portainer-url: "https://docker.sh-edraft.de"
|
||||
portainer-username: "gitea_job"
|
||||
portainer-password: "${{ secrets.docker_job }}"
|
||||
portainer-endpoint: 2
|
||||
name: kdb_staging
|
||||
file: ./docker-compose.staging.yml
|
||||
variables: '{}'
|
65
.gitea/workflows/deploy_prod.yaml
Normal file
65
.gitea/workflows/deploy_prod.yaml
Normal file
@@ -0,0 +1,65 @@
|
||||
name: Deploy dev on push
|
||||
run-name: Deploy dev on push
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
on-push-deploy_sh-edraft:
|
||||
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
|
||||
container: catthehacker/ubuntu:act-latest
|
||||
steps:
|
||||
- name: Setup Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10.12"
|
||||
- run: python -v
|
||||
|
||||
- name: Setup docker
|
||||
uses: https://github.com/papodaca/install-docker-action@main
|
||||
- run: docker -v
|
||||
|
||||
- name: Clone Repository
|
||||
uses: https://github.com/actions/checkout@v3
|
||||
|
||||
- name: Shutdown stack
|
||||
run: docker stack rm kdb_prod
|
||||
|
||||
- name: Prepare bot build
|
||||
run: |
|
||||
cd kdb-bot
|
||||
pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
|
||||
cpl i
|
||||
|
||||
- name: Build docker bot
|
||||
run: |
|
||||
cd kdb-bot
|
||||
docker image prune -f
|
||||
cpl docker-build
|
||||
|
||||
- name: Setup node
|
||||
uses: https://github.com/actions/setup-node@v3
|
||||
|
||||
- name: Prepare web build
|
||||
run: |
|
||||
cd kdb-web
|
||||
npm install -g ts-node
|
||||
npm i
|
||||
|
||||
- name: Build docker web
|
||||
run: |
|
||||
cd kdb-web
|
||||
docker image prune -f
|
||||
npm run docker-build
|
||||
|
||||
- name: Deploy Stack to sh-edraft.de
|
||||
uses: https://github.com/kgierke/portainer-stack-deployment@v1
|
||||
with:
|
||||
portainer-url: "https://docker.sh-edraft.de"
|
||||
portainer-username: "gitea_job"
|
||||
portainer-password: "${{ secrets.docker_job }}"
|
||||
portainer-endpoint: 2
|
||||
name: kdb_prod
|
||||
file: ./docker-compose.yml
|
||||
variables: '{}'
|
18
.gitmodules
vendored
18
.gitmodules
vendored
@@ -1,9 +1,9 @@
|
||||
[submodule "kdb-bot/src/bot/config"]
|
||||
path = kdb-bot/src/bot/config
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.config.git
|
||||
[submodule "kdb-bot/src/bot_api/config"]
|
||||
path = kdb-bot/src/bot_api/config
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.api.config.git
|
||||
[submodule "kdb-bot/docker"]
|
||||
path = kdb-bot/docker
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.docker.git
|
||||
[submodule "bot/src/bot/config"]
|
||||
path = bot/src/bot/config
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.config.git
|
||||
[submodule "bot/src/bot_api/config"]
|
||||
path = bot/src/bot_api/config
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.api.config.git
|
||||
[submodule "bot/docker"]
|
||||
path = bot/docker
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.docker.git
|
||||
|
@@ -16,6 +16,8 @@
|
||||
"level": "src/modules/level/level.json",
|
||||
"permission": "src/modules/permission/permission.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",
|
||||
"checks": "tools/checks/checks.json",
|
||||
"get-version": "tools/get_version/get-version.json",
|
||||
"post-build": "tools/post_build/post-build.json",
|
||||
@@ -35,7 +37,7 @@
|
||||
"stage": "export KDB_ENVIRONMENT=staging; export KDB_NAME=KDB-Stage; cpl start;",
|
||||
"pre-dev": "cpl build",
|
||||
"dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;",
|
||||
"docker-build": "cpl build $ARGS; docker build -t kdb-bot/kdb-bot:$(cpl gv) .;",
|
||||
"docker-build": "cpl build $ARGS; docker build -t sh-edraft.de/kdb-bot:$(cpl gv) .;",
|
||||
"dc-up": "docker-compose up -d",
|
||||
"dc-down": "docker-compose down",
|
||||
"docker": "cpl dc-down; cpl docker-build; cpl dc-up;"
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -8,6 +8,7 @@ from cpl_discord.service import DiscordBotServiceABC, DiscordBotService
|
||||
from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings
|
||||
|
||||
from bot_api.api_thread import ApiThread
|
||||
from bot_core.abc.task_abc import TaskABC
|
||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
||||
from bot_core.service.data_integrity_service import DataIntegrityService
|
||||
@@ -22,15 +23,25 @@ class Application(DiscordBotApplicationABC):
|
||||
|
||||
# cpl-core
|
||||
self._logger: LoggerABC = services.get_service(LoggerABC)
|
||||
self._data_integrity: DataIntegrityService = services.get_service(DataIntegrityService)
|
||||
self._data_integrity: DataIntegrityService = services.get_service(
|
||||
DataIntegrityService
|
||||
)
|
||||
# cpl-discord
|
||||
self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC)
|
||||
self._bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings)
|
||||
self._bot_settings: DiscordBotSettings = config.get_configuration(
|
||||
DiscordBotSettings
|
||||
)
|
||||
# cpl-translation
|
||||
self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC)
|
||||
self._translation: TranslationServiceABC = services.get_service(
|
||||
TranslationServiceABC
|
||||
)
|
||||
self._t: TranslatePipe = services.get_service(TranslatePipe)
|
||||
# internal stuff
|
||||
self._tasks = services.get_services(TaskABC)
|
||||
|
||||
self._feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings)
|
||||
self._feature_flags: FeatureFlagsSettings = config.get_configuration(
|
||||
FeatureFlagsSettings
|
||||
)
|
||||
|
||||
# api
|
||||
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||
@@ -39,7 +50,9 @@ class Application(DiscordBotApplicationABC):
|
||||
self._is_stopping = False
|
||||
|
||||
async def configure(self):
|
||||
self._translation.load_by_settings(self._configuration.get_configuration(TranslationSettings))
|
||||
self._translation.load_by_settings(
|
||||
self._configuration.get_configuration(TranslationSettings)
|
||||
)
|
||||
|
||||
async def main(self):
|
||||
try:
|
||||
@@ -55,6 +68,9 @@ class Application(DiscordBotApplicationABC):
|
||||
return
|
||||
|
||||
self._logger.info(__name__, f"Try to start {DiscordBotService.__name__}")
|
||||
for task in self._tasks:
|
||||
await self._bot.add_cog(task)
|
||||
|
||||
await self._bot.start_async()
|
||||
await self._bot.stop_async()
|
||||
except Exception as e:
|
||||
@@ -79,4 +95,8 @@ class Application(DiscordBotApplicationABC):
|
||||
Console.write_line()
|
||||
|
||||
def is_restart(self):
|
||||
return True if self._configuration.get_configuration("IS_RESTART") == "true" else False
|
||||
return (
|
||||
True
|
||||
if self._configuration.get_configuration("IS_RESTART") == "true"
|
||||
else False
|
||||
)
|
@@ -3,35 +3,35 @@
|
||||
"Name": "bot",
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "1",
|
||||
"Micro": "6"
|
||||
"Minor": "2",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
"Description": "Keksdose bot",
|
||||
"LongDescription": "Discord bot for the Keksdose discord Server",
|
||||
"Description": "sh-edraft.de Discord bot",
|
||||
"LongDescription": "Discord bot for customers of sh-edraft.de",
|
||||
"URL": "https://www.sh-edraft.de",
|
||||
"CopyrightDate": "2022 - 2023",
|
||||
"CopyrightName": "sh-edraft.de",
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"cpl-core==2023.4.0.post5",
|
||||
"cpl-core==2023.10.0",
|
||||
"cpl-translation==2023.4.0.post1",
|
||||
"cpl-query==2023.4.0.post1",
|
||||
"cpl-discord==2023.4.0.post3",
|
||||
"Flask==2.3.2",
|
||||
"Flask-Classful==0.14.2",
|
||||
"cpl-query==2023.10.0",
|
||||
"cpl-discord==2023.10.0.post1",
|
||||
"Flask==3.0.0",
|
||||
"Flask-Classful==0.16.0",
|
||||
"Flask-Cors==4.0.0",
|
||||
"PyJWT==2.8.0",
|
||||
"waitress==2.1.2",
|
||||
"Flask-SocketIO==5.3.4",
|
||||
"Flask-SocketIO==5.3.6",
|
||||
"eventlet==0.33.3",
|
||||
"requests-oauthlib==1.3.1",
|
||||
"icmplib==3.0.3",
|
||||
"icmplib==3.0.4",
|
||||
"ariadne==0.20.1",
|
||||
"cryptography==41.0.2",
|
||||
"discord>=2.3.2"
|
||||
"cryptography==41.0.4",
|
||||
"discord==2.3.2"
|
||||
],
|
||||
"DevDependencies": [
|
||||
"cpl-cli==2023.4.0.post3",
|
||||
@@ -68,6 +68,8 @@
|
||||
"../modules/database/database.json",
|
||||
"../modules/level/level.json",
|
||||
"../modules/permission/permission.json",
|
||||
"../modules/short_role_name/short-role-name.json",
|
||||
"../modules/special_offers/special-offers.json",
|
||||
"../modules/technician/technician.json"
|
||||
]
|
||||
}
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot.extension"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -13,4 +13,6 @@ class InitBotExtension(ApplicationExtensionABC):
|
||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||
settings = config.get_configuration(TechnicianConfig)
|
||||
|
||||
bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC, max_messages=settings.cache_max_messages)
|
||||
bot: DiscordBotServiceABC = services.get_service(
|
||||
DiscordBotServiceABC, max_messages=settings.cache_max_messages
|
||||
)
|
@@ -13,6 +13,8 @@ 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.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
|
||||
|
||||
|
||||
@@ -35,6 +37,8 @@ class ModuleList:
|
||||
ApiModule,
|
||||
TechnicianModule,
|
||||
AchievementsModule,
|
||||
ShortRoleNameModule,
|
||||
SteamSpecialOffersModule,
|
||||
# has to be last!
|
||||
BootLogModule,
|
||||
CoreExtensionModule,
|
@@ -16,6 +16,7 @@ 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.message_logger import MessageLogger
|
||||
from bot_core.logging.task_logger import TaskLogger
|
||||
from bot_data.db_context import DBContext
|
||||
|
||||
|
||||
@@ -43,12 +44,15 @@ class Startup(StartupABC):
|
||||
services.add_singleton(CustomFileLoggerABC, CommandLogger)
|
||||
services.add_singleton(CustomFileLoggerABC, DatabaseLogger)
|
||||
services.add_singleton(CustomFileLoggerABC, MessageLogger)
|
||||
services.add_singleton(CustomFileLoggerABC, TaskLogger)
|
||||
|
||||
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||
services.add_singleton(CustomFileLoggerABC, ApiLogger)
|
||||
|
||||
services.add_translation()
|
||||
services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings))
|
||||
services.add_db_context(
|
||||
DBContext, self._config.get_configuration(DatabaseSettings)
|
||||
)
|
||||
|
||||
provider = services.build_service_provider()
|
||||
# instantiate custom logger
|
@@ -9,9 +9,13 @@ class StartupDiscordExtension(StartupExtensionABC):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
pass
|
||||
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
services.add_discord()
|
||||
dcc = get_discord_collection(services)
|
106
bot/src/bot/startup_migration_extension.py
Normal file
106
bot/src/bot/startup_migration_extension.py
Normal file
@@ -0,0 +1,106 @@
|
||||
from cpl_core.application import StartupExtensionABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceCollectionABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
|
||||
from bot_data.abc.migration_abc import MigrationABC
|
||||
from bot_data.migration.achievements_migration import AchievementsMigration
|
||||
from bot_data.migration.api_key_migration import ApiKeyMigration
|
||||
from bot_data.migration.api_migration import ApiMigration
|
||||
from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration
|
||||
from bot_data.migration.auto_role_migration import AutoRoleMigration
|
||||
from bot_data.migration.birthday_migration import BirthdayMigration
|
||||
from bot_data.migration.config_feature_flags_migration import (
|
||||
ConfigFeatureFlagsMigration,
|
||||
)
|
||||
from bot_data.migration.config_migration import ConfigMigration
|
||||
from bot_data.migration.db_history_migration import DBHistoryMigration
|
||||
from bot_data.migration.default_role_migration import DefaultRoleMigration
|
||||
from bot_data.migration.fix_updates_migration import FixUpdatesMigration
|
||||
from bot_data.migration.fix_user_history_migration import FixUserHistoryMigration
|
||||
from bot_data.migration.initial_migration import InitialMigration
|
||||
from bot_data.migration.level_migration import LevelMigration
|
||||
from bot_data.migration.remove_stats_migration import RemoveStatsMigration
|
||||
from bot_data.migration.short_role_name_migration import ShortRoleNameMigration
|
||||
from bot_data.migration.short_role_name_only_highest_migration import (
|
||||
ShortRoleNameOnlyHighestMigration,
|
||||
)
|
||||
from bot_data.migration.stats_migration import StatsMigration
|
||||
from bot_data.migration.steam_special_offer_migration import SteamSpecialOfferMigration
|
||||
from bot_data.migration.user_joined_game_server_migration import (
|
||||
UserJoinedGameServerMigration,
|
||||
)
|
||||
from bot_data.migration.user_message_count_per_hour_migration import (
|
||||
UserMessageCountPerHourMigration,
|
||||
)
|
||||
from bot_data.migration.user_warning_migration import UserWarningMigration
|
||||
from bot_data.service.migration_service import MigrationService
|
||||
|
||||
|
||||
class StartupMigrationExtension(StartupExtensionABC):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
pass
|
||||
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
services.add_transient(MigrationService)
|
||||
services.add_transient(MigrationABC, InitialMigration)
|
||||
services.add_transient(
|
||||
MigrationABC, AutoRoleMigration
|
||||
) # 03.10.2022 #54 - 0.2.2
|
||||
services.add_transient(MigrationABC, ApiMigration) # 15.10.2022 #70 - 0.3.0
|
||||
services.add_transient(MigrationABC, LevelMigration) # 06.11.2022 #25 - 0.3.0
|
||||
services.add_transient(MigrationABC, StatsMigration) # 09.11.2022 #46 - 0.3.0
|
||||
services.add_transient(
|
||||
MigrationABC, AutoRoleFix1Migration
|
||||
) # 30.12.2022 #151 - 0.3.0
|
||||
services.add_transient(
|
||||
MigrationABC, UserMessageCountPerHourMigration
|
||||
) # 11.01.2023 #168 - 0.3.1
|
||||
services.add_transient(MigrationABC, ApiKeyMigration) # 09.02.2023 #162 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, UserJoinedGameServerMigration
|
||||
) # 12.02.2023 #181 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, RemoveStatsMigration
|
||||
) # 19.02.2023 #190 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, UserWarningMigration
|
||||
) # 21.02.2023 #35 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, DBHistoryMigration
|
||||
) # 06.03.2023 #246 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, AchievementsMigration
|
||||
) # 14.06.2023 #268 - 1.1.0
|
||||
services.add_transient(MigrationABC, ConfigMigration) # 19.07.2023 #127 - 1.1.0
|
||||
services.add_transient(
|
||||
MigrationABC, ConfigFeatureFlagsMigration
|
||||
) # 15.08.2023 #334 - 1.1.0
|
||||
services.add_transient(
|
||||
MigrationABC, DefaultRoleMigration
|
||||
) # 24.09.2023 #360 - 1.1.3
|
||||
services.add_transient(
|
||||
MigrationABC, ShortRoleNameMigration
|
||||
) # 28.09.2023 #378 - 1.1.7
|
||||
services.add_transient(
|
||||
MigrationABC, FixUpdatesMigration
|
||||
) # 28.09.2023 #378 - 1.1.7
|
||||
services.add_transient(
|
||||
MigrationABC, ShortRoleNameOnlyHighestMigration
|
||||
) # 02.10.2023 #391 - 1.1.9
|
||||
services.add_transient(
|
||||
MigrationABC, FixUserHistoryMigration
|
||||
) # 10.10.2023 #401 - 1.2.0
|
||||
services.add_transient(
|
||||
MigrationABC, BirthdayMigration
|
||||
) # 10.10.2023 #401 - 1.2.0
|
||||
services.add_transient(
|
||||
MigrationABC, SteamSpecialOfferMigration
|
||||
) # 10.10.2023 #188 - 1.2.0
|
@@ -18,11 +18,15 @@ class StartupModuleExtension(StartupExtensionABC):
|
||||
|
||||
self._modules = ModuleList.get_modules()
|
||||
|
||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
self._config = config
|
||||
self._feature_flags = config.get_configuration(FeatureFlagsSettings)
|
||||
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
provider = services.build_service_provider()
|
||||
dc_collection: DiscordCollectionABC = provider.get_service(DiscordCollectionABC)
|
||||
|
@@ -14,26 +14,38 @@ class StartupSettingsExtension(StartupExtensionABC):
|
||||
def __init__(self):
|
||||
self._start_time = datetime.now()
|
||||
|
||||
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC):
|
||||
def configure_configuration(
|
||||
self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC
|
||||
):
|
||||
# this shit has to be done here because we need settings in subsequent startup extensions
|
||||
environment.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
|
||||
configuration.add_environment_variables("KDB_")
|
||||
configuration.add_environment_variables("DISCORD_")
|
||||
|
||||
configuration.add_json_file(f"config/appsettings.json", optional=False)
|
||||
configuration.add_json_file(f"config/appsettings.{environment.environment_name}.json", optional=True)
|
||||
configuration.add_json_file(f"config/appsettings.{environment.host_name}.json", optional=True)
|
||||
configuration.add_json_file(
|
||||
f"config/appsettings.{environment.environment_name}.json", optional=True
|
||||
)
|
||||
configuration.add_json_file(
|
||||
f"config/appsettings.{environment.host_name}.json", optional=True
|
||||
)
|
||||
# load feature-flags
|
||||
configuration.add_json_file(f"config/feature-flags.json", optional=False)
|
||||
configuration.add_json_file(f"config/feature-flags.{environment.environment_name}.json", optional=True)
|
||||
configuration.add_json_file(f"config/feature-flags.{environment.host_name}.json", optional=True)
|
||||
configuration.add_json_file(
|
||||
f"config/feature-flags.{environment.environment_name}.json", optional=True
|
||||
)
|
||||
configuration.add_json_file(
|
||||
f"config/feature-flags.{environment.host_name}.json", optional=True
|
||||
)
|
||||
|
||||
configuration.add_configuration("Startup_StartTime", str(self._start_time))
|
||||
self._configure_settings_with_sub_settings(
|
||||
configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key
|
||||
)
|
||||
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@@ -45,4 +57,6 @@ class StartupSettingsExtension(StartupExtensionABC):
|
||||
return
|
||||
|
||||
for sub_settings in list_atr(settings):
|
||||
config.add_configuration(f"{type(sub_settings).__name__}_{atr(sub_settings)}", sub_settings)
|
||||
config.add_configuration(
|
||||
f"{type(sub_settings).__name__}_{atr(sub_settings)}", sub_settings
|
||||
)
|
@@ -21,7 +21,6 @@
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"feature_not_activated": "Diese Funktion ist deaktiviert",
|
||||
"bot_has_no_permission_message": "Ey!!!\nWas soll das?\nIch habe keine Berechtigungen :(\nScheiß System...",
|
||||
"colors": {
|
||||
"blue": "Blau",
|
||||
@@ -83,6 +82,7 @@
|
||||
"unexpected_quote_error": "Fehler: Unerwarteter Fehler beim Anführungszeichen!",
|
||||
"user_input_error": "Fehler: Eingabefehler!"
|
||||
},
|
||||
"feature_not_activated": "Diese Funktion ist deaktiviert",
|
||||
"hello_world": "Hallo Welt",
|
||||
"no_permission_message": "Nein!\nIch höre nicht auf dich ¯\\_(ツ)_/¯",
|
||||
"not_implemented_yet": "Ey Alter, das kann ich noch nicht...",
|
||||
@@ -94,11 +94,16 @@
|
||||
}
|
||||
},
|
||||
"modules": {
|
||||
"special_offers": {
|
||||
"price": "Preis",
|
||||
"discount": "Rabatt",
|
||||
"discount_price": "Neuer Preis"
|
||||
},
|
||||
"achievements": {
|
||||
"got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D",
|
||||
"commands": {
|
||||
"check": "Alles klar, ich schaue eben nach... nom nom"
|
||||
}
|
||||
},
|
||||
"got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D"
|
||||
},
|
||||
"auto_role": {
|
||||
"add": {
|
||||
@@ -123,6 +128,9 @@
|
||||
},
|
||||
"success": "auto-role {} wurde entfernt :D"
|
||||
},
|
||||
"react": {
|
||||
"success": "Alle Reaktionen wurden hinzugefügt"
|
||||
},
|
||||
"rule": {
|
||||
"add": {
|
||||
"error": {
|
||||
@@ -152,38 +160,37 @@
|
||||
}
|
||||
},
|
||||
"base": {
|
||||
"member_left_message": "{} hat uns leider verlassen :(",
|
||||
"complaints": {
|
||||
"title": "Beschwerde einreichen",
|
||||
"label": "Beschwerde",
|
||||
"message": "{} hat eine Beschwerde eingereicht:\n{}",
|
||||
"response": "Danke für deine Beschwerde"
|
||||
},
|
||||
"bug": {
|
||||
"title": "Bug melden",
|
||||
"label": "Bug",
|
||||
"message": "{} meldet einen Bug:\n{}",
|
||||
"response": "Danke für dein Feedback :D"
|
||||
},
|
||||
"afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?",
|
||||
"afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)",
|
||||
"bug": {
|
||||
"label": "Bug",
|
||||
"message": "{} meldet einen Bug:\n{}",
|
||||
"response": "Danke für dein Feedback :D",
|
||||
"title": "Bug melden"
|
||||
},
|
||||
"complaints": {
|
||||
"label": "Beschwerde",
|
||||
"message": "{} hat eine Beschwerde eingereicht:\n{}",
|
||||
"response": "Danke für deine Beschwerde",
|
||||
"title": "Beschwerde einreichen"
|
||||
},
|
||||
"game_server": {
|
||||
"add": {
|
||||
"success": "Gameserver {} wurde hinzugefügt :)"
|
||||
},
|
||||
"error": {
|
||||
"nothing_found": "Keine Gameserver gefunden."
|
||||
},
|
||||
"list_members": {
|
||||
"title": "Mitglieder",
|
||||
"description": "Konfigurierte Mitglieder:",
|
||||
"users": "Mitglieder"
|
||||
},
|
||||
"list": {
|
||||
"title": "Gameserver",
|
||||
"api_key": "API Key",
|
||||
"description": "Konfigurierte Gameserver:",
|
||||
"name": "Name",
|
||||
"api_key": "API Key"
|
||||
"title": "Gameserver"
|
||||
},
|
||||
"add": {
|
||||
"success": "Gameserver {} wurde hinzugefügt :)"
|
||||
"list_members": {
|
||||
"description": "Konfigurierte Mitglieder:",
|
||||
"title": "Mitglieder",
|
||||
"users": "Mitglieder"
|
||||
},
|
||||
"remove": {
|
||||
"success": "Gameserver wurde entfernt :D"
|
||||
@@ -210,6 +217,7 @@
|
||||
"moved": "Alle Personen aus {} wurden nach {} verschoben."
|
||||
},
|
||||
"member_joined_help_voice_channel": "{} braucht Hilfe, bitte kümmere dich drum :D",
|
||||
"member_left_message": "{} hat uns leider verlassen :(",
|
||||
"pong": "Pong",
|
||||
"presence": {
|
||||
"changed": "Presence wurde geändert.",
|
||||
@@ -226,6 +234,11 @@
|
||||
"success": "Verlinkung wurde entfernt :D"
|
||||
},
|
||||
"user": {
|
||||
"birthday": {
|
||||
"has_birthday": "Alles Gute zum Geburtag {} :D",
|
||||
"success": "Dein Geburtstag wurde eingetragen.",
|
||||
"success_team": "{} hat seinen Geburtstag eingetragen: {}"
|
||||
},
|
||||
"add": {
|
||||
"xp": "Die {} von {} wurden um {} erhöht"
|
||||
},
|
||||
@@ -346,6 +359,9 @@
|
||||
"moderator": {
|
||||
"purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss."
|
||||
},
|
||||
"short_role_name": {
|
||||
"checked_message": "Die Rollen Kürzel wurden überprüft"
|
||||
},
|
||||
"technician": {
|
||||
"api_key": {
|
||||
"add": {
|
||||
@@ -357,10 +373,10 @@
|
||||
"success": "API-Schlüssel wurde entfernt :D"
|
||||
}
|
||||
},
|
||||
"synced_message": "Der Sync wurde abgeschlossen.",
|
||||
"log_message": "Hier sind deine Logdateien! :)",
|
||||
"restart_message": "Bin gleich wieder da :D",
|
||||
"shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, euer Freund. Lebt lange und in Frieden :)"
|
||||
"shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, euer Freund. Lebt lange und in Frieden :)",
|
||||
"synced_message": "Der Sync wurde abgeschlossen."
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.abc"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -40,11 +40,15 @@ class AuthServiceABC(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO:
|
||||
async def get_filtered_auth_users_async(
|
||||
self, criteria: AuthUserSelectCriteria
|
||||
) -> AuthUserFilteredResultDTO:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO:
|
||||
async def get_auth_user_by_email_async(
|
||||
self, email: str, with_password: bool = False
|
||||
) -> AuthUserDTO:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
@@ -3,7 +3,9 @@ from abc import ABC, abstractmethod
|
||||
|
||||
class SelectCriteriaABC(ABC):
|
||||
@abstractmethod
|
||||
def __init__(self, page_index: int, page_size: int, sort_direction: str, sort_column: str):
|
||||
def __init__(
|
||||
self, page_index: int, page_size: int, sort_direction: str, sort_column: str
|
||||
):
|
||||
self.page_index = page_index
|
||||
self.page_size = page_size
|
||||
self.sort_direction = sort_direction
|
@@ -57,7 +57,9 @@ class Api(Flask):
|
||||
# Added async_mode see link below
|
||||
# https://github.com/miguelgrinberg/Flask-SocketIO/discussions/1849
|
||||
# https://stackoverflow.com/questions/39370848/flask-socket-io-sometimes-client-calls-freeze-the-server
|
||||
self._socketio = SocketIO(self, cors_allowed_origins="*", path="/api/socket.io", async_mode="eventlet")
|
||||
self._socketio = SocketIO(
|
||||
self, cors_allowed_origins="*", path="/api/socket.io", async_mode="eventlet"
|
||||
)
|
||||
self._socketio.on_event("connect", self.on_connect)
|
||||
self._socketio.on_event("disconnect", self.on_disconnect)
|
||||
|
||||
@@ -143,19 +145,26 @@ class Api(Flask):
|
||||
data = request.get_data()
|
||||
data = "" if len(data) == 0 else str(data.decode(encoding="utf-8"))
|
||||
|
||||
text = textwrap.dedent(f"Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}")
|
||||
text = textwrap.dedent(
|
||||
f"Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}"
|
||||
)
|
||||
self._logger.trace(__name__, text)
|
||||
|
||||
return response
|
||||
|
||||
def start(self):
|
||||
self._logger.info(__name__, f"Starting API {self._api_settings.host}:{self._api_settings.port}")
|
||||
self._logger.info(
|
||||
__name__,
|
||||
f"Starting API {self._api_settings.host}:{self._api_settings.port}",
|
||||
)
|
||||
self._register_routes()
|
||||
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
|
||||
# from waitress import serve
|
||||
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html
|
||||
# serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10)
|
||||
self._socket = eventlet.listen((self._api_settings.host, self._api_settings.port))
|
||||
self._socket = eventlet.listen(
|
||||
(self._api_settings.host, self._api_settings.port)
|
||||
)
|
||||
wsgi.server(self._socket, self, log_output=False)
|
||||
|
||||
def stop(self):
|
@@ -26,15 +26,21 @@ class ApiModule(ModuleABC):
|
||||
def __init__(self, dc: DiscordCollectionABC):
|
||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.api_module)
|
||||
|
||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
cwd = env.working_directory
|
||||
env.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
|
||||
config.add_json_file(f"config/apisettings.json", optional=False)
|
||||
config.add_json_file(f"config/apisettings.{env.environment_name}.json", optional=True)
|
||||
config.add_json_file(
|
||||
f"config/apisettings.{env.environment_name}.json", optional=True
|
||||
)
|
||||
config.add_json_file(f"config/apisettings.{env.host_name}.json", optional=True)
|
||||
env.set_working_directory(cwd)
|
||||
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
services.add_singleton(EMailClientABC, EMailClient)
|
||||
|
||||
services.add_singleton(ApiThread)
|
||||
@@ -48,4 +54,4 @@ class ApiModule(ModuleABC):
|
||||
services.add_transient(GraphQLController)
|
||||
|
||||
# cpl-discord
|
||||
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)
|
||||
services.add_transient(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)
|
@@ -12,7 +12,9 @@ class AppApiExtension(ApplicationExtensionABC):
|
||||
ApplicationExtensionABC.__init__(self)
|
||||
|
||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||
feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings)
|
||||
feature_flags: FeatureFlagsSettings = config.get_configuration(
|
||||
FeatureFlagsSettings
|
||||
)
|
||||
if not feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||
return
|
||||
|
@@ -3,8 +3,8 @@
|
||||
"Name": "bot-api",
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "1",
|
||||
"Micro": "6"
|
||||
"Minor": "2",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "",
|
||||
"AuthorEmail": "",
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.configuration"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -16,7 +16,9 @@ class AuthenticationSettings(ConfigurationModelABC):
|
||||
self._issuer = "" if issuer is None else issuer
|
||||
self._audience = "" if audience is None else audience
|
||||
self._token_expire_time = 0 if token_expire_time is None else token_expire_time
|
||||
self._refresh_token_expire_time = 0 if refresh_token_expire_time is None else refresh_token_expire_time
|
||||
self._refresh_token_expire_time = (
|
||||
0 if refresh_token_expire_time is None else refresh_token_expire_time
|
||||
)
|
||||
|
||||
@property
|
||||
def secret_key(self) -> str:
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.controller"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -70,7 +70,9 @@ class AuthController:
|
||||
|
||||
@Route.post(f"{BasePath}/register")
|
||||
async def register(self):
|
||||
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
||||
dto: AuthUserDTO = JSONProcessor.process(
|
||||
AuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
self._auth_service.add_auth_user(dto)
|
||||
return "", 200
|
||||
|
||||
@@ -81,7 +83,9 @@ class AuthController:
|
||||
|
||||
@Route.post(f"{BasePath}/login")
|
||||
async def login(self) -> Response:
|
||||
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
||||
dto: AuthUserDTO = JSONProcessor.process(
|
||||
AuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
result = await self._auth_service.login_async(dto)
|
||||
return jsonify(result.to_dict())
|
||||
|
||||
@@ -110,40 +114,52 @@ class AuthController:
|
||||
|
||||
@Route.post(f"{BasePath}/reset-password")
|
||||
async def reset_password(self):
|
||||
dto: ResetPasswordDTO = JSONProcessor.process(ResetPasswordDTO, request.get_json(force=True, silent=True))
|
||||
dto: ResetPasswordDTO = JSONProcessor.process(
|
||||
ResetPasswordDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
await self._auth_service.reset_password_async(dto)
|
||||
return "", 200
|
||||
|
||||
@Route.post(f"{BasePath}/update-user")
|
||||
@Route.authorize
|
||||
async def update_user(self):
|
||||
dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True))
|
||||
dto: UpdateAuthUserDTO = JSONProcessor.process(
|
||||
UpdateAuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
await self._auth_service.update_user_async(dto)
|
||||
return "", 200
|
||||
|
||||
@Route.post(f"{BasePath}/update-user-as-admin")
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def update_user_as_admin(self):
|
||||
dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True))
|
||||
dto: UpdateAuthUserDTO = JSONProcessor.process(
|
||||
UpdateAuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
await self._auth_service.update_user_as_admin_async(dto)
|
||||
return "", 200
|
||||
|
||||
@Route.post(f"{BasePath}/refresh")
|
||||
async def refresh(self) -> Response:
|
||||
dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True))
|
||||
dto: TokenDTO = JSONProcessor.process(
|
||||
TokenDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
result = await self._auth_service.refresh_async(dto)
|
||||
return jsonify(result.to_dict())
|
||||
|
||||
@Route.post(f"{BasePath}/revoke")
|
||||
async def revoke(self):
|
||||
dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True))
|
||||
dto: TokenDTO = JSONProcessor.process(
|
||||
TokenDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
await self._auth_service.revoke_async(dto)
|
||||
return "", 200
|
||||
|
||||
@Route.post(f"{BasePath}/delete-user")
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def delete_user(self):
|
||||
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
||||
dto: AuthUserDTO = JSONProcessor.process(
|
||||
AuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
await self._auth_service.delete_auth_user_async(dto)
|
||||
return "", 200
|
||||
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.event"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.exception"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.filter"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -13,7 +13,9 @@ class AuthUserSelectCriteria(SelectCriteriaABC):
|
||||
email: str,
|
||||
auth_role: int,
|
||||
):
|
||||
SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column)
|
||||
SelectCriteriaABC.__init__(
|
||||
self, page_index, page_size, sort_direction, sort_column
|
||||
)
|
||||
|
||||
self.first_name = first_name
|
||||
self.last_name = last_name
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.filter.discord"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -10,6 +10,8 @@ class ServerSelectCriteria(SelectCriteriaABC):
|
||||
sort_column: str,
|
||||
name: str,
|
||||
):
|
||||
SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column)
|
||||
SelectCriteriaABC.__init__(
|
||||
self, page_index, page_size, sort_direction, sort_column
|
||||
)
|
||||
|
||||
self.name = name
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.logging"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.model"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.model.discord"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -11,7 +11,9 @@ class ErrorDTO(DtoABC):
|
||||
def __init__(self, error_code: Optional[ServiceErrorCode], message: str):
|
||||
DtoABC.__init__(self)
|
||||
|
||||
self._error_code = ServiceErrorCode.Unknown if error_code is None else error_code
|
||||
self._error_code = (
|
||||
ServiceErrorCode.Unknown if error_code is None else error_code
|
||||
)
|
||||
self._message = message
|
||||
|
||||
@property
|
@@ -27,4 +27,8 @@ class TokenDTO(DtoABC):
|
||||
self._first_login = values["firstLogin"]
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {"token": self._token, "refreshToken": self._refresh_token, "firstLogin": self._first_login}
|
||||
return {
|
||||
"token": self._token,
|
||||
"refreshToken": self._refresh_token,
|
||||
"firstLogin": self._first_login,
|
||||
}
|
@@ -34,7 +34,9 @@ class UpdateAuthUserDTO(DtoABC):
|
||||
def from_dict(self, values: dict):
|
||||
self._auth_user = AuthUserDTO().from_dict(values["authUser"])
|
||||
self._new_auth_user = AuthUserDTO().from_dict(values["newAuthUser"])
|
||||
self._change_password = False if "changePassword" not in values else bool(values["changePassword"])
|
||||
self._change_password = (
|
||||
False if "changePassword" not in values else bool(values["changePassword"])
|
||||
)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.route"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -25,7 +25,12 @@ class Route:
|
||||
|
||||
@classmethod
|
||||
@ServiceProviderABC.inject
|
||||
def init_authorize(cls, env: ApplicationEnvironmentABC, auth_users: AuthUserRepositoryABC, auth: AuthServiceABC):
|
||||
def init_authorize(
|
||||
cls,
|
||||
env: ApplicationEnvironmentABC,
|
||||
auth_users: AuthUserRepositoryABC,
|
||||
auth: AuthServiceABC,
|
||||
):
|
||||
cls._auth_users = auth_users
|
||||
cls._auth = auth
|
||||
cls._env = env.environment_name
|
||||
@@ -52,9 +57,17 @@ class Route:
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
def authorize(cls, f: Callable = None, role: AuthRoleEnum = None, skip_in_dev=False, by_api_key=False):
|
||||
def authorize(
|
||||
cls,
|
||||
f: Callable = None,
|
||||
role: AuthRoleEnum = None,
|
||||
skip_in_dev=False,
|
||||
by_api_key=False,
|
||||
):
|
||||
if f is None:
|
||||
return functools.partial(cls.authorize, role=role, skip_in_dev=skip_in_dev, by_api_key=by_api_key)
|
||||
return functools.partial(
|
||||
cls.authorize, role=role, skip_in_dev=skip_in_dev, by_api_key=by_api_key
|
||||
)
|
||||
|
||||
@wraps(f)
|
||||
async def decorator(*args, **kwargs):
|
||||
@@ -65,7 +78,9 @@ class Route:
|
||||
api_key = None
|
||||
if "Authorization" in request.headers:
|
||||
if " " not in request.headers.get("Authorization"):
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set")
|
||||
ex = ServiceException(
|
||||
ServiceErrorCode.Unauthorized, f"Token not set"
|
||||
)
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
@@ -87,7 +102,9 @@ class Route:
|
||||
return jsonify(e), 500
|
||||
|
||||
if not valid:
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"API-Key invalid")
|
||||
ex = ServiceException(
|
||||
ServiceErrorCode.Unauthorized, f"API-Key invalid"
|
||||
)
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
@@ -99,7 +116,9 @@ class Route:
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
if cls._auth_users is None or cls._auth is None:
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Authorize is not initialized")
|
||||
ex = ServiceException(
|
||||
ServiceErrorCode.Unauthorized, f"Authorize is not initialized"
|
||||
)
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
@@ -121,7 +140,9 @@ class Route:
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
if role is not None and user.auth_role.value < role.value:
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Role {role} required")
|
||||
ex = ServiceException(
|
||||
ServiceErrorCode.Unauthorized, f"Role {role} required"
|
||||
)
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 403
|
||||
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.service"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -90,7 +90,9 @@ class AuthService(AuthServiceABC):
|
||||
|
||||
def _get_api_key_str(self, api_key: ApiKey) -> str:
|
||||
return hashlib.sha256(
|
||||
f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode("utf-8")
|
||||
f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode(
|
||||
"utf-8"
|
||||
)
|
||||
).hexdigest()
|
||||
|
||||
def generate_token(self, user: AuthUser) -> str:
|
||||
@@ -99,7 +101,8 @@ class AuthService(AuthServiceABC):
|
||||
"user_id": user.id,
|
||||
"email": user.email,
|
||||
"role": user.auth_role.value,
|
||||
"exp": datetime.now(tz=timezone.utc) + timedelta(days=self._auth_settings.token_expire_time),
|
||||
"exp": datetime.now(tz=timezone.utc)
|
||||
+ timedelta(days=self._auth_settings.token_expire_time),
|
||||
"iss": self._auth_settings.issuer,
|
||||
"aud": self._auth_settings.audience,
|
||||
},
|
||||
@@ -155,7 +158,9 @@ class AuthService(AuthServiceABC):
|
||||
def _create_and_save_refresh_token(self, user: AuthUser) -> str:
|
||||
token = str(uuid.uuid4())
|
||||
user.refresh_token = token
|
||||
user.refresh_token_expire_time = datetime.now() + timedelta(days=self._auth_settings.refresh_token_expire_time)
|
||||
user.refresh_token_expire_time = datetime.now() + timedelta(
|
||||
days=self._auth_settings.refresh_token_expire_time
|
||||
)
|
||||
self._auth_users.update_auth_user(user)
|
||||
self._db.save_changes()
|
||||
return token
|
||||
@@ -188,8 +193,12 @@ class AuthService(AuthServiceABC):
|
||||
|
||||
self._send_link_mail(
|
||||
user.email,
|
||||
self._t.transform("api.auth.confirmation.subject").format(user.first_name, user.last_name),
|
||||
self._t.transform("api.auth.confirmation.message").format(url, user.confirmation_id),
|
||||
self._t.transform("api.auth.confirmation.subject").format(
|
||||
user.first_name, user.last_name
|
||||
),
|
||||
self._t.transform("api.auth.confirmation.message").format(
|
||||
url, user.confirmation_id
|
||||
),
|
||||
)
|
||||
|
||||
def _send_forgot_password_id_to_user(self, user: AuthUser):
|
||||
@@ -199,28 +208,38 @@ class AuthService(AuthServiceABC):
|
||||
|
||||
self._send_link_mail(
|
||||
user.email,
|
||||
self._t.transform("api.auth.forgot_password.subject").format(user.first_name, user.last_name),
|
||||
self._t.transform("api.auth.forgot_password.message").format(url, user.forgot_password_id),
|
||||
self._t.transform("api.auth.forgot_password.subject").format(
|
||||
user.first_name, user.last_name
|
||||
),
|
||||
self._t.transform("api.auth.forgot_password.message").format(
|
||||
url, user.forgot_password_id
|
||||
),
|
||||
)
|
||||
|
||||
async def get_all_auth_users_async(self) -> List[AuthUserDTO]:
|
||||
result = self._auth_users.get_all_auth_users().select(lambda x: AUT.to_dto(x))
|
||||
return List(AuthUserDTO, result)
|
||||
|
||||
async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO:
|
||||
async def get_filtered_auth_users_async(
|
||||
self, criteria: AuthUserSelectCriteria
|
||||
) -> AuthUserFilteredResultDTO:
|
||||
users = self._auth_users.get_filtered_auth_users(criteria)
|
||||
result = users.result.select(lambda x: AUT.to_dto(x))
|
||||
|
||||
return AuthUserFilteredResultDTO(List(AuthUserDTO, result), users.total_count)
|
||||
|
||||
async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO:
|
||||
async def get_auth_user_by_email_async(
|
||||
self, email: str, with_password: bool = False
|
||||
) -> AuthUserDTO:
|
||||
try:
|
||||
# todo: check if logged in user is admin then send mail
|
||||
user = self._auth_users.get_auth_user_by_email(email)
|
||||
return AUT.to_dto(user, password=user.password if with_password else None)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"AuthUser not found", e)
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"User not found {email}")
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidData, f"User not found {email}"
|
||||
)
|
||||
|
||||
async def find_auth_user_by_email_async(self, email: str) -> Optional[AuthUser]:
|
||||
user = self._auth_users.find_auth_user_by_email(email)
|
||||
@@ -238,16 +257,22 @@ class AuthService(AuthServiceABC):
|
||||
user.password_salt = uuid.uuid4()
|
||||
user.password = self._hash_sha256(user_dto.password, user.password_salt)
|
||||
if not self._is_email_valid(user.email):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "Invalid E-Mail address")
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidData, "Invalid E-Mail address"
|
||||
)
|
||||
|
||||
try:
|
||||
user.confirmation_id = uuid.uuid4()
|
||||
self._auth_users.add_auth_user(user)
|
||||
self._send_confirmation_id_to_user(user)
|
||||
self._db.save_changes()
|
||||
self._logger.info(__name__, f"Added auth user with E-Mail: {user_dto.email}")
|
||||
self._logger.info(
|
||||
__name__, f"Added auth user with E-Mail: {user_dto.email}"
|
||||
)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot add user with E-Mail {user_dto.email}", e)
|
||||
self._logger.error(
|
||||
__name__, f"Cannot add user with E-Mail {user_dto.email}", e
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
|
||||
|
||||
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO):
|
||||
@@ -263,14 +288,20 @@ class AuthService(AuthServiceABC):
|
||||
db_user.first_name = dto.user.first_name
|
||||
db_user.last_name = dto.user.last_name
|
||||
db_user.password_salt = uuid.uuid4()
|
||||
db_user.password = self._hash_sha256(dto.user.password, db_user.password_salt)
|
||||
db_user.password = self._hash_sha256(
|
||||
dto.user.password, db_user.password_salt
|
||||
)
|
||||
db_user.oauth_id = None
|
||||
db_user.confirmation_id = uuid.uuid4()
|
||||
self._send_confirmation_id_to_user(db_user)
|
||||
self._auth_users.update_auth_user(db_user)
|
||||
self._logger.info(__name__, f"Added auth user with E-Mail: {dto.user.email}")
|
||||
self._logger.info(
|
||||
__name__, f"Added auth user with E-Mail: {dto.user.email}"
|
||||
)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot add user with E-Mail {dto.user.email}", e)
|
||||
self._logger.error(
|
||||
__name__, f"Cannot add user with E-Mail {dto.user.email}", e
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
|
||||
|
||||
self._db.save_changes()
|
||||
@@ -280,14 +311,16 @@ class AuthService(AuthServiceABC):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
||||
|
||||
if update_user_dto.auth_user is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Existing user is empty")
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidData, f"Existing user is empty"
|
||||
)
|
||||
|
||||
if update_user_dto.new_auth_user is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"New user is empty")
|
||||
|
||||
if not self._is_email_valid(update_user_dto.auth_user.email) or not self._is_email_valid(
|
||||
update_user_dto.new_auth_user.email
|
||||
):
|
||||
if not self._is_email_valid(
|
||||
update_user_dto.auth_user.email
|
||||
) or not self._is_email_valid(update_user_dto.new_auth_user.email):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Invalid E-Mail")
|
||||
|
||||
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
|
||||
@@ -300,7 +333,8 @@ class AuthService(AuthServiceABC):
|
||||
# update first name
|
||||
if (
|
||||
update_user_dto.new_auth_user.first_name is not None
|
||||
and update_user_dto.auth_user.first_name != update_user_dto.new_auth_user.first_name
|
||||
and update_user_dto.auth_user.first_name
|
||||
!= update_user_dto.new_auth_user.first_name
|
||||
):
|
||||
user.first_name = update_user_dto.new_auth_user.first_name
|
||||
|
||||
@@ -308,7 +342,8 @@ class AuthService(AuthServiceABC):
|
||||
if (
|
||||
update_user_dto.new_auth_user.last_name is not None
|
||||
and update_user_dto.new_auth_user.last_name != ""
|
||||
and update_user_dto.auth_user.last_name != update_user_dto.new_auth_user.last_name
|
||||
and update_user_dto.auth_user.last_name
|
||||
!= update_user_dto.new_auth_user.last_name
|
||||
):
|
||||
user.last_name = update_user_dto.new_auth_user.last_name
|
||||
|
||||
@@ -318,22 +353,33 @@ class AuthService(AuthServiceABC):
|
||||
and update_user_dto.new_auth_user.email != ""
|
||||
and update_user_dto.auth_user.email != update_user_dto.new_auth_user.email
|
||||
):
|
||||
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(update_user_dto.new_auth_user.email)
|
||||
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(
|
||||
update_user_dto.new_auth_user.email
|
||||
)
|
||||
if user_by_new_e_mail is not None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists")
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidUser, "User already exists"
|
||||
)
|
||||
user.email = update_user_dto.new_auth_user.email
|
||||
|
||||
update_user_dto.auth_user.password = self._hash_sha256(update_user_dto.auth_user.password, user.password_salt)
|
||||
update_user_dto.auth_user.password = self._hash_sha256(
|
||||
update_user_dto.auth_user.password, user.password_salt
|
||||
)
|
||||
if update_user_dto.auth_user.password != user.password:
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password")
|
||||
|
||||
# update password
|
||||
if (
|
||||
update_user_dto.new_auth_user.password is not None
|
||||
and self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt) != user.password
|
||||
and self._hash_sha256(
|
||||
update_user_dto.new_auth_user.password, user.password_salt
|
||||
)
|
||||
!= user.password
|
||||
):
|
||||
user.password_salt = uuid.uuid4()
|
||||
user.password = self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt)
|
||||
user.password = self._hash_sha256(
|
||||
update_user_dto.new_auth_user.password, user.password_salt
|
||||
)
|
||||
|
||||
self._auth_users.update_auth_user(user)
|
||||
self._db.save_changes()
|
||||
@@ -343,23 +389,31 @@ class AuthService(AuthServiceABC):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
||||
|
||||
if update_user_dto.auth_user is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Existing user is empty")
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidData, f"Existing user is empty"
|
||||
)
|
||||
|
||||
if update_user_dto.new_auth_user is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"New user is empty")
|
||||
|
||||
if not self._is_email_valid(update_user_dto.auth_user.email) or not self._is_email_valid(
|
||||
update_user_dto.new_auth_user.email
|
||||
):
|
||||
if not self._is_email_valid(
|
||||
update_user_dto.auth_user.email
|
||||
) or not self._is_email_valid(update_user_dto.new_auth_user.email):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Invalid E-Mail")
|
||||
|
||||
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
|
||||
if user is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, "User not found")
|
||||
|
||||
if user.confirmation_id is not None and update_user_dto.new_auth_user.is_confirmed:
|
||||
if (
|
||||
user.confirmation_id is not None
|
||||
and update_user_dto.new_auth_user.is_confirmed
|
||||
):
|
||||
user.confirmation_id = None
|
||||
elif user.confirmation_id is None and not update_user_dto.new_auth_user.is_confirmed:
|
||||
elif (
|
||||
user.confirmation_id is None
|
||||
and not update_user_dto.new_auth_user.is_confirmed
|
||||
):
|
||||
user.confirmation_id = uuid.uuid4()
|
||||
# else
|
||||
# raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed')
|
||||
@@ -367,7 +421,8 @@ class AuthService(AuthServiceABC):
|
||||
# update first name
|
||||
if (
|
||||
update_user_dto.new_auth_user.first_name is not None
|
||||
and update_user_dto.auth_user.first_name != update_user_dto.new_auth_user.first_name
|
||||
and update_user_dto.auth_user.first_name
|
||||
!= update_user_dto.new_auth_user.first_name
|
||||
):
|
||||
user.first_name = update_user_dto.new_auth_user.first_name
|
||||
|
||||
@@ -375,7 +430,8 @@ class AuthService(AuthServiceABC):
|
||||
if (
|
||||
update_user_dto.new_auth_user.last_name is not None
|
||||
and update_user_dto.new_auth_user.last_name != ""
|
||||
and update_user_dto.auth_user.last_name != update_user_dto.new_auth_user.last_name
|
||||
and update_user_dto.auth_user.last_name
|
||||
!= update_user_dto.new_auth_user.last_name
|
||||
):
|
||||
user.last_name = update_user_dto.new_auth_user.last_name
|
||||
|
||||
@@ -385,19 +441,28 @@ class AuthService(AuthServiceABC):
|
||||
and update_user_dto.new_auth_user.email != ""
|
||||
and update_user_dto.auth_user.email != update_user_dto.new_auth_user.email
|
||||
):
|
||||
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(update_user_dto.new_auth_user.email)
|
||||
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(
|
||||
update_user_dto.new_auth_user.email
|
||||
)
|
||||
if user_by_new_e_mail is not None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists")
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidUser, "User already exists"
|
||||
)
|
||||
user.email = update_user_dto.new_auth_user.email
|
||||
|
||||
# update password
|
||||
if (
|
||||
update_user_dto.new_auth_user.password is not None
|
||||
and update_user_dto.change_password
|
||||
and user.password != self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt)
|
||||
and user.password
|
||||
!= self._hash_sha256(
|
||||
update_user_dto.new_auth_user.password, user.password_salt
|
||||
)
|
||||
):
|
||||
user.password_salt = uuid.uuid4()
|
||||
user.password = self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt)
|
||||
user.password = self._hash_sha256(
|
||||
update_user_dto.new_auth_user.password, user.password_salt
|
||||
)
|
||||
|
||||
# update role
|
||||
if (
|
||||
@@ -416,7 +481,9 @@ class AuthService(AuthServiceABC):
|
||||
self._db.save_changes()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot delete user", e)
|
||||
raise ServiceException(ServiceErrorCode.UnableToDelete, f"Cannot delete user by mail {email}")
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.UnableToDelete, f"Cannot delete user by mail {email}"
|
||||
)
|
||||
|
||||
async def delete_auth_user_async(self, user_dto: AuthUser):
|
||||
try:
|
||||
@@ -500,7 +567,9 @@ class AuthService(AuthServiceABC):
|
||||
if user.id in user_ids:
|
||||
continue
|
||||
|
||||
self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_user, user))
|
||||
self._auth_users.add_auth_user_user_rel(
|
||||
AuthUserUsersRelation(db_user, user)
|
||||
)
|
||||
|
||||
if db_user.confirmation_id is not None and not added_user:
|
||||
raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified")
|
||||
@@ -530,13 +599,19 @@ class AuthService(AuthServiceABC):
|
||||
):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "Token expired")
|
||||
|
||||
return TokenDTO(self.generate_token(user), self._create_and_save_refresh_token(user))
|
||||
return TokenDTO(
|
||||
self.generate_token(user), self._create_and_save_refresh_token(user)
|
||||
)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Refreshing token failed", e)
|
||||
return TokenDTO("", "")
|
||||
|
||||
async def revoke_async(self, token_dto: TokenDTO):
|
||||
if token_dto is None or token_dto.token is None or token_dto.refresh_token is None:
|
||||
if (
|
||||
token_dto is None
|
||||
or token_dto.token is None
|
||||
or token_dto.refresh_token is None
|
||||
):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "Token not set")
|
||||
|
||||
try:
|
||||
@@ -589,7 +664,9 @@ class AuthService(AuthServiceABC):
|
||||
)
|
||||
|
||||
if user.confirmation_id is not None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, f"E-Mail not confirmed")
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidUser, f"E-Mail not confirmed"
|
||||
)
|
||||
|
||||
if user.password is None or rp_dto.password == "":
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Password not set")
|
@@ -53,13 +53,17 @@ class DiscordService:
|
||||
if role != AuthRoleEnum.admin:
|
||||
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
||||
if auth_user is not None:
|
||||
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id)
|
||||
user_ids = auth_user.users.select(
|
||||
lambda x: x.server is not None and x.server.id
|
||||
)
|
||||
servers = servers.where(lambda x: x.id in user_ids)
|
||||
|
||||
servers = List(ServerDTO, servers)
|
||||
return servers.select(self._to_dto).where(lambda x: x.name != "")
|
||||
|
||||
async def get_filtered_servers_async(self, criteria: ServerSelectCriteria) -> ServerFilteredResultDTO:
|
||||
async def get_filtered_servers_async(
|
||||
self, criteria: ServerSelectCriteria
|
||||
) -> ServerFilteredResultDTO:
|
||||
token = self._auth.get_decoded_token_from_request()
|
||||
if token is None or "email" not in token or "role" not in token:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "Token invalid")
|
||||
@@ -70,15 +74,22 @@ class DiscordService:
|
||||
if role != AuthRoleEnum.admin:
|
||||
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
||||
if auth_user is not None:
|
||||
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id)
|
||||
filtered_result.result = filtered_result.result.where(lambda x: x.id in user_ids)
|
||||
user_ids = auth_user.users.select(
|
||||
lambda x: x.server is not None and x.server.id
|
||||
)
|
||||
filtered_result.result = filtered_result.result.where(
|
||||
lambda x: x.id in user_ids
|
||||
)
|
||||
|
||||
servers: List = filtered_result.result.select(self._to_dto).where(lambda x: x.name != "")
|
||||
servers: List = filtered_result.result.select(self._to_dto).where(
|
||||
lambda x: x.name != ""
|
||||
)
|
||||
result = List(ServerDTO, servers)
|
||||
|
||||
if criteria.name is not None and criteria.name != "":
|
||||
result = result.where(
|
||||
lambda x: criteria.name.lower() in x.name.lower() or x.name.lower() == criteria.name.lower()
|
||||
lambda x: criteria.name.lower() in x.name.lower()
|
||||
or x.name.lower() == criteria.name.lower()
|
||||
)
|
||||
|
||||
return ServerFilteredResultDTO(List(ServerDTO, result), servers.count())
|
||||
@@ -87,5 +98,7 @@ class DiscordService:
|
||||
server = self._servers.get_server_by_id(id)
|
||||
guild = self._bot.get_guild(server.discord_id)
|
||||
|
||||
server_dto = ServerTransformer.to_dto(server, guild.name, guild.member_count, guild.icon)
|
||||
server_dto = ServerTransformer.to_dto(
|
||||
server, guild.name, guild.member_count, guild.icon
|
||||
)
|
||||
return server_dto
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_api.transformer"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -27,27 +27,35 @@ class AuthUserTransformer(TransformerABC):
|
||||
None,
|
||||
None,
|
||||
datetime.now(),
|
||||
AuthRoleEnum.normal if dto.auth_role is None else AuthRoleEnum(dto.auth_role),
|
||||
AuthRoleEnum.normal
|
||||
if dto.auth_role is None
|
||||
else AuthRoleEnum(dto.auth_role),
|
||||
auth_user_id=0 if dto.id is None else dto.id,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@ServiceProviderABC.inject
|
||||
def _is_technician(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
|
||||
def _is_technician(
|
||||
user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC
|
||||
):
|
||||
guild = bot.get_guild(user.server.discord_id)
|
||||
member = guild.get_member(user.discord_id)
|
||||
return permissions.is_member_technician(member)
|
||||
|
||||
@staticmethod
|
||||
@ServiceProviderABC.inject
|
||||
def _is_admin(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
|
||||
def _is_admin(
|
||||
user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC
|
||||
):
|
||||
guild = bot.get_guild(user.server.discord_id)
|
||||
member = guild.get_member(user.discord_id)
|
||||
return permissions.is_member_admin(member)
|
||||
|
||||
@staticmethod
|
||||
@ServiceProviderABC.inject
|
||||
def _is_moderator(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC):
|
||||
def _is_moderator(
|
||||
user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC
|
||||
):
|
||||
guild = bot.get_guild(user.server.discord_id)
|
||||
member = guild.get_member(user.discord_id)
|
||||
return permissions.is_member_moderator(member)
|
@@ -13,7 +13,9 @@ class ServerTransformer(TransformerABC):
|
||||
return Server(dto.discord_id)
|
||||
|
||||
@staticmethod
|
||||
def to_dto(db: Server, name: str, member_count: int, icon_url: Optional[discord.Asset]) -> ServerDTO:
|
||||
def to_dto(
|
||||
db: Server, name: str, member_count: int, icon_url: Optional[discord.Asset]
|
||||
) -> ServerDTO:
|
||||
return ServerDTO(
|
||||
db.id,
|
||||
db.discord_id,
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_core"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_core.abc"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -45,7 +45,9 @@ class ClientUtilsABC(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_auto_complete_list(self, _l: List, current: str, select: Callable = None) -> List:
|
||||
def get_auto_complete_list(
|
||||
self, _l: List, current: str, select: Callable = None
|
||||
) -> List:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
@@ -64,7 +66,11 @@ class ClientUtilsABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
async def react_to_message_by_auto_role_rule(
|
||||
self, discord_channel_id: int, discord_message_id: int, rule: AutoRoleRule, guild: discord.Guild
|
||||
self,
|
||||
discord_channel_id: int,
|
||||
discord_message_id: int,
|
||||
rule: AutoRoleRule,
|
||||
guild: discord.Guild,
|
||||
):
|
||||
pass
|
||||
|
@@ -18,7 +18,9 @@ class CustomFileLoggerABC(Logger, ABC):
|
||||
env: ApplicationEnvironmentABC,
|
||||
):
|
||||
self._key = key
|
||||
self._settings: LoggingSettings = config.get_configuration(f"{FileLoggingSettings.__name__}_{key}")
|
||||
self._settings: LoggingSettings = config.get_configuration(
|
||||
f"{FileLoggingSettings.__name__}_{key}"
|
||||
)
|
||||
Logger.__init__(self, self._settings, time_format, env)
|
||||
self._begin_log()
|
||||
|
||||
@@ -32,7 +34,9 @@ class CustomFileLoggerABC(Logger, ABC):
|
||||
self.info(__name__, f"Starting...")
|
||||
self._console = LoggingLevelEnum(console_level)
|
||||
|
||||
def _get_string(self, name_list_as_str: str, level: LoggingLevelEnum, message: str) -> str:
|
||||
def _get_string(
|
||||
self, name_list_as_str: str, level: LoggingLevelEnum, message: str
|
||||
) -> str:
|
||||
names = name_list_as_str.split(" ")
|
||||
log_level = level.name
|
||||
string = f"<{self._get_datetime_now()}> [ {log_level} ]"
|
@@ -13,7 +13,9 @@ class MessageServiceABC(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def delete_messages(self, messages: List[discord.Message], guild_id: int, without_tracking=False):
|
||||
async def delete_messages(
|
||||
self, messages: List[discord.Message], guild_id: int, without_tracking=False
|
||||
):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
30
bot/src/bot_core/abc/task_abc.py
Normal file
30
bot/src/bot_core/abc/task_abc.py
Normal file
@@ -0,0 +1,30 @@
|
||||
import asyncio
|
||||
from abc import abstractmethod
|
||||
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
from discord.ext import commands
|
||||
|
||||
from bot_core.logging.task_logger import TaskLogger
|
||||
|
||||
|
||||
class TaskABC(commands.Cog):
|
||||
@abstractmethod
|
||||
def __init__(self):
|
||||
commands.Cog.__init__(self)
|
||||
|
||||
@ServiceProviderABC.inject
|
||||
async def _wait_until_ready(
|
||||
self, config: ConfigurationABC, logger: TaskLogger, bot: DiscordBotServiceABC
|
||||
):
|
||||
logger.debug(__name__, f"Waiting before {type(self).__name__}")
|
||||
await bot.wait_until_ready()
|
||||
|
||||
async def wait():
|
||||
is_ready = config.get_configuration("IS_READY")
|
||||
if is_ready != "true":
|
||||
await asyncio.sleep(1)
|
||||
await wait()
|
||||
|
||||
await wait()
|
@@ -3,8 +3,8 @@
|
||||
"Name": "bot-core",
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "1",
|
||||
"Micro": "6"
|
||||
"Minor": "2",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_core.configuration"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -16,9 +16,14 @@ class FeatureFlagsEnum(Enum):
|
||||
level_module = "LevelModule"
|
||||
moderator_module = "ModeratorModule"
|
||||
permission_module = "PermissionModule"
|
||||
short_role_name_module = "ShortRoleNameModule"
|
||||
steam_special_offers_module = "SteamSpecialOffersModule"
|
||||
# features
|
||||
api_only = "ApiOnly"
|
||||
presence = "Presence"
|
||||
version_in_presence = "VersionInPresence"
|
||||
game_server = "GameServer"
|
||||
sync_xp = "SyncXp"
|
||||
short_role_name = "ShortRoleName"
|
||||
technician_full_access = "TechnicianFullAccess"
|
||||
steam_special_offers = "SteamSpecialOffers"
|
@@ -18,12 +18,17 @@ class FeatureFlagsSettings(ConfigurationModelABC):
|
||||
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
|
||||
# features
|
||||
FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70
|
||||
FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56
|
||||
FeatureFlagsEnum.version_in_presence.value: False, # 21.03.2023 #253
|
||||
FeatureFlagsEnum.game_server.value: False, # 25.09.2023 #366
|
||||
FeatureFlagsEnum.sync_xp.value: False, # 25.09.2023 #366
|
||||
FeatureFlagsEnum.short_role_name.value: False, # 28.09.2023 #378
|
||||
FeatureFlagsEnum.technician_full_access.value: False, # 03.10.2023 #393
|
||||
FeatureFlagsEnum.steam_special_offers.value: False, # 11.10.2023 #188
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs: dict):
|
@@ -10,7 +10,9 @@ class FileLoggingSettings(LoggingSettings):
|
||||
console_log_level: LoggingLevelEnum = None,
|
||||
file_log_level: LoggingLevelEnum = None,
|
||||
):
|
||||
LoggingSettings.__init__(self, path, filename, console_log_level, file_log_level)
|
||||
LoggingSettings.__init__(
|
||||
self, path, filename, console_log_level, file_log_level
|
||||
)
|
||||
|
||||
self._key = key
|
||||
|
@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot Keksdose bot
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for the Keksdose discord Server
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
@@ -15,7 +15,7 @@ __title__ = "bot_core.core_extension"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.1.6"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
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="1", micro="6")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -17,7 +17,9 @@ class CoreExtension(ApplicationExtensionABC):
|
||||
ApplicationExtensionABC.__init__(self)
|
||||
|
||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||
feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings)
|
||||
feature_flags: FeatureFlagsSettings = config.get_configuration(
|
||||
FeatureFlagsSettings
|
||||
)
|
||||
if not feature_flags.get_flag(FeatureFlagsEnum.core_module):
|
||||
return
|
||||
|
@@ -15,8 +15,14 @@ class CoreExtensionModule(ModuleABC):
|
||||
def __init__(self, dc: DiscordCollectionABC):
|
||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_extension_module)
|
||||
|
||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
pass
|
||||
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, CoreExtensionOnReadyEvent)
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
services.add_transient(
|
||||
DiscordEventTypesEnum.on_ready.value, CoreExtensionOnReadyEvent
|
||||
)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user