Compare commits
146 Commits
549b05087f
...
0.3.1
Author | SHA1 | Date | |
---|---|---|---|
1b5f87f869 | |||
ed83826234 | |||
96b54fdbc9 | |||
9658a5c238 | |||
6dd9b9c302 | |||
29ee85bd93 | |||
e969926769 | |||
d596d7465e | |||
ea266cc5be | |||
e2b2fb5abb | |||
37ec0cf0c7 | |||
460bb42028 | |||
0379c3ed9b | |||
fecb82bf36 | |||
2401e58827 | |||
5d3ceff3bf | |||
e481958bad | |||
0c76269e40 | |||
17b336623d | |||
00b4e2ab66 | |||
1b15e54199 | |||
c9aeb684d6 | |||
3811cf7d74 | |||
2a0e3d77b7 | |||
59fc1e1442 | |||
84f8690bdf | |||
d91ff392ca | |||
1ff70af72b | |||
a216506a37 | |||
3d01c9f798 | |||
624625d4b5 | |||
f9593b5f44 | |||
34ebb48c83 | |||
849a92125a | |||
5d6c55fc86 | |||
3cf0fe3479 | |||
b80958e3ab | |||
b89fa12ec6 | |||
706b6732eb | |||
053c190c78 | |||
c443d108dc | |||
09fbc27981 | |||
242ffd1550 | |||
fb4be18ef2 | |||
89ee16d1b5 | |||
8b7efed257 | |||
d10c33c6c2 | |||
3abaee3e71 | |||
4c577f6a7b | |||
f50a763539 | |||
9ff9cc672e | |||
9d4cf5a769 | |||
df1d62f569 | |||
4201510e9f | |||
394428a81a | |||
4733f84ec6 | |||
9c466733fb | |||
bd62618fdf | |||
a78d5f0fcb | |||
661630bb37 | |||
15f041a2da | |||
1ac5d982ed | |||
1337ef35dd | |||
986d7c4562 | |||
7fcb4084d2 | |||
fbac0d3d02 | |||
9626de2b27 | |||
1d74f5e67c | |||
6949db10f8 | |||
ba5d897662 | |||
47415af868 | |||
6353c7ca86 | |||
440689653d | |||
844a818aa0 | |||
33fb973f21 | |||
7646335d03 | |||
04c905d287 | |||
c7d8508173 | |||
f3eff97780 | |||
476db0ed33 | |||
9c369b911a | |||
6dfd476bce | |||
f669410b2a | |||
a46122243f | |||
3b7345b404 | |||
59d38f8f2a | |||
612430d3e0 | |||
e01290db9b | |||
6273ce9cba | |||
5c923d8bd8 | |||
6c6169f7ee | |||
ffd5105154 | |||
9040ab6fca | |||
9d89135b4c | |||
71899346b2 | |||
d197a6e158 | |||
40e53de3f2 | |||
1b9553e63b | |||
5447d502cc | |||
5a4c2901f5 | |||
bcf71a26f0 | |||
b25b75e382 | |||
f21b4f9881 | |||
8705904882 | |||
cf610b770b | |||
ec30069ff5 | |||
7026b3abac | |||
31464df3f6 | |||
eb9f5b83d5 | |||
fdd8357729 | |||
7c744f0e65 | |||
4a0f5c28c1 | |||
d2f99003ff | |||
9dd3fd4b8e | |||
d18500b96c | |||
91fdf34d32 | |||
12369cdbe3 | |||
25c698273a | |||
2868b1afe2 | |||
0d1c15b31d | |||
840da350e4 | |||
bd94c42eae | |||
c7a925b997 | |||
7fb6d22c3f | |||
c5b5297058 | |||
9ed66c2560 | |||
6e6157ccf2 | |||
f136d6164e | |||
9b5033b80e | |||
f5a71a8450 | |||
d3279eb7c7 | |||
ec7aeb8712 | |||
fd609eb923 | |||
a7dbc75d2e | |||
b0459567f4 | |||
25b7b18013 | |||
87350cba1a | |||
864d181de0 | |||
90011be760 | |||
47dd6fdc2d | |||
8445c23e7f | |||
e6fc41090a | |||
7c79c6f992 | |||
7b8dca64bf | |||
2c7f4647af | |||
53604706c2 |
@@ -13,19 +13,22 @@
|
|||||||
"level": "src/modules/level/level.json",
|
"level": "src/modules/level/level.json",
|
||||||
"permission": "src/modules/permission/permission.json",
|
"permission": "src/modules/permission/permission.json",
|
||||||
"stats": "src/modules/stats/stats.json",
|
"stats": "src/modules/stats/stats.json",
|
||||||
|
"technician": "src/modules/technician/technician.json",
|
||||||
"get-version": "tools/get_version/get-version.json",
|
"get-version": "tools/get_version/get-version.json",
|
||||||
"post-build": "tools/post_build/post-build.json",
|
"post-build": "tools/post_build/post-build.json",
|
||||||
"set-version": "tools/set_version/set-version.json"
|
"set-version": "tools/set_version/set-version.json"
|
||||||
},
|
},
|
||||||
"Scripts": {
|
"Scripts": {
|
||||||
"sv": "cpl set-version",
|
"format": "black ./",
|
||||||
"set-version": "cpl run set-version $ARGS; echo '';",
|
|
||||||
|
"sv": "cpl set-version $ARGS",
|
||||||
|
"set-version": "cpl run set-version $ARGS --dev; echo '';",
|
||||||
|
|
||||||
"gv": "cpl get-version",
|
"gv": "cpl get-version",
|
||||||
"get-version": "export VERSION=$(cpl run get-version); echo $VERSION;",
|
"get-version": "export VERSION=$(cpl run get-version --dev); echo $VERSION;",
|
||||||
|
|
||||||
"pre-build": "cpl set-version $ARGS",
|
"pre-build": "cpl set-version $ARGS; black ./;",
|
||||||
"post-build": "cpl run post-build",
|
"post-build": "cpl run post-build --dev; black ./;",
|
||||||
|
|
||||||
"pre-prod": "cpl build",
|
"pre-prod": "cpl build",
|
||||||
"prod": "export KDB_ENVIRONMENT=production; export KDB_NAME=KDB-Prod; cpl start;",
|
"prod": "export KDB_ENVIRONMENT=production; export KDB_NAME=KDB-Prod; cpl start;",
|
||||||
@@ -36,9 +39,10 @@
|
|||||||
"pre-dev": "cpl build",
|
"pre-dev": "cpl build",
|
||||||
"dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;",
|
"dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;",
|
||||||
|
|
||||||
"docker-build": "cpl b; docker-compose down; docker build -t kdb-bot/kdb-bot:$(cpl gv) .",
|
"docker-build": "cpl build $ARGS; docker build -t kdb-bot/kdb-bot:$(cpl gv) .;",
|
||||||
"docker-compose": "docker-compose up -d",
|
"dc-up": "docker-compose up -d",
|
||||||
"docker": "cpl docker-build; cpl docker-compose;"
|
"dc-down": "docker-compose down",
|
||||||
|
"docker": "cpl dc-down; cpl docker-build; cpl dc-up;"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Submodule kdb-bot/docker updated: b3d5e9feef...6b25cc87fc
18
kdb-bot/dockerfile
Normal file
18
kdb-bot/dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM python:3.10.4-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY ./dist/bot/build/kdb-bot/ .
|
||||||
|
COPY ./dist/bot/build/requirements.txt .
|
||||||
|
|
||||||
|
RUN python -m pip install --upgrade pip
|
||||||
|
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add --update alpine-sdk linux-headers
|
||||||
|
RUN apk add bash
|
||||||
|
RUN apk add nano
|
||||||
|
|
||||||
|
RUN pip install -r requirements.txt --extra-index-url https://pip.sh-edraft.de
|
||||||
|
RUN pip install flask[async]
|
||||||
|
|
||||||
|
CMD [ "bash", "/app/bot/bot"]
|
2
kdb-bot/pyproject.toml
Normal file
2
kdb-bot/pyproject.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[tool.black]
|
||||||
|
line-length = 120
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot'
|
__title__ = "bot"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -13,7 +13,6 @@ from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
|||||||
|
|
||||||
|
|
||||||
class Application(DiscordBotApplicationABC):
|
class Application(DiscordBotApplicationABC):
|
||||||
|
|
||||||
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||||
DiscordBotApplicationABC.__init__(self, config, services)
|
DiscordBotApplicationABC.__init__(self, config, services)
|
||||||
|
|
||||||
@@ -42,18 +41,22 @@ class Application(DiscordBotApplicationABC):
|
|||||||
|
|
||||||
async def main(self):
|
async def main(self):
|
||||||
try:
|
try:
|
||||||
self._logger.debug(__name__, f'Starting...')
|
self._logger.debug(__name__, f"Starting...")
|
||||||
|
|
||||||
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module) and self._feature_flags.get_flag(FeatureFlagsEnum.api_only) and self._environment.environment_name == 'development':
|
if (
|
||||||
|
self._feature_flags.get_flag(FeatureFlagsEnum.api_module)
|
||||||
|
and self._feature_flags.get_flag(FeatureFlagsEnum.api_only)
|
||||||
|
and self._environment.environment_name == "development"
|
||||||
|
):
|
||||||
self._api.start()
|
self._api.start()
|
||||||
self._api.join()
|
self._api.join()
|
||||||
return
|
return
|
||||||
|
|
||||||
self._logger.trace(__name__, f'Try to start {DiscordBotService.__name__}')
|
self._logger.trace(__name__, f"Try to start {DiscordBotService.__name__}")
|
||||||
await self._bot.start_async()
|
await self._bot.start_async()
|
||||||
await self._bot.stop_async()
|
await self._bot.stop_async()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, 'Start failed', e)
|
self._logger.error(__name__, "Start failed", e)
|
||||||
|
|
||||||
async def stop_async(self):
|
async def stop_async(self):
|
||||||
if self._is_stopping:
|
if self._is_stopping:
|
||||||
@@ -61,13 +64,13 @@ class Application(DiscordBotApplicationABC):
|
|||||||
|
|
||||||
self._is_stopping = True
|
self._is_stopping = True
|
||||||
try:
|
try:
|
||||||
self._logger.trace(__name__, f'Try to stop {DiscordBotService.__name__}')
|
self._logger.trace(__name__, f"Try to stop {DiscordBotService.__name__}")
|
||||||
await self._bot.close()
|
await self._bot.close()
|
||||||
self._logger.trace(__name__, f'Stopped {DiscordBotService.__name__}')
|
self._logger.trace(__name__, f"Stopped {DiscordBotService.__name__}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, 'stop failed', e)
|
self._logger.error(__name__, "stop failed", e)
|
||||||
|
|
||||||
Console.write_line()
|
Console.write_line()
|
||||||
|
|
||||||
def is_restart(self):
|
def is_restart(self):
|
||||||
return True if self._configuration.get_configuration('IS_RESTART') == 'true' else False #
|
return True if self._configuration.get_configuration("IS_RESTART") == "true" else False #
|
||||||
|
@@ -4,33 +4,34 @@
|
|||||||
"Version": {
|
"Version": {
|
||||||
"Major": "0",
|
"Major": "0",
|
||||||
"Minor": "3",
|
"Minor": "3",
|
||||||
"Micro": "dev25"
|
"Micro": "1"
|
||||||
},
|
},
|
||||||
"Author": "Sven Heidemann",
|
"Author": "Sven Heidemann",
|
||||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||||
"Description": "Keksdose bot",
|
"Description": "Keksdose bot",
|
||||||
"LongDescription": "Discord bot for the Keksdose discord Server",
|
"LongDescription": "Discord bot for the Keksdose discord Server",
|
||||||
"URL": "https://www.sh-edraft.de",
|
"URL": "https://www.sh-edraft.de",
|
||||||
"CopyrightDate": "2022",
|
"CopyrightDate": "2022 - 2023",
|
||||||
"CopyrightName": "sh-edraft.de",
|
"CopyrightName": "sh-edraft.de",
|
||||||
"LicenseName": "MIT",
|
"LicenseName": "MIT",
|
||||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"cpl-core==2022.10.0.post7",
|
"cpl-core==2022.12.1.post2",
|
||||||
"cpl-translation==2022.10.0.post2",
|
"cpl-translation==2022.12.1",
|
||||||
"cpl-query==2022.10.0.post2",
|
"cpl-query==2022.12.2.post1",
|
||||||
"cpl-discord==2022.10.0.post6",
|
"cpl-discord==2022.12.1.post2",
|
||||||
"Flask==2.2.2",
|
"Flask==2.2.2",
|
||||||
"Flask-Classful==0.14.2",
|
"Flask-Classful==0.14.2",
|
||||||
"Flask-Cors==3.0.10",
|
"Flask-Cors==3.0.10",
|
||||||
"PyJWT==2.6.0",
|
"PyJWT==2.6.0",
|
||||||
"waitress==2.1.2",
|
"waitress==2.1.2",
|
||||||
"Flask-SocketIO==5.3.1",
|
"Flask-SocketIO==5.3.2",
|
||||||
"eventlet==0.33.1",
|
"eventlet==0.33.2",
|
||||||
"requests-oauthlib==1.3.1"
|
"requests-oauthlib==1.3.1",
|
||||||
|
"icmplib==3.0.3"
|
||||||
],
|
],
|
||||||
"DevDependencies": [
|
"DevDependencies": [
|
||||||
"cpl-cli==2022.10.0"
|
"cpl-cli==2022.12.1.post2"
|
||||||
],
|
],
|
||||||
"PythonVersion": ">=3.10.4",
|
"PythonVersion": ">=3.10.4",
|
||||||
"PythonPath": {},
|
"PythonPath": {},
|
||||||
@@ -59,9 +60,9 @@
|
|||||||
"../modules/boot_log/boot-log.json",
|
"../modules/boot_log/boot-log.json",
|
||||||
"../modules/database/database.json",
|
"../modules/database/database.json",
|
||||||
"../modules/level/level.json",
|
"../modules/level/level.json",
|
||||||
"../modules/permission/level.json",
|
|
||||||
"../modules/permission/permission.json",
|
"../modules/permission/permission.json",
|
||||||
"../modules/permission/stats.json"
|
"../modules/stats/stats.json",
|
||||||
|
"../modules/technician/technician.json"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
Submodule kdb-bot/src/bot/config updated: c8e3ac0963...54b1b3860c
26
kdb-bot/src/bot/extension/__init__.py
Normal file
26
kdb-bot/src/bot/extension/__init__.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
bot Keksdose bot
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__title__ = "bot.extension"
|
||||||
|
__author__ = "Sven Heidemann"
|
||||||
|
__license__ = "MIT"
|
||||||
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
|
# imports:
|
||||||
|
|
||||||
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
16
kdb-bot/src/bot/extension/init_bot_extension.py
Normal file
16
kdb-bot/src/bot/extension/init_bot_extension.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from cpl_core.application import ApplicationExtensionABC
|
||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
|
from cpl_core.dependency_injection import ServiceProviderABC
|
||||||
|
from cpl_discord.service import DiscordBotServiceABC
|
||||||
|
|
||||||
|
from bot_core.configuration.bot_settings import BotSettings
|
||||||
|
|
||||||
|
|
||||||
|
class InitBotExtension(ApplicationExtensionABC):
|
||||||
|
def __init__(self):
|
||||||
|
ApplicationExtensionABC.__init__(self)
|
||||||
|
|
||||||
|
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||||
|
settings = config.get_configuration(BotSettings)
|
||||||
|
|
||||||
|
bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC, max_messages=settings.cache_max_messages)
|
@@ -6,6 +6,7 @@ from cpl_core.application import ApplicationBuilder
|
|||||||
from cpl_core.console import Console
|
from cpl_core.console import Console
|
||||||
|
|
||||||
from bot.application import Application
|
from bot.application import Application
|
||||||
|
from bot.extension.init_bot_extension import InitBotExtension
|
||||||
from bot.startup import Startup
|
from bot.startup import Startup
|
||||||
from bot.startup_discord_extension import StartupDiscordExtension
|
from bot.startup_discord_extension import StartupDiscordExtension
|
||||||
from bot.startup_migration_extension import StartupMigrationExtension
|
from bot.startup_migration_extension import StartupMigrationExtension
|
||||||
@@ -18,22 +19,24 @@ from modules.database.database_extension import DatabaseExtension
|
|||||||
|
|
||||||
|
|
||||||
class Program:
|
class Program:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.app: Optional[Application] = None
|
self.app: Optional[Application] = None
|
||||||
|
|
||||||
async def start(self):
|
async def start(self):
|
||||||
# discord extension has to be loaded before modules (modules depends on discord stuff)
|
# discord extension has to be loaded before modules (modules depends on discord stuff)
|
||||||
app_builder = ApplicationBuilder(Application) \
|
app_builder = (
|
||||||
.use_extension(StartupSettingsExtension) \
|
ApplicationBuilder(Application)
|
||||||
.use_extension(StartupDiscordExtension) \
|
.use_extension(StartupSettingsExtension)
|
||||||
.use_extension(StartupModuleExtension) \
|
.use_extension(StartupDiscordExtension)
|
||||||
.use_extension(StartupMigrationExtension) \
|
.use_extension(StartupModuleExtension)
|
||||||
.use_extension(BootLogExtension) \
|
.use_extension(StartupMigrationExtension)
|
||||||
.use_extension(DatabaseExtension) \
|
.use_extension(InitBotExtension)
|
||||||
.use_extension(AppApiExtension) \
|
.use_extension(BootLogExtension)
|
||||||
.use_extension(CoreExtension) \
|
.use_extension(DatabaseExtension)
|
||||||
|
.use_extension(AppApiExtension)
|
||||||
|
.use_extension(CoreExtension)
|
||||||
.use_startup(Startup)
|
.use_startup(Startup)
|
||||||
|
)
|
||||||
self.app: Application = await app_builder.build_async()
|
self.app: Application = await app_builder.build_async()
|
||||||
await self.app.run_async()
|
await self.app.run_async()
|
||||||
|
|
||||||
@@ -50,19 +53,25 @@ def main():
|
|||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
asyncio.run(program.stop())
|
asyncio.run(program.stop())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Cannot start the bot', f'{e} -> {traceback.format_exc()}')
|
Console.error(
|
||||||
|
f"[ ERROR ] [ {__name__} ]: Cannot start the bot",
|
||||||
|
f"{e} -> {traceback.format_exc()}",
|
||||||
|
)
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
asyncio.run(program.stop())
|
asyncio.run(program.stop())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Cannot stop the bot', f'{e} -> {traceback.format_exc()}')
|
Console.error(
|
||||||
|
f"[ ERROR ] [ {__name__} ]: Cannot stop the bot",
|
||||||
|
f"{e} -> {traceback.format_exc()}",
|
||||||
|
)
|
||||||
|
|
||||||
if program.app is not None and program.app.is_restart():
|
if program.app is not None and program.app.is_restart():
|
||||||
del program
|
del program
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
||||||
# ((
|
# ((
|
||||||
|
@@ -11,24 +11,28 @@ from modules.database.database_module import DatabaseModule
|
|||||||
from modules.level.level_module import LevelModule
|
from modules.level.level_module import LevelModule
|
||||||
from modules.permission.permission_module import PermissionModule
|
from modules.permission.permission_module import PermissionModule
|
||||||
from modules.stats.stats_module import StatsModule
|
from modules.stats.stats_module import StatsModule
|
||||||
|
from modules.technician.technician_module import TechnicianModule
|
||||||
|
|
||||||
|
|
||||||
class ModuleList:
|
class ModuleList:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_modules():
|
def get_modules():
|
||||||
# core modules (modules out of modules folder) should be loaded first!
|
# core modules (modules out of modules folder) should be loaded first!
|
||||||
return List(type, [
|
return List(
|
||||||
CoreModule, # has to be first!
|
type,
|
||||||
DataModule,
|
[
|
||||||
AutoRoleModule,
|
CoreModule, # has to be first!
|
||||||
BaseModule,
|
DataModule,
|
||||||
DatabaseModule,
|
PermissionModule,
|
||||||
LevelModule,
|
DatabaseModule,
|
||||||
PermissionModule,
|
AutoRoleModule,
|
||||||
ApiModule,
|
BaseModule,
|
||||||
StatsModule,
|
LevelModule,
|
||||||
# has to be last!
|
ApiModule,
|
||||||
BootLogModule,
|
StatsModule,
|
||||||
CoreExtensionModule,
|
TechnicianModule,
|
||||||
])
|
# has to be last!
|
||||||
|
BootLogModule,
|
||||||
|
CoreExtensionModule,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@@ -20,7 +20,6 @@ from bot_data.db_context import DBContext
|
|||||||
|
|
||||||
|
|
||||||
class Startup(StartupABC):
|
class Startup(StartupABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
StartupABC.__init__(self)
|
StartupABC.__init__(self)
|
||||||
self._start_time = datetime.now()
|
self._start_time = datetime.now()
|
||||||
@@ -28,12 +27,16 @@ class Startup(StartupABC):
|
|||||||
self._config: Optional[ConfigurationABC] = None
|
self._config: Optional[ConfigurationABC] = None
|
||||||
self._feature_flags: Optional[FeatureFlagsSettings] = None
|
self._feature_flags: Optional[FeatureFlagsSettings] = None
|
||||||
|
|
||||||
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC:
|
def configure_configuration(
|
||||||
|
self, configuration: ConfigurationABC, environment: ApplicationEnvironment
|
||||||
|
) -> ConfigurationABC:
|
||||||
self._config = configuration
|
self._config = configuration
|
||||||
self._feature_flags = configuration.get_configuration(FeatureFlagsSettings)
|
self._feature_flags = configuration.get_configuration(FeatureFlagsSettings)
|
||||||
return configuration
|
return configuration
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
def configure_services(
|
||||||
|
self, services: ServiceCollectionABC, environment: ApplicationEnvironment
|
||||||
|
) -> ServiceProviderABC:
|
||||||
services.add_logging()
|
services.add_logging()
|
||||||
if self._feature_flags.get_flag(FeatureFlagsEnum.core_module):
|
if self._feature_flags.get_flag(FeatureFlagsEnum.core_module):
|
||||||
# custom logging
|
# custom logging
|
||||||
@@ -52,9 +55,11 @@ class Startup(StartupABC):
|
|||||||
for c in CustomFileLoggerABC.__subclasses__():
|
for c in CustomFileLoggerABC.__subclasses__():
|
||||||
i: LoggerABC = provider.get_service(c)
|
i: LoggerABC = provider.get_service(c)
|
||||||
|
|
||||||
|
|
||||||
logger: LoggerABC = provider.get_service(LoggerABC)
|
logger: LoggerABC = provider.get_service(LoggerABC)
|
||||||
for flag in [f for f in FeatureFlagsEnum]:
|
for flag in [f for f in FeatureFlagsEnum]:
|
||||||
logger.debug(__name__, f'Loaded feature-flag: {flag} = {self._feature_flags.get_flag(flag)}')
|
logger.debug(
|
||||||
|
__name__,
|
||||||
|
f"Loaded feature-flag: {flag} = {self._feature_flags.get_flag(flag)}",
|
||||||
|
)
|
||||||
|
|
||||||
return provider
|
return provider
|
||||||
|
@@ -6,7 +6,6 @@ from cpl_discord import get_discord_collection
|
|||||||
|
|
||||||
|
|
||||||
class StartupDiscordExtension(StartupExtensionABC):
|
class StartupDiscordExtension(StartupExtensionABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@@ -5,15 +5,18 @@ from cpl_core.environment import ApplicationEnvironmentABC
|
|||||||
|
|
||||||
from bot_data.abc.migration_abc import MigrationABC
|
from bot_data.abc.migration_abc import MigrationABC
|
||||||
from bot_data.migration.api_migration import ApiMigration
|
from bot_data.migration.api_migration import ApiMigration
|
||||||
|
from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration
|
||||||
from bot_data.migration.auto_role_migration import AutoRoleMigration
|
from bot_data.migration.auto_role_migration import AutoRoleMigration
|
||||||
from bot_data.migration.initial_migration import InitialMigration
|
from bot_data.migration.initial_migration import InitialMigration
|
||||||
from bot_data.migration.level_migration import LevelMigration
|
from bot_data.migration.level_migration import LevelMigration
|
||||||
from bot_data.migration.stats_migration import StatsMigration
|
from bot_data.migration.stats_migration import StatsMigration
|
||||||
|
from bot_data.migration.user_message_count_per_hour_migration import (
|
||||||
|
UserMessageCountPerHourMigration,
|
||||||
|
)
|
||||||
from bot_data.service.migration_service import MigrationService
|
from bot_data.service.migration_service import MigrationService
|
||||||
|
|
||||||
|
|
||||||
class StartupMigrationExtension(StartupExtensionABC):
|
class StartupMigrationExtension(StartupExtensionABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -27,3 +30,5 @@ class StartupMigrationExtension(StartupExtensionABC):
|
|||||||
services.add_transient(MigrationABC, ApiMigration) # 15.10.2022 #70 - 0.3.0
|
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, LevelMigration) # 06.11.2022 #25 - 0.3.0
|
||||||
services.add_transient(MigrationABC, StatsMigration) # 09.11.2022 #46 - 0.3.0
|
services.add_transient(MigrationABC, StatsMigration) # 09.11.2022 #46 - 0.3.0
|
||||||
|
services.add_transient(MigrationABC, AutoRoleFix1Migration) # 30.12.2022 #151 - 0.3.0
|
||||||
|
services.add_transient(MigrationABC, UserMessageCountPerHourMigration) # 11.01.2023 #168 - 0.3.1
|
||||||
|
@@ -12,7 +12,6 @@ from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
|||||||
|
|
||||||
|
|
||||||
class StartupModuleExtension(StartupExtensionABC):
|
class StartupModuleExtension(StartupExtensionABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._config: Optional[ConfigurationABC] = None
|
self._config: Optional[ConfigurationABC] = None
|
||||||
self._feature_flags: Optional[FeatureFlagsSettings] = None
|
self._feature_flags: Optional[FeatureFlagsSettings] = None
|
||||||
@@ -33,7 +32,7 @@ class StartupModuleExtension(StartupExtensionABC):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
Console.set_foreground_color(ForegroundColorEnum.green)
|
Console.set_foreground_color(ForegroundColorEnum.green)
|
||||||
Console.write_line(f'[{__name__}] Loaded module: {module_type}')
|
Console.write_line(f"[{__name__}] Loaded module: {module_type}")
|
||||||
Console.color_reset()
|
Console.color_reset()
|
||||||
module.configure_configuration(self._config, env)
|
module.configure_configuration(self._config, env)
|
||||||
module.configure_services(services, env)
|
module.configure_services(services, env)
|
||||||
|
@@ -16,38 +16,45 @@ from modules.permission.configuration.permission_settings import PermissionSetti
|
|||||||
|
|
||||||
|
|
||||||
class StartupSettingsExtension(StartupExtensionABC):
|
class StartupSettingsExtension(StartupExtensionABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._start_time = datetime.now()
|
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
|
# 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__)))
|
environment.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
|
||||||
configuration.add_environment_variables('KDB_')
|
configuration.add_environment_variables("KDB_")
|
||||||
configuration.add_environment_variables('DISCORD_')
|
configuration.add_environment_variables("DISCORD_")
|
||||||
|
|
||||||
configuration.add_json_file(f'config/appsettings.json', optional=False)
|
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.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.host_name}.json", optional=True)
|
||||||
# load feature-flags
|
# load feature-flags
|
||||||
configuration.add_json_file(f'config/feature-flags.json', optional=False)
|
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_configuration('Startup_StartTime', str(self._start_time))
|
configuration.add_configuration("Startup_StartTime", str(self._start_time))
|
||||||
self._configure_settings_with_sub_settings(configuration, BotSettings, lambda x: x.servers, lambda x: x.id)
|
self._configure_settings_with_sub_settings(configuration, BotSettings, lambda x: x.servers, lambda x: x.id)
|
||||||
self._configure_settings_with_sub_settings(configuration, BaseSettings, lambda x: x.servers, lambda x: x.id)
|
self._configure_settings_with_sub_settings(configuration, BaseSettings, lambda x: x.servers, lambda x: x.id)
|
||||||
self._configure_settings_with_sub_settings(configuration, BootLogSettings, lambda x: x.servers, lambda x: x.id)
|
self._configure_settings_with_sub_settings(configuration, BootLogSettings, lambda x: x.servers, lambda x: x.id)
|
||||||
self._configure_settings_with_sub_settings(configuration, LevelSettings, lambda x: x.servers, lambda x: x.id)
|
self._configure_settings_with_sub_settings(configuration, LevelSettings, lambda x: x.servers, lambda x: x.id)
|
||||||
self._configure_settings_with_sub_settings(configuration, PermissionSettings, lambda x: x.servers, lambda x: x.id)
|
self._configure_settings_with_sub_settings(
|
||||||
self._configure_settings_with_sub_settings(configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key)
|
configuration, PermissionSettings, lambda x: x.servers, lambda x: x.id
|
||||||
|
)
|
||||||
|
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
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _configure_settings_with_sub_settings(config: ConfigurationABC, settings: Type, list_atr: Callable, atr: Callable):
|
def _configure_settings_with_sub_settings(
|
||||||
|
config: ConfigurationABC, settings: Type, list_atr: Callable, atr: Callable
|
||||||
|
):
|
||||||
settings: Optional[settings] = config.get_configuration(settings)
|
settings: Optional[settings] = config.get_configuration(settings)
|
||||||
if settings is None:
|
if settings is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
for sub_settings in list_atr(settings):
|
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)
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
"not_implemented_yet": "Ey Alter, das kann ich noch nicht...",
|
"not_implemented_yet": "Ey Alter, das kann ich noch nicht...",
|
||||||
"presence": {
|
"presence": {
|
||||||
"booting": "{} Ich fahre gerade hoch...",
|
"booting": "{} Ich fahre gerade hoch...",
|
||||||
"running": "{} Behalte Ruhe und iss Kekse :D",
|
"running": "{} Ich esse Kekse :D",
|
||||||
"restart": "{} Muss neue Kekse holen...",
|
"restart": "{} Muss neue Kekse holen...",
|
||||||
"shutdown": "{} Ich werde bestimmt wieder kommen..."
|
"shutdown": "{} Ich werde bestimmt wieder kommen..."
|
||||||
},
|
},
|
||||||
@@ -72,11 +72,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"modules": {
|
"modules": {
|
||||||
"admin": {
|
|
||||||
"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 :)",
|
|
||||||
"deploy_message": "Der neue Stand wurde hochgeladen."
|
|
||||||
},
|
|
||||||
"auto_role": {
|
"auto_role": {
|
||||||
"list": {
|
"list": {
|
||||||
"title": "Beobachtete Nachrichten:",
|
"title": "Beobachtete Nachrichten:",
|
||||||
@@ -113,7 +108,7 @@
|
|||||||
"error": {
|
"error": {
|
||||||
"not_found": "Regel für auto-role {} nicht gefunden!",
|
"not_found": "Regel für auto-role {} nicht gefunden!",
|
||||||
"emoji_not_found": "Emoji {} für auto-role Regel {} nicht gefunden!",
|
"emoji_not_found": "Emoji {} für auto-role Regel {} nicht gefunden!",
|
||||||
"rule_not_found": "Rolle {} für auto-role Regel {} nicht gefunden!",
|
"role_not_found": "Rolle {} für auto-role Regel {} nicht gefunden!",
|
||||||
"already_exists": "Regel für auto-role {} existiert bereits!"
|
"already_exists": "Regel für auto-role {} existiert bereits!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -132,17 +127,17 @@
|
|||||||
"purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss."
|
"purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss."
|
||||||
},
|
},
|
||||||
"base": {
|
"base": {
|
||||||
"technician_error_message": "Es gab ein Fehler mit dem Event: {}\nDatum und Zeit: {}\nSchau bitte ins log für Details.UUID: {}",
|
"technician_error_message": "Es gab ein Fehler mit dem Event: {}\nDatum und Zeit: {}\nSchau bitte ins log für Details.\nUUID: {}",
|
||||||
"technician_command_error_message": "Es gab ein Fehler mit dem Befehl: {} ausgelöst von {} -> {}\nDatum und Zeit: {}\nSchau bitte ins log für Details.UUID: {}",
|
"technician_command_error_message": "Es gab ein Fehler mit dem Befehl: {} ausgelöst von {} -> {}\nDatum und Zeit: {}\nSchau bitte ins log für Details.\nUUID: {}",
|
||||||
"welcome_message": "Hello There!\nIch heiße dich bei {} herzlichst willkommen!",
|
"welcome_message": "Hello There!\nIch heiße dich bei {} herzlichst Willkommen!",
|
||||||
"welcome_message_for_team": "{} hat gerade das Irrenhaus betreten.",
|
"welcome_message_for_team": "{} hat gerade das Irrenhaus betreten.",
|
||||||
"goodbye_message": "Schade das du uns so schnell verlässt :(",
|
"goodbye_message": "Schade, dass du uns so schnell verlässt :(",
|
||||||
"afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?",
|
"afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?",
|
||||||
"afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)",
|
"afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)",
|
||||||
"member_joined_help_voice_channel": "{} braucht hilfe, bitte kümmer dich drum :D",
|
"member_joined_help_voice_channel": "{} braucht hilfe, bitte kümmer dich drum :D",
|
||||||
"pong": "Pong",
|
"pong": "Pong",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Gismo",
|
"title": "Krümmelmonster",
|
||||||
"description": "Informationen über mich",
|
"description": "Informationen über mich",
|
||||||
"fields": {
|
"fields": {
|
||||||
"version": "Version",
|
"version": "Version",
|
||||||
@@ -156,8 +151,17 @@
|
|||||||
},
|
},
|
||||||
"footer": ""
|
"footer": ""
|
||||||
},
|
},
|
||||||
"user_info": {
|
"mass_move": {
|
||||||
"fields": {
|
"moved": "Alle Personen aus {} wurden nach {} verschoben.",
|
||||||
|
"channel_from_error": "Du musst dich in einem Voicechannel befinden oder die Option \"channel_from\" mit angeben."
|
||||||
|
},
|
||||||
|
"presence": {
|
||||||
|
"changed": "Presence wurde geändert.",
|
||||||
|
"removed": "Presence wurde entfernt.",
|
||||||
|
"max_char_count_exceeded": "Der Text darf nicht mehr als 128 Zeichen lang sein!"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"atr": {
|
||||||
"id": "Id",
|
"id": "Id",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"discord_join": "Discord beigetreten am",
|
"discord_join": "Discord beigetreten am",
|
||||||
@@ -169,27 +173,53 @@
|
|||||||
"lefts": "Abgänge",
|
"lefts": "Abgänge",
|
||||||
"warnings": "Verwarnungen"
|
"warnings": "Verwarnungen"
|
||||||
},
|
},
|
||||||
"footer": ""
|
"info": {
|
||||||
|
"footer": ""
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"xp": "{} hat {} xp",
|
||||||
|
"ontime": "{} war insgesamt {} Stunden aktiv in einem Sprachkanal"
|
||||||
|
},
|
||||||
|
"set": {
|
||||||
|
"xp": "{} hat nun {} xp",
|
||||||
|
"error": {
|
||||||
|
"value_type_not_numeric": "Der angegebende Wert ist keine Ganzzahl! :(",
|
||||||
|
"type_error": "Der angegebene Wert ist keine Zahl! :("
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"add": {
|
||||||
|
"xp": "Die {} von {} wurden um {} erhöht"
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"xp": "Die {} von {} wurden um {} verringert"
|
||||||
|
},
|
||||||
|
"reset": {
|
||||||
|
"xp": "Die {} von {} wurden entfernt",
|
||||||
|
"ontime": "Die {} von {} wurden entfernt"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"atr_not_found": "Das Attribut {} konnte nicht gefunden werden :("
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"boot_log": {
|
"boot_log": {
|
||||||
"login_message": "Ich bin on the line :D\nDer Scheiß hat {} Sekunden gedauert"
|
"login_message": "Ich bin on the line :D\nDer Scheiß hat {} Sekunden gedauert"
|
||||||
},
|
},
|
||||||
"level": {
|
"level": {
|
||||||
"new_level_message": "<@{}> ist nun Level {}",
|
"new_level_message": "{} ist nun Level {}",
|
||||||
"seeding_started": "Levelsystem wird neu geladen.",
|
"seeding_started": "Levelsystem wird neu geladen...",
|
||||||
"seeding_failed": "Levelsystem konnte nicht neu geladen werden.",
|
"seeding_failed": "Levelsystem konnte nicht neu geladen werden :(",
|
||||||
"seeding_finished": "Levelsystem wurde Erfolgreich neu geladen.",
|
"seeding_finished": "Levelsystem wurde Erfolgreich neu geladen :)",
|
||||||
"error": {
|
"error": {
|
||||||
"nothing_found": "Keine Level Einträge gefunden.",
|
"nothing_found": "Keine Level Einträge gefunden.",
|
||||||
"level_with_name_already_exists": "Ein Level mit dem Namen {} existiert bereits!",
|
"level_with_name_already_exists": "Ein Level mit dem Namen {} existiert bereits!",
|
||||||
"level_with_xp_already_exists": "Das Level {} hat bereits die Mindest XP {}!"
|
"level_with_xp_already_exists": "Das Level {} hat bereits die Mindest-XP {}!"
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"title": "Level:",
|
"title": "Level:",
|
||||||
"description": "Konfigurierte Level:",
|
"description": "Konfigurierte Level:",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"min_xp": "Mindest XP",
|
"min_xp": "Mindest-XP",
|
||||||
"permission_int": "Berechtigungen"
|
"permission_int": "Berechtigungen"
|
||||||
},
|
},
|
||||||
"create": {
|
"create": {
|
||||||
@@ -249,6 +279,11 @@
|
|||||||
"failed": "Statistik kann nicht gelöscht werden :(",
|
"failed": "Statistik kann nicht gelöscht werden :(",
|
||||||
"success": "Statistik wurde gelöscht :D"
|
"success": "Statistik wurde gelöscht :D"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"technician": {
|
||||||
|
"restart_message": "Bin gleich wieder da :D",
|
||||||
|
"shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, Euer Freund. Lebt lange und in Frieden :)",
|
||||||
|
"log_message": "Hier sind deine Logdateien! :)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"api": {
|
"api": {
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api'
|
__title__ = "bot_api"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.service'
|
__title__ = "bot_api.abc"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -15,75 +15,102 @@ from bot_data.model.auth_user import AuthUser
|
|||||||
|
|
||||||
|
|
||||||
class AuthServiceABC(ABC):
|
class AuthServiceABC(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self): pass
|
def generate_token(self, user: AuthUser) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def generate_token(self, user: AuthUser) -> str: pass
|
def decode_token(self, token: str) -> dict:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def decode_token(self, token: str) -> dict: pass
|
def get_decoded_token_from_request(self) -> dict:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_decoded_token_from_request(self) -> dict: pass
|
def find_decoded_token_from_request(self) -> Optional[dict]:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def find_decoded_token_from_request(self) -> Optional[dict]: pass
|
async def get_all_auth_users_async(self) -> List[AuthUserDTO]:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def get_all_auth_users_async(self) -> List[AuthUserDTO]: pass
|
async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO: pass
|
async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO: pass
|
async def find_auth_user_by_email_async(self, email: str) -> AuthUserDTO:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def find_auth_user_by_email_async(self, email: str) -> AuthUserDTO: pass
|
async def add_auth_user_async(self, user_dto: AuthUserDTO):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def add_auth_user_async(self, user_dto: AuthUserDTO): pass
|
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO): pass
|
async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO: pass
|
async def update_user_async(self, update_user_dto: UpdateAuthUserDTO):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def update_user_async(self, update_user_dto: UpdateAuthUserDTO): pass
|
async def update_user_as_admin_async(self, update_user_dto: UpdateAuthUserDTO):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def update_user_as_admin_async(self, update_user_dto: UpdateAuthUserDTO): pass
|
async def delete_auth_user_by_email_async(self, email: str):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def delete_auth_user_by_email_async(self, email: str): pass
|
async def delete_auth_user_async(self, user_dto: AuthUserDTO):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def delete_auth_user_async(self, user_dto: AuthUserDTO): pass
|
async def verify_login(self, token_str: str) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def verify_login(self, token_str: str) -> bool: pass
|
async def login_async(self, user_dto: AuthUserDTO) -> TokenDTO:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def login_async(self, user_dto: AuthUserDTO) -> TokenDTO: pass
|
async def login_discord_async(self, oauth_dto: AuthUserDTO) -> TokenDTO:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def refresh_async(self, token_dto: TokenDTO) -> TokenDTO: pass
|
async def refresh_async(self, token_dto: TokenDTO) -> TokenDTO:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def revoke_async(self, token_dto: TokenDTO): pass
|
async def revoke_async(self, token_dto: TokenDTO):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def confirm_email_async(self, id: str) -> bool: pass
|
async def confirm_email_async(self, id: str) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def forgot_password_async(self, email: str): pass
|
async def forgot_password_async(self, email: str):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def confirm_forgot_password_async(self, id: str) -> EMailStringDTO: pass
|
async def confirm_forgot_password_async(self, id: str) -> EMailStringDTO:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def reset_password_async(self, rp_dto: ResetPasswordDTO): pass
|
async def reset_password_async(self, rp_dto: ResetPasswordDTO):
|
||||||
|
pass
|
||||||
|
@@ -2,12 +2,14 @@ from abc import ABC, abstractmethod
|
|||||||
|
|
||||||
|
|
||||||
class DtoABC(ABC):
|
class DtoABC(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self): pass
|
def from_dict(self, values: dict):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def from_dict(self, values: dict): pass
|
def to_dict(self) -> dict:
|
||||||
|
pass
|
||||||
@abstractmethod
|
|
||||||
def to_dict(self) -> dict: pass
|
|
||||||
|
@@ -2,15 +2,8 @@ from abc import ABC, abstractmethod
|
|||||||
|
|
||||||
|
|
||||||
class SelectCriteriaABC(ABC):
|
class SelectCriteriaABC(ABC):
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(
|
def __init__(self, page_index: int, page_size: int, sort_direction: str, sort_column: str):
|
||||||
self,
|
|
||||||
page_index: int,
|
|
||||||
page_size: int,
|
|
||||||
sort_direction: str,
|
|
||||||
sort_column: str
|
|
||||||
):
|
|
||||||
self.page_index = page_index
|
self.page_index = page_index
|
||||||
self.page_size = page_size
|
self.page_size = page_size
|
||||||
self.sort_direction = sort_direction
|
self.sort_direction = sort_direction
|
||||||
|
@@ -6,11 +6,12 @@ from bot_api.abc.dto_abc import DtoABC
|
|||||||
|
|
||||||
|
|
||||||
class TransformerABC:
|
class TransformerABC:
|
||||||
|
@staticmethod
|
||||||
|
@abstractmethod
|
||||||
|
def to_db(dto: DtoABC) -> TableABC:
|
||||||
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def to_db(dto: DtoABC) -> TableABC: pass
|
def to_dto(db: TableABC) -> DtoABC:
|
||||||
|
pass
|
||||||
@staticmethod
|
|
||||||
@abstractmethod
|
|
||||||
def to_dto(db: TableABC) -> DtoABC: pass
|
|
||||||
|
@@ -25,18 +25,18 @@ from bot_api.route.route import Route
|
|||||||
|
|
||||||
|
|
||||||
class Api(Flask):
|
class Api(Flask):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
logger: ApiLogger,
|
logger: ApiLogger,
|
||||||
services: ServiceProviderABC,
|
services: ServiceProviderABC,
|
||||||
api_settings: ApiSettings,
|
api_settings: ApiSettings,
|
||||||
frontend_settings: FrontendSettings,
|
frontend_settings: FrontendSettings,
|
||||||
auth_settings: AuthenticationSettings,
|
auth_settings: AuthenticationSettings,
|
||||||
*args, **kwargs
|
*args,
|
||||||
|
**kwargs,
|
||||||
):
|
):
|
||||||
if not args:
|
if not args:
|
||||||
kwargs.setdefault('import_name', __name__)
|
kwargs.setdefault("import_name", __name__)
|
||||||
|
|
||||||
Flask.__init__(self, *args, **kwargs)
|
Flask.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
@@ -56,17 +56,21 @@ class Api(Flask):
|
|||||||
self.register_error_handler(exc_class, self.handle_exception)
|
self.register_error_handler(exc_class, self.handle_exception)
|
||||||
|
|
||||||
# websockets
|
# websockets
|
||||||
self._socketio = SocketIO(self, cors_allowed_origins='*', path='/api/socket.io')
|
self._socketio = SocketIO(self, cors_allowed_origins="*", path="/api/socket.io")
|
||||||
self._socketio.on_event('connect', self.on_connect)
|
self._socketio.on_event("connect", self.on_connect)
|
||||||
self._socketio.on_event('disconnect', self.on_disconnect)
|
self._socketio.on_event("disconnect", self.on_disconnect)
|
||||||
|
|
||||||
self._requests = {}
|
self._requests = {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_methods_from_registered_route() -> Union[list[str], str]:
|
def _get_methods_from_registered_route() -> Union[list[str], str]:
|
||||||
methods = ['Unknown']
|
methods = ["Unknown"]
|
||||||
if request.path in Route.registered_routes and len(Route.registered_routes[request.path]) >= 1 and 'methods' in Route.registered_routes[request.path][1]:
|
if (
|
||||||
methods = Route.registered_routes[request.path][1]['methods']
|
request.path in Route.registered_routes
|
||||||
|
and len(Route.registered_routes[request.path]) >= 1
|
||||||
|
and "methods" in Route.registered_routes[request.path][1]
|
||||||
|
):
|
||||||
|
methods = Route.registered_routes[request.path][1]["methods"]
|
||||||
|
|
||||||
if len(methods) == 1:
|
if len(methods) == 1:
|
||||||
return methods[0]
|
return methods[0]
|
||||||
@@ -77,7 +81,7 @@ class Api(Flask):
|
|||||||
route = f[0]
|
route = f[0]
|
||||||
kwargs = f[1]
|
kwargs = f[1]
|
||||||
cls = None
|
cls = None
|
||||||
qual_name_split = route.__qualname__.split('.')
|
qual_name_split = route.__qualname__.split(".")
|
||||||
if len(qual_name_split) > 0:
|
if len(qual_name_split) > 0:
|
||||||
cls_type = vars(sys.modules[route.__module__])[qual_name_split[0]]
|
cls_type = vars(sys.modules[route.__module__])[qual_name_split[0]]
|
||||||
cls = self._services.get_service(cls_type)
|
cls = self._services.get_service(cls_type)
|
||||||
@@ -87,7 +91,7 @@ class Api(Flask):
|
|||||||
self.route(path, **kwargs)(partial_f)
|
self.route(path, **kwargs)(partial_f)
|
||||||
|
|
||||||
def handle_exception(self, e: Exception):
|
def handle_exception(self, e: Exception):
|
||||||
self._logger.error(__name__, f'Caught error', e)
|
self._logger.error(__name__, f"Caught error", e)
|
||||||
|
|
||||||
if isinstance(e, ServiceException):
|
if isinstance(e, ServiceException):
|
||||||
ex: ServiceException = e
|
ex: ServiceException = e
|
||||||
@@ -100,7 +104,7 @@ class Api(Flask):
|
|||||||
return jsonify(error.to_dict()), 404
|
return jsonify(error.to_dict()), 404
|
||||||
else:
|
else:
|
||||||
tracking_id = uuid.uuid4()
|
tracking_id = uuid.uuid4()
|
||||||
user_message = f'Tracking Id: {tracking_id}'
|
user_message = f"Tracking Id: {tracking_id}"
|
||||||
self._logger.error(__name__, user_message, e)
|
self._logger.error(__name__, user_message, e)
|
||||||
error = ErrorDTO(None, user_message)
|
error = ErrorDTO(None, user_message)
|
||||||
return jsonify(error.to_dict()), 400
|
return jsonify(error.to_dict()), 400
|
||||||
@@ -110,34 +114,42 @@ class Api(Flask):
|
|||||||
self._requests[request] = request_id
|
self._requests[request] = request_id
|
||||||
method = request.access_control_request_method
|
method = request.access_control_request_method
|
||||||
|
|
||||||
self._logger.info(__name__, f'Received {request_id} @ {self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}')
|
self._logger.info(
|
||||||
|
__name__,
|
||||||
|
f"Received {request_id} @ {self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}",
|
||||||
|
)
|
||||||
|
|
||||||
headers = str(request.headers).replace('\n', '\n\t\t')
|
headers = str(request.headers).replace("\n", "\n\t\t")
|
||||||
data = request.get_data()
|
data = request.get_data()
|
||||||
data = '' if len(data) == 0 else str(data.decode(encoding="utf-8"))
|
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\tUser-Agent: {request.user_agent.string}\n\tBody: {data}')
|
text = textwrap.dedent(
|
||||||
|
f"Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tUser-Agent: {request.user_agent.string}\n\tBody: {data}"
|
||||||
|
)
|
||||||
self._logger.trace(__name__, text)
|
self._logger.trace(__name__, text)
|
||||||
|
|
||||||
def after_request_hook(self, response: Response):
|
def after_request_hook(self, response: Response):
|
||||||
method = request.access_control_request_method
|
method = request.access_control_request_method
|
||||||
request_id = f'{self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}'
|
request_id = f"{self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}"
|
||||||
if request in self._requests:
|
if request in self._requests:
|
||||||
request_id = self._requests[request]
|
request_id = self._requests[request]
|
||||||
|
|
||||||
self._logger.info(__name__, f'Answered {request_id}')
|
self._logger.info(__name__, f"Answered {request_id}")
|
||||||
|
|
||||||
headers = str(request.headers).replace('\n', '\n\t\t')
|
headers = str(request.headers).replace("\n", "\n\t\t")
|
||||||
data = request.get_data()
|
data = request.get_data()
|
||||||
data = '' if len(data) == 0 else str(data.decode(encoding="utf-8"))
|
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)
|
self._logger.trace(__name__, text)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def start(self):
|
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._register_routes()
|
||||||
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
|
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
|
||||||
# from waitress import serve
|
# from waitress import serve
|
||||||
@@ -146,11 +158,11 @@ class Api(Flask):
|
|||||||
wsgi.server(
|
wsgi.server(
|
||||||
eventlet.listen((self._api_settings.host, self._api_settings.port)),
|
eventlet.listen((self._api_settings.host, self._api_settings.port)),
|
||||||
self,
|
self,
|
||||||
log_output=False
|
log_output=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_connect(self):
|
def on_connect(self):
|
||||||
self._logger.info(__name__, f'Client connected')
|
self._logger.info(__name__, f"Client connected")
|
||||||
|
|
||||||
def on_disconnect(self):
|
def on_disconnect(self):
|
||||||
self._logger.info(__name__, f'Client disconnected')
|
self._logger.info(__name__, f"Client disconnected")
|
||||||
|
@@ -23,16 +23,15 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
|||||||
|
|
||||||
|
|
||||||
class ApiModule(ModuleABC):
|
class ApiModule(ModuleABC):
|
||||||
|
|
||||||
def __init__(self, dc: DiscordCollectionABC):
|
def __init__(self, dc: DiscordCollectionABC):
|
||||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.api_module)
|
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
|
cwd = env.working_directory
|
||||||
env.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
|
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.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)
|
config.add_json_file(f"config/apisettings.{env.host_name}.json", optional=True)
|
||||||
env.set_working_directory(cwd)
|
env.set_working_directory(cwd)
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||||
|
@@ -5,12 +5,7 @@ from bot_api.logging.api_logger import ApiLogger
|
|||||||
|
|
||||||
|
|
||||||
class ApiThread(threading.Thread):
|
class ApiThread(threading.Thread):
|
||||||
|
def __init__(self, logger: ApiLogger, api: Api):
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
logger: ApiLogger,
|
|
||||||
api: Api
|
|
||||||
):
|
|
||||||
threading.Thread.__init__(self, daemon=True)
|
threading.Thread.__init__(self, daemon=True)
|
||||||
|
|
||||||
self._logger = logger
|
self._logger = logger
|
||||||
@@ -18,7 +13,7 @@ class ApiThread(threading.Thread):
|
|||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
try:
|
try:
|
||||||
self._logger.trace(__name__, f'Try to start {type(self._api).__name__}')
|
self._logger.trace(__name__, f"Try to start {type(self._api).__name__}")
|
||||||
self._api.start()
|
self._api.start()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, 'Start failed', e)
|
self._logger.error(__name__, "Start failed", e)
|
||||||
|
@@ -11,7 +11,6 @@ from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC
|
|||||||
|
|
||||||
|
|
||||||
class AppApiExtension(ApplicationExtensionABC):
|
class AppApiExtension(ApplicationExtensionABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ApplicationExtensionABC.__init__(self)
|
ApplicationExtensionABC.__init__(self)
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
"Version": {
|
"Version": {
|
||||||
"Major": "0",
|
"Major": "0",
|
||||||
"Minor": "3",
|
"Minor": "3",
|
||||||
"Micro": "dev70"
|
"Micro": "1"
|
||||||
},
|
},
|
||||||
"Author": "",
|
"Author": "",
|
||||||
"AuthorEmail": "",
|
"AuthorEmail": "",
|
||||||
@@ -16,10 +16,10 @@
|
|||||||
"LicenseName": "",
|
"LicenseName": "",
|
||||||
"LicenseDescription": "",
|
"LicenseDescription": "",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"cpl-core==2022.10.0.post7"
|
"cpl-core==2022.12.0"
|
||||||
],
|
],
|
||||||
"DevDependencies": [
|
"DevDependencies": [
|
||||||
"cpl-cli==2022.10.0"
|
"cpl-cli==2022.12.0"
|
||||||
],
|
],
|
||||||
"PythonVersion": ">=3.10.4",
|
"PythonVersion": ">=3.10.4",
|
||||||
"PythonPath": {},
|
"PythonPath": {},
|
||||||
|
Submodule kdb-bot/src/bot_api/config updated: 98303ffd45...e6046881b5
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.configuration'
|
__title__ = "bot_api.configuration"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -5,12 +5,11 @@ from cpl_core.console import Console
|
|||||||
|
|
||||||
|
|
||||||
class ApiSettings(ConfigurationModelABC):
|
class ApiSettings(ConfigurationModelABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
self._port = 80
|
self._port = 80
|
||||||
self._host = ''
|
self._host = ""
|
||||||
self._redirect_to_https = False
|
self._redirect_to_https = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -27,9 +26,9 @@ class ApiSettings(ConfigurationModelABC):
|
|||||||
|
|
||||||
def from_dict(self, settings: dict):
|
def from_dict(self, settings: dict):
|
||||||
try:
|
try:
|
||||||
self._port = int(settings['Port'])
|
self._port = int(settings["Port"])
|
||||||
self._host = settings['Host']
|
self._host = settings["Host"]
|
||||||
self._redirect_to_https = bool(settings['RedirectToHTTPS'])
|
self._redirect_to_https = bool(settings["RedirectToHTTPS"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
|
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@@ -6,13 +6,12 @@ from cpl_core.console import Console
|
|||||||
|
|
||||||
|
|
||||||
class AuthenticationSettings(ConfigurationModelABC):
|
class AuthenticationSettings(ConfigurationModelABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
self._secret_key = ''
|
self._secret_key = ""
|
||||||
self._issuer = ''
|
self._issuer = ""
|
||||||
self._audience = ''
|
self._audience = ""
|
||||||
self._token_expire_time = 0
|
self._token_expire_time = 0
|
||||||
self._refresh_token_expire_time = 0
|
self._refresh_token_expire_time = 0
|
||||||
|
|
||||||
@@ -38,11 +37,11 @@ class AuthenticationSettings(ConfigurationModelABC):
|
|||||||
|
|
||||||
def from_dict(self, settings: dict):
|
def from_dict(self, settings: dict):
|
||||||
try:
|
try:
|
||||||
self._secret_key = settings['SecretKey']
|
self._secret_key = settings["SecretKey"]
|
||||||
self._issuer = settings['Issuer']
|
self._issuer = settings["Issuer"]
|
||||||
self._audience = settings['Audience']
|
self._audience = settings["Audience"]
|
||||||
self._token_expire_time = int(settings['TokenExpireTime'])
|
self._token_expire_time = int(settings["TokenExpireTime"])
|
||||||
self._refresh_token_expire_time = int(settings['RefreshTokenExpireTime'])
|
self._refresh_token_expire_time = int(settings["RefreshTokenExpireTime"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
|
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@@ -6,15 +6,14 @@ from cpl_query.extension import List
|
|||||||
|
|
||||||
|
|
||||||
class DiscordAuthenticationSettings(ConfigurationModelABC):
|
class DiscordAuthenticationSettings(ConfigurationModelABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
self._client_secret = ''
|
self._client_secret = ""
|
||||||
self._redirect_url = ''
|
self._redirect_url = ""
|
||||||
self._scope = List()
|
self._scope = List()
|
||||||
self._token_url = ''
|
self._token_url = ""
|
||||||
self._auth_url = ''
|
self._auth_url = ""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def client_secret(self) -> str:
|
def client_secret(self) -> str:
|
||||||
@@ -38,11 +37,11 @@ class DiscordAuthenticationSettings(ConfigurationModelABC):
|
|||||||
|
|
||||||
def from_dict(self, settings: dict):
|
def from_dict(self, settings: dict):
|
||||||
try:
|
try:
|
||||||
self._client_secret = settings['ClientSecret']
|
self._client_secret = settings["ClientSecret"]
|
||||||
self._redirect_url = settings['RedirectURL']
|
self._redirect_url = settings["RedirectURL"]
|
||||||
self._scope = List(str, settings['Scope'])
|
self._scope = List(str, settings["Scope"])
|
||||||
self._token_url = settings['TokenURL']
|
self._token_url = settings["TokenURL"]
|
||||||
self._auth_url = settings['AuthURL']
|
self._auth_url = settings["AuthURL"]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
|
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@@ -5,11 +5,10 @@ from cpl_core.console import Console
|
|||||||
|
|
||||||
|
|
||||||
class FrontendSettings(ConfigurationModelABC):
|
class FrontendSettings(ConfigurationModelABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
self._url = ''
|
self._url = ""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self) -> str:
|
def url(self) -> str:
|
||||||
@@ -17,7 +16,7 @@ class FrontendSettings(ConfigurationModelABC):
|
|||||||
|
|
||||||
def from_dict(self, settings: dict):
|
def from_dict(self, settings: dict):
|
||||||
try:
|
try:
|
||||||
self._url = settings['URL']
|
self._url = settings["URL"]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
|
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@@ -5,13 +5,7 @@ from cpl_cli.configuration.version_settings_name_enum import VersionSettingsName
|
|||||||
|
|
||||||
|
|
||||||
class VersionSettings(ConfigurationModelABC):
|
class VersionSettings(ConfigurationModelABC):
|
||||||
|
def __init__(self, major: str = None, minor: str = None, micro: str = None):
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
major: str = None,
|
|
||||||
minor: str = None,
|
|
||||||
micro: str = None
|
|
||||||
):
|
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
self._major: Optional[str] = major
|
self._major: Optional[str] = major
|
||||||
@@ -32,15 +26,15 @@ class VersionSettings(ConfigurationModelABC):
|
|||||||
|
|
||||||
def to_str(self) -> str:
|
def to_str(self) -> str:
|
||||||
if self._micro is None:
|
if self._micro is None:
|
||||||
return f'{self._major}.{self._minor}'
|
return f"{self._major}.{self._minor}"
|
||||||
else:
|
else:
|
||||||
return f'{self._major}.{self._minor}.{self._micro}'
|
return f"{self._major}.{self._minor}.{self._micro}"
|
||||||
|
|
||||||
def from_dict(self, settings: dict):
|
def from_dict(self, settings: dict):
|
||||||
self._major = settings[VersionSettingsNameEnum.major.value]
|
self._major = settings[VersionSettingsNameEnum.major.value]
|
||||||
self._minor = settings[VersionSettingsNameEnum.minor.value]
|
self._minor = settings[VersionSettingsNameEnum.minor.value]
|
||||||
micro = settings[VersionSettingsNameEnum.micro.value]
|
micro = settings[VersionSettingsNameEnum.micro.value]
|
||||||
if micro != '':
|
if micro != "":
|
||||||
self._micro = micro
|
self._micro = micro
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.controller'
|
__title__ = "bot_api.controller"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -20,18 +20,18 @@ from bot_data.model.auth_role_enum import AuthRoleEnum
|
|||||||
|
|
||||||
|
|
||||||
class AuthController:
|
class AuthController:
|
||||||
BasePath = '/api/auth'
|
BasePath = "/api/auth"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
config: ConfigurationABC,
|
config: ConfigurationABC,
|
||||||
env: ApplicationEnvironmentABC,
|
env: ApplicationEnvironmentABC,
|
||||||
logger: ApiLogger,
|
logger: ApiLogger,
|
||||||
t: TranslatePipe,
|
t: TranslatePipe,
|
||||||
api: Api,
|
api: Api,
|
||||||
mail_settings: EMailClientSettings,
|
mail_settings: EMailClientSettings,
|
||||||
mailer: EMailClientABC,
|
mailer: EMailClientABC,
|
||||||
auth_service: AuthServiceABC
|
auth_service: AuthServiceABC,
|
||||||
):
|
):
|
||||||
self._config = config
|
self._config = config
|
||||||
self._env = env
|
self._env = env
|
||||||
@@ -42,55 +42,57 @@ class AuthController:
|
|||||||
self._mailer = mailer
|
self._mailer = mailer
|
||||||
self._auth_service = auth_service
|
self._auth_service = auth_service
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/users')
|
@Route.get(f"{BasePath}/users")
|
||||||
@Route.authorize(role=AuthRoleEnum.admin)
|
@Route.authorize(role=AuthRoleEnum.admin)
|
||||||
async def get_all_users(self) -> Response:
|
async def get_all_users(self) -> Response:
|
||||||
result = await self._auth_service.get_all_auth_users_async()
|
result = await self._auth_service.get_all_auth_users_async()
|
||||||
return jsonify(result.select(lambda x: x.to_dict()))
|
return jsonify(result.select(lambda x: x.to_dict()).to_list())
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/users/get/filtered')
|
@Route.post(f"{BasePath}/users/get/filtered")
|
||||||
@Route.authorize(role=AuthRoleEnum.admin)
|
@Route.authorize(role=AuthRoleEnum.admin)
|
||||||
async def get_filtered_users(self) -> Response:
|
async def get_filtered_users(self) -> Response:
|
||||||
dto: AuthUserSelectCriteria = JSONProcessor.process(AuthUserSelectCriteria, request.get_json(force=True, silent=True))
|
dto: AuthUserSelectCriteria = JSONProcessor.process(
|
||||||
|
AuthUserSelectCriteria, request.get_json(force=True, silent=True)
|
||||||
|
)
|
||||||
result = await self._auth_service.get_filtered_auth_users_async(dto)
|
result = await self._auth_service.get_filtered_auth_users_async(dto)
|
||||||
result.result = result.result.select(lambda x: x.to_dict())
|
result.result = result.result.select(lambda x: x.to_dict()).to_list()
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/users/get/<email>')
|
@Route.get(f"{BasePath}/users/get/<email>")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def get_user_from_email(self, email: str) -> Response:
|
async def get_user_from_email(self, email: str) -> Response:
|
||||||
result = await self._auth_service.get_auth_user_by_email_async(email)
|
result = await self._auth_service.get_auth_user_by_email_async(email)
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/users/find/<email>')
|
@Route.get(f"{BasePath}/users/find/<email>")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def find_user_from_email(self, email: str) -> Response:
|
async def find_user_from_email(self, email: str) -> Response:
|
||||||
result = await self._auth_service.find_auth_user_by_email_async(email)
|
result = await self._auth_service.find_auth_user_by_email_async(email)
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/register')
|
@Route.post(f"{BasePath}/register")
|
||||||
async def register(self):
|
async def register(self):
|
||||||
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
||||||
await self._auth_service.add_auth_user_async(dto)
|
await self._auth_service.add_auth_user_async(dto)
|
||||||
return '', 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/register-by-id/<id>')
|
@Route.post(f"{BasePath}/register-by-id/<id>")
|
||||||
async def register_id(self, id: str):
|
async def register_id(self, id: str):
|
||||||
result = await self._auth_service.confirm_email_async(id)
|
result = await self._auth_service.confirm_email_async(id)
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/login')
|
@Route.post(f"{BasePath}/login")
|
||||||
async def login(self) -> Response:
|
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)
|
result = await self._auth_service.login_async(dto)
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/verify-login')
|
@Route.get(f"{BasePath}/verify-login")
|
||||||
async def verify_login(self):
|
async def verify_login(self):
|
||||||
token = None
|
token = None
|
||||||
result = False
|
result = False
|
||||||
if 'Authorization' in request.headers:
|
if "Authorization" in request.headers:
|
||||||
bearer = request.headers.get('Authorization')
|
bearer = request.headers.get("Authorization")
|
||||||
token = bearer.split()[1]
|
token = bearer.split()[1]
|
||||||
|
|
||||||
if token is not None:
|
if token is not None:
|
||||||
@@ -98,58 +100,58 @@ class AuthController:
|
|||||||
|
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/forgot-password/<email>')
|
@Route.post(f"{BasePath}/forgot-password/<email>")
|
||||||
async def forgot_password(self, email: str):
|
async def forgot_password(self, email: str):
|
||||||
await self._auth_service.forgot_password_async(email)
|
await self._auth_service.forgot_password_async(email)
|
||||||
return '', 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/confirm-forgot-password/<id>')
|
@Route.post(f"{BasePath}/confirm-forgot-password/<id>")
|
||||||
async def confirm_forgot_password(self, id: str):
|
async def confirm_forgot_password(self, id: str):
|
||||||
result = await self._auth_service.confirm_forgot_password_async(id)
|
result = await self._auth_service.confirm_forgot_password_async(id)
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/reset-password')
|
@Route.post(f"{BasePath}/reset-password")
|
||||||
async def reset_password(self):
|
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)
|
await self._auth_service.reset_password_async(dto)
|
||||||
return '', 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/update-user')
|
@Route.post(f"{BasePath}/update-user")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def update_user(self):
|
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)
|
await self._auth_service.update_user_async(dto)
|
||||||
return '', 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/update-user-as-admin')
|
@Route.post(f"{BasePath}/update-user-as-admin")
|
||||||
@Route.authorize(role=AuthRoleEnum.admin)
|
@Route.authorize(role=AuthRoleEnum.admin)
|
||||||
async def update_user_as_admin(self):
|
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)
|
await self._auth_service.update_user_as_admin_async(dto)
|
||||||
return '', 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/refresh')
|
@Route.post(f"{BasePath}/refresh")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def refresh(self) -> Response:
|
async def refresh(self) -> Response:
|
||||||
dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True))
|
dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True))
|
||||||
result = await self._auth_service.refresh_async(dto)
|
result = await self._auth_service.refresh_async(dto)
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/revoke')
|
@Route.post(f"{BasePath}/revoke")
|
||||||
async def revoke(self):
|
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)
|
await self._auth_service.revoke_async(dto)
|
||||||
return '', 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/delete-user')
|
@Route.post(f"{BasePath}/delete-user")
|
||||||
@Route.authorize(role=AuthRoleEnum.admin)
|
@Route.authorize(role=AuthRoleEnum.admin)
|
||||||
async def delete_user(self):
|
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)
|
await self._auth_service.delete_auth_user_async(dto)
|
||||||
return '', 200
|
return "", 200
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/delete-user-by-mail/<email>')
|
@Route.post(f"{BasePath}/delete-user-by-mail/<email>")
|
||||||
@Route.authorize(role=AuthRoleEnum.admin)
|
@Route.authorize(role=AuthRoleEnum.admin)
|
||||||
async def delete_user_by_mail(self, email: str):
|
async def delete_user_by_mail(self, email: str):
|
||||||
await self._auth_service.delete_auth_user_by_email_async(email)
|
await self._auth_service.delete_auth_user_by_email_async(email)
|
||||||
return '', 200
|
return "", 200
|
||||||
|
@@ -13,7 +13,9 @@ from requests_oauthlib import OAuth2Session
|
|||||||
|
|
||||||
from bot_api.abc.auth_service_abc import AuthServiceABC
|
from bot_api.abc.auth_service_abc import AuthServiceABC
|
||||||
from bot_api.api import Api
|
from bot_api.api import Api
|
||||||
from bot_api.configuration.discord_authentication_settings import DiscordAuthenticationSettings
|
from bot_api.configuration.discord_authentication_settings import (
|
||||||
|
DiscordAuthenticationSettings,
|
||||||
|
)
|
||||||
from bot_api.json_processor import JSONProcessor
|
from bot_api.json_processor import JSONProcessor
|
||||||
from bot_api.logging.api_logger import ApiLogger
|
from bot_api.logging.api_logger import ApiLogger
|
||||||
from bot_api.model.auth_user_dto import AuthUserDTO
|
from bot_api.model.auth_user_dto import AuthUserDTO
|
||||||
@@ -22,24 +24,24 @@ from bot_api.route.route import Route
|
|||||||
from bot_data.model.auth_role_enum import AuthRoleEnum
|
from bot_data.model.auth_role_enum import AuthRoleEnum
|
||||||
|
|
||||||
# Disable SSL requirement
|
# Disable SSL requirement
|
||||||
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
|
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
|
||||||
|
|
||||||
|
|
||||||
class AuthDiscordController:
|
class AuthDiscordController:
|
||||||
BasePath = '/api/auth/discord'
|
BasePath = "/api/auth/discord"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
auth_settings: DiscordAuthenticationSettings,
|
auth_settings: DiscordAuthenticationSettings,
|
||||||
config: ConfigurationABC,
|
config: ConfigurationABC,
|
||||||
env: ApplicationEnvironmentABC,
|
env: ApplicationEnvironmentABC,
|
||||||
logger: ApiLogger,
|
logger: ApiLogger,
|
||||||
bot: DiscordBotServiceABC,
|
bot: DiscordBotServiceABC,
|
||||||
t: TranslatePipe,
|
t: TranslatePipe,
|
||||||
api: Api,
|
api: Api,
|
||||||
mail_settings: EMailClientSettings,
|
mail_settings: EMailClientSettings,
|
||||||
mailer: EMailClientABC,
|
mailer: EMailClientABC,
|
||||||
auth_service: AuthServiceABC
|
auth_service: AuthServiceABC,
|
||||||
):
|
):
|
||||||
self._auth_settings = auth_settings
|
self._auth_settings = auth_settings
|
||||||
self._config = config
|
self._config = config
|
||||||
@@ -53,37 +55,59 @@ class AuthDiscordController:
|
|||||||
self._auth_service = auth_service
|
self._auth_service = auth_service
|
||||||
|
|
||||||
def _get_user_from_discord_response(self) -> dict:
|
def _get_user_from_discord_response(self) -> dict:
|
||||||
discord = OAuth2Session(self._bot.user.id, redirect_uri=self._auth_settings.redirect_url, state=request.args.get('state'), scope=self._auth_settings.scope)
|
discord = OAuth2Session(
|
||||||
|
self._bot.user.id,
|
||||||
|
redirect_uri=self._auth_settings.redirect_url,
|
||||||
|
state=request.args.get("state"),
|
||||||
|
scope=self._auth_settings.scope,
|
||||||
|
)
|
||||||
token = discord.fetch_token(
|
token = discord.fetch_token(
|
||||||
self._auth_settings.token_url,
|
self._auth_settings.token_url,
|
||||||
client_secret=CredentialManager.decrypt(self._auth_settings.client_secret),
|
client_secret=CredentialManager.decrypt(self._auth_settings.client_secret),
|
||||||
authorization_response=request.url,
|
authorization_response=request.url,
|
||||||
)
|
)
|
||||||
discord = OAuth2Session(self._bot.user.id, token=token)
|
discord = OAuth2Session(self._bot.user.id, token=token)
|
||||||
return discord.get('https://discordapp.com/api' + '/users/@me').json()
|
return discord.get("https://discordapp.com/api" + "/users/@me").json()
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/get-url')
|
@Route.get(f"{BasePath}/get-url")
|
||||||
async def get_url(self):
|
async def get_url(self):
|
||||||
oauth = OAuth2Session(self._bot.user.id, redirect_uri=self._auth_settings.redirect_url, scope=self._auth_settings.scope)
|
oauth = OAuth2Session(
|
||||||
|
self._bot.user.id,
|
||||||
|
redirect_uri=self._auth_settings.redirect_url,
|
||||||
|
scope=self._auth_settings.scope,
|
||||||
|
)
|
||||||
login_url, state = oauth.authorization_url(self._auth_settings.auth_url)
|
login_url, state = oauth.authorization_url(self._auth_settings.auth_url)
|
||||||
return jsonify({'loginUrl': login_url})
|
return jsonify({"loginUrl": login_url})
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/create-user')
|
@Route.get(f"{BasePath}/create-user")
|
||||||
async def discord_create_user(self) -> Response:
|
async def discord_create_user(self) -> Response:
|
||||||
response = self._get_user_from_discord_response()
|
response = self._get_user_from_discord_response()
|
||||||
result = await self._auth_service.add_auth_user_by_discord_async(AuthUserDTO(
|
result = await self._auth_service.add_auth_user_by_discord_async(
|
||||||
0,
|
AuthUserDTO(
|
||||||
response['username'],
|
0,
|
||||||
response['discriminator'],
|
response["username"],
|
||||||
response['email'],
|
response["discriminator"],
|
||||||
str(uuid.uuid4()),
|
response["email"],
|
||||||
None,
|
str(uuid.uuid4()),
|
||||||
AuthRoleEnum.normal
|
None,
|
||||||
), response['id'])
|
AuthRoleEnum.normal,
|
||||||
|
),
|
||||||
|
response["id"],
|
||||||
|
)
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/register')
|
@Route.get(f"{BasePath}/login")
|
||||||
async def discord_register(self):
|
async def discord_login(self) -> Response:
|
||||||
dto: OAuthDTO = JSONProcessor.process(OAuthDTO, request.get_json(force=True, silent=True))
|
response = self._get_user_from_discord_response()
|
||||||
await self._auth_service.add_auth_user_by_oauth_async(dto)
|
dto = AuthUserDTO(
|
||||||
return '', 200
|
0,
|
||||||
|
response["username"],
|
||||||
|
response["discriminator"],
|
||||||
|
response["email"],
|
||||||
|
str(uuid.uuid4()),
|
||||||
|
None,
|
||||||
|
AuthRoleEnum.normal,
|
||||||
|
)
|
||||||
|
|
||||||
|
result = await self._auth_service.login_discord_async(dto)
|
||||||
|
return jsonify(result.to_dict())
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.controller.discord'
|
__title__ = "bot_api.controller.discord"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -14,18 +14,18 @@ from bot_data.model.auth_role_enum import AuthRoleEnum
|
|||||||
|
|
||||||
|
|
||||||
class ServerController:
|
class ServerController:
|
||||||
BasePath = f'/api/discord/server'
|
BasePath = f"/api/discord/server"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
config: ConfigurationABC,
|
config: ConfigurationABC,
|
||||||
env: ApplicationEnvironmentABC,
|
env: ApplicationEnvironmentABC,
|
||||||
logger: ApiLogger,
|
logger: ApiLogger,
|
||||||
t: TranslatePipe,
|
t: TranslatePipe,
|
||||||
api: Api,
|
api: Api,
|
||||||
mail_settings: EMailClientSettings,
|
mail_settings: EMailClientSettings,
|
||||||
mailer: EMailClientABC,
|
mailer: EMailClientABC,
|
||||||
discord_service: DiscordService
|
discord_service: DiscordService,
|
||||||
):
|
):
|
||||||
self._config = config
|
self._config = config
|
||||||
self._env = env
|
self._env = env
|
||||||
@@ -36,30 +36,32 @@ class ServerController:
|
|||||||
self._mailer = mailer
|
self._mailer = mailer
|
||||||
self._discord_service = discord_service
|
self._discord_service = discord_service
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/get/servers')
|
@Route.get(f"{BasePath}/get/servers")
|
||||||
@Route.authorize(role=AuthRoleEnum.admin)
|
@Route.authorize(role=AuthRoleEnum.admin)
|
||||||
async def get_all_servers(self) -> Response:
|
async def get_all_servers(self) -> Response:
|
||||||
result = await self._discord_service.get_all_servers()
|
result = await self._discord_service.get_all_servers()
|
||||||
result = result.select(lambda x: x.to_dict())
|
result = result.select(lambda x: x.to_dict()).to_list()
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/get/servers-by-user')
|
@Route.get(f"{BasePath}/get/servers-by-user")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def get_all_servers_by_user(self) -> Response:
|
async def get_all_servers_by_user(self) -> Response:
|
||||||
result = await self._discord_service.get_all_servers_by_user()
|
result = await self._discord_service.get_all_servers_by_user()
|
||||||
result = result.select(lambda x: x.to_dict())
|
result = result.select(lambda x: x.to_dict()).to_list()
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/get/filtered')
|
@Route.post(f"{BasePath}/get/filtered")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def get_filtered_servers(self) -> Response:
|
async def get_filtered_servers(self) -> Response:
|
||||||
dto: ServerSelectCriteria = JSONProcessor.process(ServerSelectCriteria, request.get_json(force=True, silent=True))
|
dto: ServerSelectCriteria = JSONProcessor.process(
|
||||||
|
ServerSelectCriteria, request.get_json(force=True, silent=True)
|
||||||
|
)
|
||||||
result = await self._discord_service.get_filtered_servers_async(dto)
|
result = await self._discord_service.get_filtered_servers_async(dto)
|
||||||
result.result = result.result.select(lambda x: x.to_dict())
|
result.result = result.result.select(lambda x: x.to_dict()).to_list()
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/get/<id>')
|
@Route.get(f"{BasePath}/get/<id>")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def get_server_by_id(self, id: int) -> Response:
|
async def get_server_by_id(self, id: int) -> Response:
|
||||||
result = await self._discord_service.get_server_by_id_async(id)
|
result = await self._discord_service.get_server_by_id_async(id).to_list()
|
||||||
return jsonify(result.to_dict())
|
return jsonify(result.to_dict())
|
||||||
|
@@ -15,18 +15,18 @@ from bot_api.route.route import Route
|
|||||||
|
|
||||||
|
|
||||||
class GuiController:
|
class GuiController:
|
||||||
BasePath = f'/api/gui'
|
BasePath = f"/api/gui"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
config: ConfigurationABC,
|
config: ConfigurationABC,
|
||||||
env: ApplicationEnvironmentABC,
|
env: ApplicationEnvironmentABC,
|
||||||
logger: ApiLogger,
|
logger: ApiLogger,
|
||||||
t: TranslatePipe,
|
t: TranslatePipe,
|
||||||
api: Api,
|
api: Api,
|
||||||
mail_settings: EMailClientSettings,
|
mail_settings: EMailClientSettings,
|
||||||
mailer: EMailClientABC,
|
mailer: EMailClientABC,
|
||||||
auth_settings: AuthenticationSettings
|
auth_settings: AuthenticationSettings,
|
||||||
):
|
):
|
||||||
self._config = config
|
self._config = config
|
||||||
self._env = env
|
self._env = env
|
||||||
@@ -37,42 +37,48 @@ class GuiController:
|
|||||||
self._mailer = mailer
|
self._mailer = mailer
|
||||||
self._auth_settings = auth_settings
|
self._auth_settings = auth_settings
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/api-version')
|
@Route.get(f"{BasePath}/api-version")
|
||||||
async def api_version(self):
|
async def api_version(self):
|
||||||
import bot_api
|
import bot_api
|
||||||
|
|
||||||
version = bot_api.version_info
|
version = bot_api.version_info
|
||||||
return VersionDTO(version.major, version.minor, version.micro).to_dict()
|
return VersionDTO(version.major, version.minor, version.micro).to_dict()
|
||||||
|
|
||||||
@Route.get(f'{BasePath}/settings')
|
@Route.get(f"{BasePath}/settings")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def settings(self):
|
async def settings(self):
|
||||||
import bot_api
|
import bot_api
|
||||||
|
|
||||||
version = bot_api.version_info
|
version = bot_api.version_info
|
||||||
|
|
||||||
return jsonify(SettingsDTO(
|
return jsonify(
|
||||||
'',
|
SettingsDTO(
|
||||||
VersionDTO(version.major, version.minor, version.micro),
|
"",
|
||||||
os.path.abspath(os.path.join(self._env.working_directory, 'config')),
|
VersionDTO(version.major, version.minor, version.micro),
|
||||||
'/',
|
os.path.abspath(os.path.join(self._env.working_directory, "config")),
|
||||||
'/',
|
"/",
|
||||||
self._auth_settings.token_expire_time,
|
"/",
|
||||||
self._auth_settings.refresh_token_expire_time,
|
self._auth_settings.token_expire_time,
|
||||||
self._mail_settings.user_name,
|
self._auth_settings.refresh_token_expire_time,
|
||||||
self._mail_settings.port,
|
self._mail_settings.user_name,
|
||||||
self._mail_settings.host,
|
self._mail_settings.port,
|
||||||
self._mail_settings.user_name,
|
self._mail_settings.host,
|
||||||
self._mail_settings.user_name,
|
self._mail_settings.user_name,
|
||||||
).to_dict())
|
self._mail_settings.user_name,
|
||||||
|
).to_dict()
|
||||||
|
)
|
||||||
|
|
||||||
@Route.post(f'{BasePath}/send-test-mail/<email>')
|
@Route.post(f"{BasePath}/send-test-mail/<email>")
|
||||||
@Route.authorize
|
@Route.authorize
|
||||||
async def send_test_mail(self, email: str):
|
async def send_test_mail(self, email: str):
|
||||||
mail = EMail()
|
mail = EMail()
|
||||||
mail.add_header('Mime-Version: 1.0')
|
mail.add_header("Mime-Version: 1.0")
|
||||||
mail.add_header('Content-Type: text/plain; charset=utf-8')
|
mail.add_header("Content-Type: text/plain; charset=utf-8")
|
||||||
mail.add_header('Content-Transfer-Encoding: quoted-printable')
|
mail.add_header("Content-Transfer-Encoding: quoted-printable")
|
||||||
mail.add_receiver(email)
|
mail.add_receiver(email)
|
||||||
mail.subject = self._t.transform('api.api.test_mail.subject')
|
mail.subject = self._t.transform("api.api.test_mail.subject")
|
||||||
mail.body = self._t.transform('api.api.test_mail.message').format(self._env.host_name, self._env.environment_name)
|
mail.body = self._t.transform("api.api.test_mail.message").format(
|
||||||
|
self._env.host_name, self._env.environment_name
|
||||||
|
)
|
||||||
self._mailer.send_mail(mail)
|
self._mailer.send_mail(mail)
|
||||||
return '', 200
|
return "", 200
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.event'
|
__title__ = "bot_api.event"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -4,7 +4,6 @@ from bot_api.api_thread import ApiThread
|
|||||||
|
|
||||||
|
|
||||||
class BotApiOnReadyEvent(OnReadyABC):
|
class BotApiOnReadyEvent(OnReadyABC):
|
||||||
|
|
||||||
def __init__(self, api: ApiThread):
|
def __init__(self, api: ApiThread):
|
||||||
OnReadyABC.__init__(self)
|
OnReadyABC.__init__(self)
|
||||||
self._api = api
|
self._api = api
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.exception'
|
__title__ = "bot_api.exception"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -2,7 +2,6 @@ from bot_api.exception.service_error_code_enum import ServiceErrorCode
|
|||||||
|
|
||||||
|
|
||||||
class ServiceException(Exception):
|
class ServiceException(Exception):
|
||||||
|
|
||||||
def __init__(self, error_code: ServiceErrorCode, message: str, *args):
|
def __init__(self, error_code: ServiceErrorCode, message: str, *args):
|
||||||
Exception.__init__(self, *args)
|
Exception.__init__(self, *args)
|
||||||
|
|
||||||
@@ -10,4 +9,4 @@ class ServiceException(Exception):
|
|||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
def get_detailed_message(self) -> str:
|
def get_detailed_message(self) -> str:
|
||||||
return f'ServiceException - ErrorCode: {self.error_code} - ErrorMessage: {self.message}'
|
return f"ServiceException - ErrorCode: {self.error_code} - ErrorMessage: {self.message}"
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.filter'
|
__title__ = "bot_api.filter"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -2,18 +2,16 @@ from bot_api.abc.select_criteria_abc import SelectCriteriaABC
|
|||||||
|
|
||||||
|
|
||||||
class AuthUserSelectCriteria(SelectCriteriaABC):
|
class AuthUserSelectCriteria(SelectCriteriaABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
page_index: int,
|
page_index: int,
|
||||||
page_size: int,
|
page_size: int,
|
||||||
sort_direction: str,
|
sort_direction: str,
|
||||||
sort_column: str,
|
sort_column: str,
|
||||||
|
first_name: str,
|
||||||
first_name: str,
|
last_name: str,
|
||||||
last_name: str,
|
email: str,
|
||||||
email: str,
|
auth_role: int,
|
||||||
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)
|
||||||
|
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.filter.discord'
|
__title__ = "bot_api.filter.discord"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -2,15 +2,13 @@ from bot_api.abc.select_criteria_abc import SelectCriteriaABC
|
|||||||
|
|
||||||
|
|
||||||
class ServerSelectCriteria(SelectCriteriaABC):
|
class ServerSelectCriteria(SelectCriteriaABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
page_index: int,
|
page_index: int,
|
||||||
page_size: int,
|
page_size: int,
|
||||||
sort_direction: str,
|
sort_direction: str,
|
||||||
sort_column: str,
|
sort_column: str,
|
||||||
|
name: 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)
|
||||||
|
|
||||||
|
@@ -5,7 +5,6 @@ from cpl_core.utils import String
|
|||||||
|
|
||||||
|
|
||||||
class JSONProcessor:
|
class JSONProcessor:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def process(_t: type, values: dict) -> object:
|
def process(_t: type, values: dict) -> object:
|
||||||
args = []
|
args = []
|
||||||
@@ -13,14 +12,14 @@ class JSONProcessor:
|
|||||||
sig = signature(_t.__init__)
|
sig = signature(_t.__init__)
|
||||||
for param in sig.parameters.items():
|
for param in sig.parameters.items():
|
||||||
parameter = param[1]
|
parameter = param[1]
|
||||||
if parameter.name == 'self' or parameter.annotation == Parameter.empty:
|
if parameter.name == "self" or parameter.annotation == Parameter.empty:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
name = String.convert_to_camel_case(parameter.name)
|
name = String.convert_to_camel_case(parameter.name)
|
||||||
name = name.replace('Dto', 'DTO')
|
name = name.replace("Dto", "DTO")
|
||||||
name_first_lower = String.first_to_lower(name)
|
name_first_lower = String.first_to_lower(name)
|
||||||
if name in values or name_first_lower in values:
|
if name in values or name_first_lower in values:
|
||||||
value = ''
|
value = ""
|
||||||
if name in values:
|
if name in values:
|
||||||
value = values[name]
|
value = values[name]
|
||||||
else:
|
else:
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.logging'
|
__title__ = "bot_api.logging"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -6,6 +6,10 @@ from bot_core.abc.custom_file_logger_abc import CustomFileLoggerABC
|
|||||||
|
|
||||||
|
|
||||||
class ApiLogger(CustomFileLoggerABC):
|
class ApiLogger(CustomFileLoggerABC):
|
||||||
|
def __init__(
|
||||||
def __init__(self, config: ConfigurationABC, time_format: TimeFormatSettings, env: ApplicationEnvironmentABC):
|
self,
|
||||||
CustomFileLoggerABC.__init__(self, 'Api', config, time_format, env)
|
config: ConfigurationABC,
|
||||||
|
time_format: TimeFormatSettings,
|
||||||
|
env: ApplicationEnvironmentABC,
|
||||||
|
):
|
||||||
|
CustomFileLoggerABC.__init__(self, "Api", config, time_format, env)
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.model'
|
__title__ = "bot_api.model"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -5,16 +5,15 @@ from bot_data.model.auth_role_enum import AuthRoleEnum
|
|||||||
|
|
||||||
|
|
||||||
class AuthUserDTO(DtoABC):
|
class AuthUserDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
id: int = None,
|
id: int = None,
|
||||||
first_name: str = None,
|
first_name: str = None,
|
||||||
last_name: str = None,
|
last_name: str = None,
|
||||||
email: str = None,
|
email: str = None,
|
||||||
password: str = None,
|
password: str = None,
|
||||||
confirmation_id: Optional[str] = None,
|
confirmation_id: Optional[str] = None,
|
||||||
auth_role: AuthRoleEnum = None,
|
auth_role: AuthRoleEnum = None,
|
||||||
):
|
):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
@@ -79,21 +78,21 @@ class AuthUserDTO(DtoABC):
|
|||||||
self._auth_role = value
|
self._auth_role = value
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._id = values['id']
|
self._id = values["id"]
|
||||||
self._first_name = values['firstName']
|
self._first_name = values["firstName"]
|
||||||
self._last_name = values['lastName']
|
self._last_name = values["lastName"]
|
||||||
self._email = values['email']
|
self._email = values["email"]
|
||||||
self._password = values['password']
|
self._password = values["password"]
|
||||||
self._is_confirmed = values['isConfirmed']
|
self._is_confirmed = values["isConfirmed"]
|
||||||
self._auth_role = AuthRoleEnum(values['authRole'])
|
self._auth_role = AuthRoleEnum(values["authRole"])
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {
|
||||||
'id': self._id,
|
"id": self._id,
|
||||||
'firstName': self._first_name,
|
"firstName": self._first_name,
|
||||||
'lastName': self._last_name,
|
"lastName": self._last_name,
|
||||||
'email': self._email,
|
"email": self._email,
|
||||||
'password': self._password,
|
"password": self._password,
|
||||||
'isConfirmed': self._is_confirmed,
|
"isConfirmed": self._is_confirmed,
|
||||||
'authRole': self._auth_role.value,
|
"authRole": self._auth_role.value,
|
||||||
}
|
}
|
||||||
|
@@ -5,17 +5,13 @@ from bot_data.filtered_result import FilteredResult
|
|||||||
|
|
||||||
|
|
||||||
class AuthUserFilteredResultDTO(DtoABC, FilteredResult):
|
class AuthUserFilteredResultDTO(DtoABC, FilteredResult):
|
||||||
|
|
||||||
def __init__(self, result: List = None, total_count: int = 0):
|
def __init__(self, result: List = None, total_count: int = 0):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
FilteredResult.__init__(self, result, total_count)
|
FilteredResult.__init__(self, result, total_count)
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._result = values['users']
|
self._result = values["users"]
|
||||||
self._total_count = values['totalCount']
|
self._total_count = values["totalCount"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {"users": self.result, "totalCount": self.total_count}
|
||||||
'users': self.result,
|
|
||||||
'totalCount': self.total_count
|
|
||||||
}
|
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.model.discord'
|
__title__ = "bot_api.model.discord"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -4,15 +4,13 @@ from bot_api.abc.dto_abc import DtoABC
|
|||||||
|
|
||||||
|
|
||||||
class ServerDTO(DtoABC):
|
class ServerDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
server_id: int,
|
server_id: int,
|
||||||
discord_id: int,
|
discord_id: int,
|
||||||
name: str,
|
name: str,
|
||||||
member_count: int,
|
member_count: int,
|
||||||
icon_url: Optional[str]
|
icon_url: Optional[str],
|
||||||
|
|
||||||
):
|
):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
@@ -21,19 +19,19 @@ class ServerDTO(DtoABC):
|
|||||||
self._name = name
|
self._name = name
|
||||||
self._member_count = member_count
|
self._member_count = member_count
|
||||||
self._icon_url = icon_url
|
self._icon_url = icon_url
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def server_id(self) -> int:
|
def server_id(self) -> int:
|
||||||
return self._server_id
|
return self._server_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def discord_id(self) -> int:
|
def discord_id(self) -> int:
|
||||||
return self._discord_id
|
return self._discord_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def member_count(self) -> int:
|
def member_count(self) -> int:
|
||||||
return self._member_count
|
return self._member_count
|
||||||
@@ -43,16 +41,16 @@ class ServerDTO(DtoABC):
|
|||||||
return self._icon_url
|
return self._icon_url
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._server_id = int(values['serverId'])
|
self._server_id = int(values["serverId"])
|
||||||
self._discord_id = int(values['discordId'])
|
self._discord_id = int(values["discordId"])
|
||||||
self._name = values['name']
|
self._name = values["name"]
|
||||||
self._icon_url = values['iconURL']
|
self._icon_url = values["iconURL"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {
|
||||||
'serverId': self._server_id,
|
"serverId": self._server_id,
|
||||||
'discordId': self._discord_id,
|
"discordId": self._discord_id,
|
||||||
'name': self._name,
|
"name": self._name,
|
||||||
'memberCount': self._member_count,
|
"memberCount": self._member_count,
|
||||||
'iconURL': self._icon_url,
|
"iconURL": self._icon_url,
|
||||||
}
|
}
|
||||||
|
@@ -5,17 +5,13 @@ from bot_data.filtered_result import FilteredResult
|
|||||||
|
|
||||||
|
|
||||||
class ServerFilteredResultDTO(DtoABC, FilteredResult):
|
class ServerFilteredResultDTO(DtoABC, FilteredResult):
|
||||||
|
|
||||||
def __init__(self, result: List = None, total_count: int = 0):
|
def __init__(self, result: List = None, total_count: int = 0):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
FilteredResult.__init__(self, result, total_count)
|
FilteredResult.__init__(self, result, total_count)
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._result = values['servers']
|
self._result = values["servers"]
|
||||||
self._total_count = values['totalCount']
|
self._total_count = values["totalCount"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {"servers": self.result, "totalCount": self.total_count}
|
||||||
'servers': self.result,
|
|
||||||
'totalCount': self.total_count
|
|
||||||
}
|
|
||||||
|
@@ -6,16 +6,13 @@ from bot_api.abc.dto_abc import DtoABC
|
|||||||
|
|
||||||
|
|
||||||
class EMailStringDTO(DtoABC):
|
class EMailStringDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(self, email: str):
|
def __init__(self, email: str):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
self._email = email
|
self._email = email
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._email = values['email']
|
self._email = values["email"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {"email": self._email}
|
||||||
'email': self._email
|
|
||||||
}
|
|
||||||
|
@@ -8,7 +8,6 @@ from bot_api.exception.service_error_code_enum import ServiceErrorCode
|
|||||||
|
|
||||||
|
|
||||||
class ErrorDTO(DtoABC):
|
class ErrorDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(self, error_code: Optional[ServiceErrorCode], message: str):
|
def __init__(self, error_code: Optional[ServiceErrorCode], message: str):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
@@ -24,11 +23,8 @@ class ErrorDTO(DtoABC):
|
|||||||
return self._message
|
return self._message
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._error_code = values['ErrorCode']
|
self._error_code = values["ErrorCode"]
|
||||||
self._message = values['Message']
|
self._message = values["Message"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {"errorCode": int(self._error_code.value), "message": self._message}
|
||||||
'errorCode': int(self._error_code.value),
|
|
||||||
'message': self._message
|
|
||||||
}
|
|
||||||
|
@@ -6,11 +6,10 @@ from bot_data.model.auth_role_enum import AuthRoleEnum
|
|||||||
|
|
||||||
|
|
||||||
class OAuthDTO(DtoABC):
|
class OAuthDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
user: AuthUserDTO,
|
user: AuthUserDTO,
|
||||||
o_auth_id: Optional[str],
|
o_auth_id: Optional[str],
|
||||||
):
|
):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
@@ -34,11 +33,8 @@ class OAuthDTO(DtoABC):
|
|||||||
self._oauth_id = value
|
self._oauth_id = value
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._user = AuthUserDTO().from_dict(values['user'])
|
self._user = AuthUserDTO().from_dict(values["user"])
|
||||||
self._oauth_id = values['oAuthId']
|
self._oauth_id = values["oAuthId"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {"user": self._user.to_dict(), "oAuthId": self._oauth_id}
|
||||||
'user': self._user.to_dict(),
|
|
||||||
'oAuthId': self._oauth_id
|
|
||||||
}
|
|
||||||
|
@@ -6,7 +6,6 @@ from bot_api.abc.dto_abc import DtoABC
|
|||||||
|
|
||||||
|
|
||||||
class ResetPasswordDTO(DtoABC):
|
class ResetPasswordDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(self, id: str, password: str):
|
def __init__(self, id: str, password: str):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
@@ -22,11 +21,8 @@ class ResetPasswordDTO(DtoABC):
|
|||||||
return self._password
|
return self._password
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._id = values['id']
|
self._id = values["id"]
|
||||||
self._password = values['password']
|
self._password = values["password"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {"id": self._id, "password": self._password}
|
||||||
'id': self._id,
|
|
||||||
'password': self._password
|
|
||||||
}
|
|
||||||
|
@@ -3,21 +3,20 @@ from bot_api.model.version_dto import VersionDTO
|
|||||||
|
|
||||||
|
|
||||||
class SettingsDTO(DtoABC):
|
class SettingsDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
web_version: str,
|
web_version: str,
|
||||||
api_version: VersionDTO,
|
api_version: VersionDTO,
|
||||||
config_path: str,
|
config_path: str,
|
||||||
web_base_url: str,
|
web_base_url: str,
|
||||||
api_base_url: str,
|
api_base_url: str,
|
||||||
token_expire_time: int,
|
token_expire_time: int,
|
||||||
refresh_token_expire_time: int,
|
refresh_token_expire_time: int,
|
||||||
mail_user: str,
|
mail_user: str,
|
||||||
mail_port: int,
|
mail_port: int,
|
||||||
mail_host: str,
|
mail_host: str,
|
||||||
mail_transceiver: str,
|
mail_transceiver: str,
|
||||||
mail_transceiver_address: str,
|
mail_transceiver_address: str,
|
||||||
):
|
):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
@@ -37,31 +36,31 @@ class SettingsDTO(DtoABC):
|
|||||||
self._mail_transceiver_address = mail_transceiver_address
|
self._mail_transceiver_address = mail_transceiver_address
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._web_version = values['webVersion']
|
self._web_version = values["webVersion"]
|
||||||
self._api_version.from_dict(values['apiVersion'])
|
self._api_version.from_dict(values["apiVersion"])
|
||||||
self._config_path = values['configPath']
|
self._config_path = values["configPath"]
|
||||||
self._web_base_url = values['webBaseURL']
|
self._web_base_url = values["webBaseURL"]
|
||||||
self._api_base_url = values['apiBaseURL']
|
self._api_base_url = values["apiBaseURL"]
|
||||||
self._token_expire_time = values['tokenExpireTime']
|
self._token_expire_time = values["tokenExpireTime"]
|
||||||
self._refresh_token_expire_time = values['refreshTokenExpireTime']
|
self._refresh_token_expire_time = values["refreshTokenExpireTime"]
|
||||||
self._mail_user = values['mailUser']
|
self._mail_user = values["mailUser"]
|
||||||
self._mail_port = values['mailPort']
|
self._mail_port = values["mailPort"]
|
||||||
self._mail_host = values['mailHost']
|
self._mail_host = values["mailHost"]
|
||||||
self._mail_transceiver = values['mailTransceiver']
|
self._mail_transceiver = values["mailTransceiver"]
|
||||||
self._mail_transceiver_address = values['mailTransceiverAddress']
|
self._mail_transceiver_address = values["mailTransceiverAddress"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {
|
||||||
'webVersion': self._web_version,
|
"webVersion": self._web_version,
|
||||||
'apiVersion': self._api_version.str,
|
"apiVersion": self._api_version.str,
|
||||||
'configPath': self._config_path,
|
"configPath": self._config_path,
|
||||||
'webBaseURL': self._web_base_url,
|
"webBaseURL": self._web_base_url,
|
||||||
'apiBaseURL': self._api_base_url,
|
"apiBaseURL": self._api_base_url,
|
||||||
'tokenExpireTime': self._token_expire_time,
|
"tokenExpireTime": self._token_expire_time,
|
||||||
'refreshTokenExpireTime': self._refresh_token_expire_time,
|
"refreshTokenExpireTime": self._refresh_token_expire_time,
|
||||||
'mailUser': self._mail_user,
|
"mailUser": self._mail_user,
|
||||||
'mailPort': self._mail_port,
|
"mailPort": self._mail_port,
|
||||||
'mailHost': self._mail_host,
|
"mailHost": self._mail_host,
|
||||||
'mailTransceiver': self._mail_transceiver,
|
"mailTransceiver": self._mail_transceiver,
|
||||||
'mailTransceiverAddress': self._mail_transceiver_address,
|
"mailTransceiverAddress": self._mail_transceiver_address,
|
||||||
}
|
}
|
||||||
|
@@ -6,27 +6,23 @@ from bot_api.abc.dto_abc import DtoABC
|
|||||||
|
|
||||||
|
|
||||||
class TokenDTO(DtoABC):
|
class TokenDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(self, token: str, refresh_token: str):
|
def __init__(self, token: str, refresh_token: str):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
self._token = token
|
self._token = token
|
||||||
self._refresh_token = refresh_token
|
self._refresh_token = refresh_token
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def token(self) -> str:
|
def token(self) -> str:
|
||||||
return self._token
|
return self._token
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def refresh_token(self) -> str:
|
def refresh_token(self) -> str:
|
||||||
return self._refresh_token
|
return self._refresh_token
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._token = values['token']
|
self._token = values["token"]
|
||||||
self._refresh_token = values['refreshToken']
|
self._refresh_token = values["refreshToken"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {"token": self._token, "refreshToken": self._refresh_token}
|
||||||
'token': self._token,
|
|
||||||
'refreshToken': self._refresh_token
|
|
||||||
}
|
|
||||||
|
@@ -7,12 +7,11 @@ from bot_api.model.auth_user_dto import AuthUserDTO
|
|||||||
|
|
||||||
|
|
||||||
class UpdateAuthUserDTO(DtoABC):
|
class UpdateAuthUserDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
auth_user_dto: AuthUserDTO,
|
auth_user_dto: AuthUserDTO,
|
||||||
new_auth_user_dto: AuthUserDTO,
|
new_auth_user_dto: AuthUserDTO,
|
||||||
change_password: bool = False
|
change_password: bool = False,
|
||||||
):
|
):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
@@ -33,13 +32,13 @@ class UpdateAuthUserDTO(DtoABC):
|
|||||||
return self._change_password
|
return self._change_password
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._auth_user = AuthUserDTO().from_dict(values['authUser'])
|
self._auth_user = AuthUserDTO().from_dict(values["authUser"])
|
||||||
self._new_auth_user = AuthUserDTO().from_dict(values['newAuthUser'])
|
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:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {
|
||||||
'authUser': self._auth_user,
|
"authUser": self._auth_user,
|
||||||
'newAuthUser': self._new_auth_user,
|
"newAuthUser": self._new_auth_user,
|
||||||
'changePassword': self._change_password
|
"changePassword": self._change_password,
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,6 @@ from bot_api.abc.dto_abc import DtoABC
|
|||||||
|
|
||||||
|
|
||||||
class VersionDTO(DtoABC):
|
class VersionDTO(DtoABC):
|
||||||
|
|
||||||
def __init__(self, major: str = None, minor: str = None, micro: str = None):
|
def __init__(self, major: str = None, minor: str = None, micro: str = None):
|
||||||
DtoABC.__init__(self)
|
DtoABC.__init__(self)
|
||||||
|
|
||||||
@@ -28,16 +27,16 @@ class VersionDTO(DtoABC):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def str(self) -> str:
|
def str(self) -> str:
|
||||||
return f'{self._major}.{self._minor}.{self._micro}'
|
return f"{self._major}.{self._minor}.{self._micro}"
|
||||||
|
|
||||||
def from_dict(self, values: dict):
|
def from_dict(self, values: dict):
|
||||||
self._major = values['major']
|
self._major = values["major"]
|
||||||
self._minor = values['minor']
|
self._minor = values["minor"]
|
||||||
self._micro = values['micro']
|
self._micro = values["micro"]
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
return {
|
return {
|
||||||
'major': self._major,
|
"major": self._major,
|
||||||
'minor': self._minor,
|
"minor": self._minor,
|
||||||
'micro': self._micro,
|
"micro": self._micro,
|
||||||
}
|
}
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.route'
|
__title__ = "bot_api.route"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -32,39 +32,39 @@ class Route:
|
|||||||
@wraps(f)
|
@wraps(f)
|
||||||
async def decorator(*args, **kwargs):
|
async def decorator(*args, **kwargs):
|
||||||
token = None
|
token = None
|
||||||
if 'Authorization' in request.headers:
|
if "Authorization" in request.headers:
|
||||||
bearer = request.headers.get('Authorization')
|
bearer = request.headers.get("Authorization")
|
||||||
token = bearer.split()[1]
|
token = bearer.split()[1]
|
||||||
|
|
||||||
if token is None:
|
if token is None:
|
||||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token not set')
|
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set")
|
||||||
error = ErrorDTO(ex.error_code, ex.message)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
if cls._auth_users is None or cls._auth is None:
|
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)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
if not cls._auth.verify_login(token):
|
if not cls._auth.verify_login(token):
|
||||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token expired')
|
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token expired")
|
||||||
error = ErrorDTO(ex.error_code, ex.message)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
token = cls._auth.decode_token(token)
|
token = cls._auth.decode_token(token)
|
||||||
if token is None or 'email' not in token:
|
if token is None or "email" not in token:
|
||||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token invalid')
|
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token invalid")
|
||||||
error = ErrorDTO(ex.error_code, ex.message)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
user = cls._auth_users.get_auth_user_by_email(token['email'])
|
user = cls._auth_users.get_auth_user_by_email(token["email"])
|
||||||
if user is None:
|
if user is None:
|
||||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token invalid')
|
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token invalid")
|
||||||
error = ErrorDTO(ex.error_code, ex.message)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 401
|
return jsonify(error.to_dict()), 401
|
||||||
|
|
||||||
if role is not None and user.auth_role.value < role.value:
|
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)
|
error = ErrorDTO(ex.error_code, ex.message)
|
||||||
return jsonify(error.to_dict()), 403
|
return jsonify(error.to_dict()), 403
|
||||||
|
|
||||||
@@ -84,20 +84,20 @@ class Route:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, path=None, **kwargs):
|
def get(cls, path=None, **kwargs):
|
||||||
return cls.route(path, methods=['GET'], **kwargs)
|
return cls.route(path, methods=["GET"], **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def post(cls, path=None, **kwargs):
|
def post(cls, path=None, **kwargs):
|
||||||
return cls.route(path, methods=['POST'], **kwargs)
|
return cls.route(path, methods=["POST"], **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def head(cls, path=None, **kwargs):
|
def head(cls, path=None, **kwargs):
|
||||||
return cls.route(path, methods=['HEAD'], **kwargs)
|
return cls.route(path, methods=["HEAD"], **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def put(cls, path=None, **kwargs):
|
def put(cls, path=None, **kwargs):
|
||||||
return cls.route(path, methods=['PUT'], **kwargs)
|
return cls.route(path, methods=["PUT"], **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete(cls, path=None, **kwargs):
|
def delete(cls, path=None, **kwargs):
|
||||||
return cls.route(path, methods=['DELETE'], **kwargs)
|
return cls.route(path, methods=["DELETE"], **kwargs)
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.service'
|
__title__ = "bot_api.service"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -38,26 +38,24 @@ from bot_data.model.auth_role_enum import AuthRoleEnum
|
|||||||
from bot_data.model.auth_user import AuthUser
|
from bot_data.model.auth_user import AuthUser
|
||||||
from bot_data.model.auth_user_users_relation import AuthUserUsersRelation
|
from bot_data.model.auth_user_users_relation import AuthUserUsersRelation
|
||||||
|
|
||||||
_email_regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
|
_email_regex = r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"
|
||||||
|
|
||||||
|
|
||||||
class AuthService(AuthServiceABC):
|
class AuthService(AuthServiceABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
env: ApplicationEnvironmentABC,
|
env: ApplicationEnvironmentABC,
|
||||||
logger: ApiLogger,
|
logger: ApiLogger,
|
||||||
bot: DiscordBotServiceABC,
|
bot: DiscordBotServiceABC,
|
||||||
db: DatabaseContextABC,
|
db: DatabaseContextABC,
|
||||||
auth_users: AuthUserRepositoryABC,
|
auth_users: AuthUserRepositoryABC,
|
||||||
users: UserRepositoryABC,
|
users: UserRepositoryABC,
|
||||||
servers: ServerRepositoryABC,
|
servers: ServerRepositoryABC,
|
||||||
# mailer: MailThread,
|
# mailer: MailThread,
|
||||||
mailer: EMailClientABC,
|
mailer: EMailClientABC,
|
||||||
t: TranslatePipe,
|
t: TranslatePipe,
|
||||||
auth_settings: AuthenticationSettings,
|
auth_settings: AuthenticationSettings,
|
||||||
frontend_settings: FrontendSettings,
|
frontend_settings: FrontendSettings,
|
||||||
|
|
||||||
):
|
):
|
||||||
AuthServiceABC.__init__(self)
|
AuthServiceABC.__init__(self)
|
||||||
|
|
||||||
@@ -75,7 +73,7 @@ class AuthService(AuthServiceABC):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _hash_sha256(password: str, salt: str) -> str:
|
def _hash_sha256(password: str, salt: str) -> str:
|
||||||
return hashlib.sha256(f'{password}{salt}'.encode('utf-8')).hexdigest()
|
return hashlib.sha256(f"{password}{salt}".encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_email_valid(email: str) -> bool:
|
def _is_email_valid(email: str) -> bool:
|
||||||
@@ -87,14 +85,14 @@ class AuthService(AuthServiceABC):
|
|||||||
def generate_token(self, user: AuthUser) -> str:
|
def generate_token(self, user: AuthUser) -> str:
|
||||||
token = jwt.encode(
|
token = jwt.encode(
|
||||||
payload={
|
payload={
|
||||||
'user_id': user.id,
|
"user_id": user.id,
|
||||||
'email': user.email,
|
"email": user.email,
|
||||||
'role': user.auth_role.value,
|
"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,
|
"iss": self._auth_settings.issuer,
|
||||||
'aud': self._auth_settings.audience
|
"aud": self._auth_settings.audience,
|
||||||
},
|
},
|
||||||
key=CredentialManager.decrypt(self._auth_settings.secret_key)
|
key=CredentialManager.decrypt(self._auth_settings.secret_key),
|
||||||
)
|
)
|
||||||
|
|
||||||
return token
|
return token
|
||||||
@@ -105,39 +103,43 @@ class AuthService(AuthServiceABC):
|
|||||||
key=CredentialManager.decrypt(self._auth_settings.secret_key),
|
key=CredentialManager.decrypt(self._auth_settings.secret_key),
|
||||||
issuer=self._auth_settings.issuer,
|
issuer=self._auth_settings.issuer,
|
||||||
audience=self._auth_settings.audience,
|
audience=self._auth_settings.audience,
|
||||||
algorithms=['HS256']
|
algorithms=["HS256"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_decoded_token_from_request(self) -> dict:
|
def get_decoded_token_from_request(self) -> dict:
|
||||||
token = None
|
token = None
|
||||||
if 'Authorization' in request.headers:
|
if "Authorization" in request.headers:
|
||||||
bearer = request.headers.get('Authorization')
|
bearer = request.headers.get("Authorization")
|
||||||
token = bearer.split()[1]
|
token = bearer.split()[1]
|
||||||
|
|
||||||
if token is None:
|
if token is None:
|
||||||
raise ServiceException(ServiceErrorCode.Unauthorized, f'Token not set')
|
raise ServiceException(ServiceErrorCode.Unauthorized, f"Token not set")
|
||||||
|
|
||||||
return jwt.decode(
|
return jwt.decode(
|
||||||
token,
|
token,
|
||||||
key=CredentialManager.decrypt(self._auth_settings.secret_key),
|
key=CredentialManager.decrypt(self._auth_settings.secret_key),
|
||||||
issuer=self._auth_settings.issuer,
|
issuer=self._auth_settings.issuer,
|
||||||
audience=self._auth_settings.audience,
|
audience=self._auth_settings.audience,
|
||||||
algorithms=['HS256']
|
algorithms=["HS256"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def find_decoded_token_from_request(self) -> Optional[dict]:
|
def find_decoded_token_from_request(self) -> Optional[dict]:
|
||||||
token = None
|
token = None
|
||||||
if 'Authorization' in request.headers:
|
if "Authorization" in request.headers:
|
||||||
bearer = request.headers.get('Authorization')
|
bearer = request.headers.get("Authorization")
|
||||||
token = bearer.split()[1]
|
token = bearer.split()[1]
|
||||||
|
|
||||||
return jwt.decode(
|
return (
|
||||||
token,
|
jwt.decode(
|
||||||
key=CredentialManager.decrypt(self._auth_settings.secret_key),
|
token,
|
||||||
issuer=self._auth_settings.issuer,
|
key=CredentialManager.decrypt(self._auth_settings.secret_key),
|
||||||
audience=self._auth_settings.audience,
|
issuer=self._auth_settings.issuer,
|
||||||
algorithms=['HS256']
|
audience=self._auth_settings.audience,
|
||||||
) if token is not None else None
|
algorithms=["HS256"],
|
||||||
|
)
|
||||||
|
if token is not None
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
def _create_and_save_refresh_token(self, user: AuthUser) -> str:
|
def _create_and_save_refresh_token(self, user: AuthUser) -> str:
|
||||||
token = str(uuid.uuid4())
|
token = str(uuid.uuid4())
|
||||||
@@ -149,58 +151,56 @@ class AuthService(AuthServiceABC):
|
|||||||
|
|
||||||
def _send_link_mail(self, email: str, subject: str, message: str):
|
def _send_link_mail(self, email: str, subject: str, message: str):
|
||||||
url = self._frontend_settings.url
|
url = self._frontend_settings.url
|
||||||
if not url.endswith('/'):
|
if not url.endswith("/"):
|
||||||
url = f'{url}/'
|
url = f"{url}/"
|
||||||
|
|
||||||
self._mailer.connect()
|
self._mailer.connect()
|
||||||
mail = EMail()
|
mail = EMail()
|
||||||
mail.add_header('Mime-Version: 1.0')
|
mail.add_header("Mime-Version: 1.0")
|
||||||
mail.add_header('Content-Type: text/plain; charset=utf-8')
|
mail.add_header("Content-Type: text/plain; charset=utf-8")
|
||||||
mail.add_header('Content-Transfer-Encoding: quoted-printable')
|
mail.add_header("Content-Transfer-Encoding: quoted-printable")
|
||||||
mail.add_receiver(str(email))
|
mail.add_receiver(str(email))
|
||||||
mail.subject = subject
|
mail.subject = subject
|
||||||
mail.body = textwrap.dedent(f"""{message}
|
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)}
|
{self._t.transform('api.mail.automatic_mail').format(self._environment.application_name, self._environment.environment_name, self._environment.host_name)}
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
thr = Thread(target=self._mailer.send_mail, args=[mail])
|
thr = Thread(target=self._mailer.send_mail, args=[mail])
|
||||||
thr.start()
|
thr.start()
|
||||||
|
|
||||||
def _send_confirmation_id_to_user(self, user: AuthUser):
|
def _send_confirmation_id_to_user(self, user: AuthUser):
|
||||||
url = self._frontend_settings.url
|
url = self._frontend_settings.url
|
||||||
if not url.endswith('/'):
|
if not url.endswith("/"):
|
||||||
url = f'{url}/'
|
url = f"{url}/"
|
||||||
|
|
||||||
self._send_link_mail(
|
self._send_link_mail(
|
||||||
user.email,
|
user.email,
|
||||||
self._t.transform('api.auth.confirmation.subject').format(user.first_name, user.last_name),
|
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.message").format(url, user.confirmation_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _send_forgot_password_id_to_user(self, user: AuthUser):
|
def _send_forgot_password_id_to_user(self, user: AuthUser):
|
||||||
url = self._frontend_settings.url
|
url = self._frontend_settings.url
|
||||||
if not url.endswith('/'):
|
if not url.endswith("/"):
|
||||||
url = f'{url}/'
|
url = f"{url}/"
|
||||||
|
|
||||||
self._send_link_mail(
|
self._send_link_mail(
|
||||||
user.email,
|
user.email,
|
||||||
self._t.transform('api.auth.forgot_password.subject').format(user.first_name, user.last_name),
|
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.message").format(url, user.forgot_password_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
async def get_all_auth_users_async(self) -> List[AuthUserDTO]:
|
async def get_all_auth_users_async(self) -> List[AuthUserDTO]:
|
||||||
result = self._auth_users.get_all_auth_users() \
|
result = self._auth_users.get_all_auth_users().select(lambda x: AUT.to_dto(x))
|
||||||
.select(lambda x: AUT.to_dto(x))
|
|
||||||
return List(AuthUserDTO, result)
|
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)
|
users = self._auth_users.get_filtered_auth_users(criteria)
|
||||||
result = users.result.select(lambda x: AUT.to_dto(x))
|
result = users.result.select(lambda x: AUT.to_dto(x))
|
||||||
|
|
||||||
return AuthUserFilteredResultDTO(
|
return AuthUserFilteredResultDTO(List(AuthUserDTO, result), users.total_count)
|
||||||
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:
|
try:
|
||||||
@@ -208,8 +208,8 @@ class AuthService(AuthServiceABC):
|
|||||||
user = self._auth_users.get_auth_user_by_email(email)
|
user = self._auth_users.get_auth_user_by_email(email)
|
||||||
return AUT.to_dto(user, password=user.password if with_password else None)
|
return AUT.to_dto(user, password=user.password if with_password else None)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f'AuthUser not found', 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]:
|
async def find_auth_user_by_email_async(self, email: str) -> Optional[AuthUser]:
|
||||||
user = self._auth_users.find_auth_user_by_email(email)
|
user = self._auth_users.find_auth_user_by_email(email)
|
||||||
@@ -218,7 +218,7 @@ class AuthService(AuthServiceABC):
|
|||||||
async def add_auth_user_async(self, user_dto: AuthUserDTO):
|
async def add_auth_user_async(self, user_dto: AuthUserDTO):
|
||||||
db_user = self._auth_users.find_auth_user_by_email(user_dto.email)
|
db_user = self._auth_users.find_auth_user_by_email(user_dto.email)
|
||||||
if db_user is not None:
|
if db_user is not None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists')
|
raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists")
|
||||||
|
|
||||||
user = AUT.to_db(user_dto)
|
user = AUT.to_db(user_dto)
|
||||||
if self._auth_users.get_all_auth_users().count() == 0:
|
if self._auth_users.get_all_auth_users().count() == 0:
|
||||||
@@ -227,26 +227,26 @@ class AuthService(AuthServiceABC):
|
|||||||
user.password_salt = uuid.uuid4()
|
user.password_salt = uuid.uuid4()
|
||||||
user.password = self._hash_sha256(user_dto.password, user.password_salt)
|
user.password = self._hash_sha256(user_dto.password, user.password_salt)
|
||||||
if not self._is_email_valid(user.email):
|
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:
|
try:
|
||||||
user.confirmation_id = uuid.uuid4()
|
user.confirmation_id = uuid.uuid4()
|
||||||
self._auth_users.add_auth_user(user)
|
self._auth_users.add_auth_user(user)
|
||||||
self._send_confirmation_id_to_user(user)
|
self._send_confirmation_id_to_user(user)
|
||||||
self._db.save_changes()
|
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:
|
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")
|
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
|
||||||
|
|
||||||
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO):
|
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO):
|
||||||
db_user = self._auth_users.find_auth_user_by_email(dto.user.email)
|
db_user = self._auth_users.find_auth_user_by_email(dto.user.email)
|
||||||
|
|
||||||
if db_user is None:
|
if db_user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, 'User not found')
|
raise ServiceException(ServiceErrorCode.InvalidUser, "User not found")
|
||||||
|
|
||||||
if db_user.oauth_id != dto.oauth_id:
|
if db_user.oauth_id != dto.oauth_id:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, 'Wrong OAuthId')
|
raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong OAuthId")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db_user.first_name = dto.user.first_name
|
db_user.first_name = dto.user.first_name
|
||||||
@@ -257,9 +257,9 @@ class AuthService(AuthServiceABC):
|
|||||||
db_user.confirmation_id = uuid.uuid4()
|
db_user.confirmation_id = uuid.uuid4()
|
||||||
self._send_confirmation_id_to_user(db_user)
|
self._send_confirmation_id_to_user(db_user)
|
||||||
self._auth_users.update_auth_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:
|
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")
|
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
|
||||||
|
|
||||||
self._db.save_changes()
|
self._db.save_changes()
|
||||||
@@ -270,23 +270,23 @@ class AuthService(AuthServiceABC):
|
|||||||
# user exists
|
# user exists
|
||||||
if db_auth_user is not None and db_auth_user.users.count() > 0:
|
if db_auth_user is not None and db_auth_user.users.count() > 0:
|
||||||
# raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists')
|
# raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists')
|
||||||
self._logger.debug(__name__, f'Discord user already exists')
|
self._logger.debug(__name__, f"Discord user already exists")
|
||||||
return OAuthDTO(AUT.to_dto(db_auth_user), None)
|
return OAuthDTO(AUT.to_dto(db_auth_user), None)
|
||||||
|
|
||||||
# user exists but discord user id not set
|
# user exists but discord user id not set
|
||||||
elif db_auth_user is not None and db_auth_user.users.count() == 0:
|
elif db_auth_user is not None and db_auth_user.users.count() == 0:
|
||||||
self._logger.debug(__name__, f'Auth user exists but not linked with discord')
|
self._logger.debug(__name__, f"Auth user exists but not linked with discord")
|
||||||
# users = self._users.get_users_by_discord_id(user_dto.user_id)
|
# users = self._users.get_users_by_discord_id(user_dto.user_id)
|
||||||
# add auth_user to user refs
|
# add auth_user to user refs
|
||||||
db_auth_user.oauth_id = None
|
db_auth_user.oauth_id = None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# user does not exists
|
# user does not exists
|
||||||
self._logger.debug(__name__, f'Auth user does not exist')
|
self._logger.debug(__name__, f"Auth user does not exist")
|
||||||
try:
|
try:
|
||||||
user_dto.user_id = self._users.get_users_by_discord_id(user_dto.user_id).single().user_id
|
user_dto.user_id = self._users.get_users_by_discord_id(user_dto.user_id).single().user_id
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f'User not found')
|
self._logger.error(__name__, f"User not found")
|
||||||
user_dto.user_id = None
|
user_dto.user_id = None
|
||||||
|
|
||||||
await self.add_auth_user_async(user_dto)
|
await self.add_auth_user_async(user_dto)
|
||||||
@@ -311,46 +311,61 @@ class AuthService(AuthServiceABC):
|
|||||||
|
|
||||||
async def update_user_async(self, update_user_dto: UpdateAuthUserDTO):
|
async def update_user_async(self, update_user_dto: UpdateAuthUserDTO):
|
||||||
if update_user_dto is None:
|
if update_user_dto is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f'User is empty')
|
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
||||||
|
|
||||||
if update_user_dto.auth_user is None:
|
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:
|
if update_user_dto.new_auth_user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f'New user is empty')
|
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(
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f'Invalid E-Mail')
|
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)
|
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
|
||||||
if user is None:
|
if user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, 'User not found')
|
raise ServiceException(ServiceErrorCode.InvalidUser, "User not found")
|
||||||
|
|
||||||
if user.confirmation_id is not None:
|
if user.confirmation_id is not None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed')
|
raise ServiceException(ServiceErrorCode.InvalidUser, "E-Mail not confirmed")
|
||||||
|
|
||||||
# update first name
|
# 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:
|
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
|
||||||
|
):
|
||||||
user.first_name = update_user_dto.new_auth_user.first_name
|
user.first_name = update_user_dto.new_auth_user.first_name
|
||||||
|
|
||||||
# update last name
|
# update last name
|
||||||
if update_user_dto.new_auth_user.last_name is not None and update_user_dto.new_auth_user.last_name != '' and \
|
if (
|
||||||
update_user_dto.auth_user.last_name != update_user_dto.new_auth_user.last_name:
|
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
|
||||||
|
):
|
||||||
user.last_name = update_user_dto.new_auth_user.last_name
|
user.last_name = update_user_dto.new_auth_user.last_name
|
||||||
|
|
||||||
# update E-Mail
|
# update E-Mail
|
||||||
if update_user_dto.new_auth_user.email is not None and update_user_dto.new_auth_user.email != '' and update_user_dto.auth_user.email != update_user_dto.new_auth_user.email:
|
if (
|
||||||
|
update_user_dto.new_auth_user.email is not None
|
||||||
|
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:
|
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
|
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:
|
if update_user_dto.auth_user.password != user.password:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, 'Wrong password')
|
raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password")
|
||||||
|
|
||||||
# update 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:
|
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
|
||||||
|
):
|
||||||
user.password_salt = uuid.uuid4()
|
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)
|
||||||
|
|
||||||
@@ -359,20 +374,22 @@ class AuthService(AuthServiceABC):
|
|||||||
|
|
||||||
async def update_user_as_admin_async(self, update_user_dto: UpdateAuthUserDTO):
|
async def update_user_as_admin_async(self, update_user_dto: UpdateAuthUserDTO):
|
||||||
if update_user_dto is None:
|
if update_user_dto is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f'User is empty')
|
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
||||||
|
|
||||||
if update_user_dto.auth_user is None:
|
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:
|
if update_user_dto.new_auth_user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f'New user is empty')
|
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(
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f'Invalid E-Mail')
|
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)
|
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
|
||||||
if user is None:
|
if user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, 'User not found')
|
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
|
user.confirmation_id = None
|
||||||
@@ -382,27 +399,45 @@ class AuthService(AuthServiceABC):
|
|||||||
# raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed')
|
# raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed')
|
||||||
|
|
||||||
# update first name
|
# 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:
|
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
|
||||||
|
):
|
||||||
user.first_name = update_user_dto.new_auth_user.first_name
|
user.first_name = update_user_dto.new_auth_user.first_name
|
||||||
|
|
||||||
# update last name
|
# update last name
|
||||||
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:
|
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
|
||||||
|
):
|
||||||
user.last_name = update_user_dto.new_auth_user.last_name
|
user.last_name = update_user_dto.new_auth_user.last_name
|
||||||
|
|
||||||
# update E-Mail
|
# update E-Mail
|
||||||
if update_user_dto.new_auth_user.email is not None and update_user_dto.new_auth_user.email != '' and update_user_dto.auth_user.email != update_user_dto.new_auth_user.email:
|
if (
|
||||||
|
update_user_dto.new_auth_user.email is not None
|
||||||
|
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:
|
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
|
user.email = update_user_dto.new_auth_user.email
|
||||||
|
|
||||||
# update password
|
# 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):
|
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)
|
||||||
|
):
|
||||||
user.password_salt = uuid.uuid4()
|
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
|
# update role
|
||||||
if user.auth_role == update_user_dto.auth_user.auth_role and user.auth_role != update_user_dto.new_auth_user.auth_role:
|
if (
|
||||||
|
user.auth_role == update_user_dto.auth_user.auth_role
|
||||||
|
and user.auth_role != update_user_dto.new_auth_user.auth_role
|
||||||
|
):
|
||||||
user.auth_role = update_user_dto.new_auth_user.auth_role
|
user.auth_role = update_user_dto.new_auth_user.auth_role
|
||||||
|
|
||||||
self._auth_users.update_auth_user(user)
|
self._auth_users.update_auth_user(user)
|
||||||
@@ -414,43 +449,46 @@ class AuthService(AuthServiceABC):
|
|||||||
self._auth_users.delete_auth_user(user)
|
self._auth_users.delete_auth_user(user)
|
||||||
self._db.save_changes()
|
self._db.save_changes()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f'Cannot delete user', 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):
|
async def delete_auth_user_async(self, user_dto: AuthUser):
|
||||||
try:
|
try:
|
||||||
self._auth_users.delete_auth_user(AUT.to_db(user_dto))
|
self._auth_users.delete_auth_user(AUT.to_db(user_dto))
|
||||||
self._db.save_changes()
|
self._db.save_changes()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f'Cannot delete user', e)
|
self._logger.error(__name__, f"Cannot delete user", e)
|
||||||
raise ServiceException(ServiceErrorCode.UnableToDelete, f'Cannot delete user by mail {user_dto.email}')
|
raise ServiceException(
|
||||||
|
ServiceErrorCode.UnableToDelete,
|
||||||
|
f"Cannot delete user by mail {user_dto.email}",
|
||||||
|
)
|
||||||
|
|
||||||
def verify_login(self, token_str: str) -> bool:
|
def verify_login(self, token_str: str) -> bool:
|
||||||
try:
|
try:
|
||||||
token = self.decode_token(token_str)
|
token = self.decode_token(token_str)
|
||||||
if token is None or 'email' not in token:
|
if token is None or "email" not in token:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, 'Token invalid')
|
raise ServiceException(ServiceErrorCode.InvalidData, "Token invalid")
|
||||||
|
|
||||||
user = self._auth_users.find_auth_user_by_email(token['email'])
|
user = self._auth_users.find_auth_user_by_email(token["email"])
|
||||||
if user is None:
|
if user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, 'Token expired')
|
raise ServiceException(ServiceErrorCode.InvalidData, "Token expired")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f'Token invalid', e)
|
self._logger.error(__name__, f"Token invalid", e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def login_async(self, user_dto: AuthUser) -> TokenDTO:
|
async def login_async(self, user_dto: AuthUser) -> TokenDTO:
|
||||||
if user_dto is None:
|
if user_dto is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, 'User not set')
|
raise ServiceException(ServiceErrorCode.InvalidData, "User not set")
|
||||||
|
|
||||||
db_user = self._auth_users.find_auth_user_by_email(user_dto.email)
|
db_user = self._auth_users.find_auth_user_by_email(user_dto.email)
|
||||||
if db_user is None:
|
if db_user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, f'User not found')
|
raise ServiceException(ServiceErrorCode.InvalidUser, f"User not found")
|
||||||
|
|
||||||
user_dto.password = self._hash_sha256(user_dto.password, db_user.password_salt)
|
user_dto.password = self._hash_sha256(user_dto.password, db_user.password_salt)
|
||||||
if db_user.password != user_dto.password:
|
if db_user.password != user_dto.password:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, 'Wrong password')
|
raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password")
|
||||||
|
|
||||||
token = self.generate_token(db_user)
|
token = self.generate_token(db_user)
|
||||||
refresh_token = self._create_and_save_refresh_token(db_user)
|
refresh_token = self._create_and_save_refresh_token(db_user)
|
||||||
@@ -460,40 +498,66 @@ class AuthService(AuthServiceABC):
|
|||||||
self._db.save_changes()
|
self._db.save_changes()
|
||||||
return TokenDTO(token, refresh_token)
|
return TokenDTO(token, refresh_token)
|
||||||
|
|
||||||
|
async def login_discord_async(self, user_dto: AuthUserDTO) -> TokenDTO:
|
||||||
|
if user_dto is None:
|
||||||
|
raise ServiceException(ServiceErrorCode.InvalidData, "User not set")
|
||||||
|
|
||||||
|
db_user = self._auth_users.find_auth_user_by_email(user_dto.email)
|
||||||
|
if db_user is None:
|
||||||
|
await self.add_auth_user_async(user_dto)
|
||||||
|
# raise ServiceException(ServiceErrorCode.InvalidUser, f'User not found')
|
||||||
|
|
||||||
|
db_user = self._auth_users.get_auth_user_by_email(user_dto.email)
|
||||||
|
token = self.generate_token(db_user)
|
||||||
|
refresh_token = self._create_and_save_refresh_token(db_user)
|
||||||
|
if db_user.forgot_password_id is not None:
|
||||||
|
db_user.forgot_password_id = None
|
||||||
|
|
||||||
|
self._db.save_changes()
|
||||||
|
return TokenDTO(token, refresh_token)
|
||||||
|
|
||||||
async def refresh_async(self, token_dto: TokenDTO) -> TokenDTO:
|
async def refresh_async(self, token_dto: TokenDTO) -> TokenDTO:
|
||||||
if token_dto is None:
|
if token_dto is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f'Token not set')
|
raise ServiceException(ServiceErrorCode.InvalidData, f"Token not set")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
token = self.decode_token(token_dto.token)
|
token = self.decode_token(token_dto.token)
|
||||||
if token is None or 'email' not in token:
|
if token is None or "email" not in token:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, 'Token invalid')
|
raise ServiceException(ServiceErrorCode.InvalidData, "Token invalid")
|
||||||
|
|
||||||
user = self._auth_users.get_auth_user_by_email(token['email'])
|
user = self._auth_users.get_auth_user_by_email(token["email"])
|
||||||
if user is None or user.refresh_token != token_dto.refresh_token or user.refresh_token_expire_time <= datetime.now():
|
if (
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, 'Token expired')
|
user is None
|
||||||
|
or user.refresh_token != token_dto.refresh_token
|
||||||
|
or user.refresh_token_expire_time <= datetime.now()
|
||||||
|
):
|
||||||
|
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:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f'Refreshing token failed', e)
|
self._logger.error(__name__, f"Refreshing token failed", e)
|
||||||
return TokenDTO('', '')
|
return TokenDTO("", "")
|
||||||
|
|
||||||
async def revoke_async(self, token_dto: 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')
|
raise ServiceException(ServiceErrorCode.InvalidData, "Token not set")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
token = self.decode_token(token_dto.token)
|
token = self.decode_token(token_dto.token)
|
||||||
|
|
||||||
user = self._auth_users.get_auth_user_by_email(token['email'])
|
user = self._auth_users.get_auth_user_by_email(token["email"])
|
||||||
if user is None or user.refresh_token != token_dto.refresh_token or user.refresh_token_expire_time <= datetime.now():
|
if (
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, 'Token expired')
|
user is None
|
||||||
|
or user.refresh_token != token_dto.refresh_token
|
||||||
|
or user.refresh_token_expire_time <= datetime.now()
|
||||||
|
):
|
||||||
|
raise ServiceException(ServiceErrorCode.InvalidData, "Token expired")
|
||||||
|
|
||||||
user.refresh_token = None
|
user.refresh_token = None
|
||||||
self._auth_users.update_auth_user(user)
|
self._auth_users.update_auth_user(user)
|
||||||
self._db.save_changes()
|
self._db.save_changes()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logger.error(__name__, f'Refreshing token failed', e)
|
self._logger.error(__name__, f"Refreshing token failed", e)
|
||||||
|
|
||||||
async def confirm_email_async(self, id: str) -> bool:
|
async def confirm_email_async(self, id: str) -> bool:
|
||||||
user = self._auth_users.find_auth_user_by_confirmation_id(id)
|
user = self._auth_users.find_auth_user_by_confirmation_id(id)
|
||||||
@@ -522,13 +586,16 @@ class AuthService(AuthServiceABC):
|
|||||||
async def reset_password_async(self, rp_dto: ResetPasswordDTO):
|
async def reset_password_async(self, rp_dto: ResetPasswordDTO):
|
||||||
user = self._auth_users.find_auth_user_by_forgot_password_id(rp_dto.id)
|
user = self._auth_users.find_auth_user_by_forgot_password_id(rp_dto.id)
|
||||||
if user is None:
|
if user is None:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidUser, f'User by forgot password id {rp_dto.id} not found')
|
raise ServiceException(
|
||||||
|
ServiceErrorCode.InvalidUser,
|
||||||
|
f"User by forgot password id {rp_dto.id} not found",
|
||||||
|
)
|
||||||
|
|
||||||
if user.confirmation_id is not None:
|
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 == '':
|
if user.password is None or rp_dto.password == "":
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, f'Password not set')
|
raise ServiceException(ServiceErrorCode.InvalidData, f"Password not set")
|
||||||
|
|
||||||
user.password_salt = uuid.uuid4()
|
user.password_salt = uuid.uuid4()
|
||||||
user.password = self._hash_sha256(rp_dto.password, user.password_salt)
|
user.password = self._hash_sha256(rp_dto.password, user.password_salt)
|
||||||
|
@@ -20,14 +20,13 @@ from bot_data.model.server import Server
|
|||||||
|
|
||||||
|
|
||||||
class DiscordService:
|
class DiscordService:
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
bot: DiscordBotServiceABC,
|
bot: DiscordBotServiceABC,
|
||||||
servers: ServerRepositoryABC,
|
servers: ServerRepositoryABC,
|
||||||
auth: AuthServiceABC,
|
auth: AuthServiceABC,
|
||||||
auth_users: AuthUserRepositoryABC,
|
auth_users: AuthUserRepositoryABC,
|
||||||
users: UserRepositoryABC,
|
users: UserRepositoryABC,
|
||||||
):
|
):
|
||||||
self._bot = bot
|
self._bot = bot
|
||||||
self._servers = servers
|
self._servers = servers
|
||||||
@@ -38,64 +37,53 @@ class DiscordService:
|
|||||||
def _to_dto(self, x: Server) -> Optional[ServerDTO]:
|
def _to_dto(self, x: Server) -> Optional[ServerDTO]:
|
||||||
guild = self._bot.get_guild(x.discord_server_id)
|
guild = self._bot.get_guild(x.discord_server_id)
|
||||||
if guild is None:
|
if guild is None:
|
||||||
return ServerTransformer.to_dto(
|
return ServerTransformer.to_dto(x, "", 0, None)
|
||||||
x,
|
|
||||||
'',
|
|
||||||
0,
|
|
||||||
None
|
|
||||||
)
|
|
||||||
|
|
||||||
return ServerTransformer.to_dto(
|
return ServerTransformer.to_dto(x, guild.name, guild.member_count, guild.icon)
|
||||||
x,
|
|
||||||
guild.name,
|
|
||||||
guild.member_count,
|
|
||||||
guild.icon
|
|
||||||
)
|
|
||||||
|
|
||||||
async def get_all_servers(self) -> List[ServerDTO]:
|
async def get_all_servers(self) -> List[ServerDTO]:
|
||||||
servers = List(ServerDTO, self._servers.get_servers())
|
servers = List(ServerDTO, self._servers.get_servers())
|
||||||
return servers.select(self._to_dto).where(lambda x: x.name != '')
|
return servers.select(self._to_dto).where(lambda x: x.name != "")
|
||||||
|
|
||||||
async def get_all_servers_by_user(self) -> List[ServerDTO]:
|
async def get_all_servers_by_user(self) -> List[ServerDTO]:
|
||||||
token = self._auth.get_decoded_token_from_request()
|
token = self._auth.get_decoded_token_from_request()
|
||||||
if token is None or 'email' not in token or 'role' not in token:
|
if token is None or "email" not in token or "role" not in token:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, 'Token invalid')
|
raise ServiceException(ServiceErrorCode.InvalidData, "Token invalid")
|
||||||
|
|
||||||
role = AuthRoleEnum(token['role'])
|
role = AuthRoleEnum(token["role"])
|
||||||
servers = self._servers.get_servers()
|
servers = self._servers.get_servers()
|
||||||
if role != AuthRoleEnum.admin:
|
if role != AuthRoleEnum.admin:
|
||||||
auth_user = self._auth_users.find_auth_user_by_email(token['email'])
|
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
||||||
if auth_user is not None:
|
if auth_user is not None:
|
||||||
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id)
|
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id)
|
||||||
servers = servers.where(lambda x: x.server_id in user_ids)
|
servers = servers.where(lambda x: x.server_id in user_ids)
|
||||||
|
|
||||||
servers = List(ServerDTO, servers)
|
servers = List(ServerDTO, servers)
|
||||||
return servers.select(self._to_dto).where(lambda x: x.name != '')
|
return servers.select(self._to_dto).where(lambda x: x.name != "")
|
||||||
|
|
||||||
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()
|
token = self._auth.get_decoded_token_from_request()
|
||||||
if token is None or 'email' not in token or 'role' not in token:
|
if token is None or "email" not in token or "role" not in token:
|
||||||
raise ServiceException(ServiceErrorCode.InvalidData, 'Token invalid')
|
raise ServiceException(ServiceErrorCode.InvalidData, "Token invalid")
|
||||||
|
|
||||||
role = AuthRoleEnum(token['role'])
|
role = AuthRoleEnum(token["role"])
|
||||||
filtered_result = self._servers.get_filtered_servers(criteria)
|
filtered_result = self._servers.get_filtered_servers(criteria)
|
||||||
# filter out servers, where the user not exists
|
# filter out servers, where the user not exists
|
||||||
if role != AuthRoleEnum.admin:
|
if role != AuthRoleEnum.admin:
|
||||||
auth_user = self._auth_users.find_auth_user_by_email(token['email'])
|
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
||||||
if auth_user is not None:
|
if auth_user is not None:
|
||||||
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id)
|
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id)
|
||||||
filtered_result.result = filtered_result.result.where(lambda x: x.server_id in user_ids)
|
filtered_result.result = filtered_result.result.where(lambda x: x.server_id in user_ids)
|
||||||
|
|
||||||
servers: List = filtered_result.result.select(self._to_dto).where(lambda x: x.name != '')
|
servers: List = filtered_result.result.select(self._to_dto).where(lambda x: x.name != "")
|
||||||
result = List(ServerDTO, servers)
|
result = List(ServerDTO, servers)
|
||||||
|
|
||||||
if criteria.name is not None and criteria.name != '':
|
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())
|
result = result.where(
|
||||||
|
lambda x: criteria.name.lower() in x.name.lower() or x.name.lower() == criteria.name.lower()
|
||||||
|
)
|
||||||
|
|
||||||
return ServerFilteredResultDTO(
|
return ServerFilteredResultDTO(List(ServerDTO, result), servers.count())
|
||||||
List(ServerDTO, result),
|
|
||||||
servers.count()
|
|
||||||
)
|
|
||||||
|
|
||||||
async def get_server_by_id_async(self, id: int) -> ServerDTO:
|
async def get_server_by_id_async(self, id: int) -> ServerDTO:
|
||||||
server = self._servers.get_server_by_id(id)
|
server = self._servers.get_server_by_id(id)
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_api.transformer'
|
__title__ = "bot_api.transformer"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -7,7 +7,6 @@ from bot_data.model.auth_user import AuthUser
|
|||||||
|
|
||||||
|
|
||||||
class AuthUserTransformer(TransformerABC):
|
class AuthUserTransformer(TransformerABC):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_db(dto: AuthUserDTO) -> AuthUser:
|
def to_db(dto: AuthUserDTO) -> AuthUser:
|
||||||
return AuthUser(
|
return AuthUser(
|
||||||
@@ -22,7 +21,7 @@ class AuthUserTransformer(TransformerABC):
|
|||||||
None,
|
None,
|
||||||
datetime.now(),
|
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
|
auth_user_id=0 if dto.id is None else dto.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -32,7 +31,7 @@ class AuthUserTransformer(TransformerABC):
|
|||||||
db.first_name,
|
db.first_name,
|
||||||
db.last_name,
|
db.last_name,
|
||||||
db.email,
|
db.email,
|
||||||
'' if password is None else password,
|
"" if password is None else password,
|
||||||
db.confirmation_id,
|
db.confirmation_id,
|
||||||
db.auth_role
|
db.auth_role,
|
||||||
)
|
)
|
||||||
|
@@ -8,7 +8,6 @@ from bot_data.model.server import Server
|
|||||||
|
|
||||||
|
|
||||||
class ServerTransformer(TransformerABC):
|
class ServerTransformer(TransformerABC):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_db(dto: ServerDTO) -> Server:
|
def to_db(dto: ServerDTO) -> Server:
|
||||||
return Server(dto.discord_id)
|
return Server(dto.discord_id)
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_core'
|
__title__ = "bot_core"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports
|
# imports
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_core.service'
|
__title__ = "bot_core.abc"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
61
kdb-bot/src/bot_core/abc/client_utils_abc.py
Normal file
61
kdb-bot/src/bot_core/abc/client_utils_abc.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
from cpl_query.extension import List
|
||||||
|
from discord.ext.commands import Context
|
||||||
|
|
||||||
|
from bot_data.model.user import User
|
||||||
|
from modules.base.configuration.base_server_settings import BaseServerSettings
|
||||||
|
|
||||||
|
|
||||||
|
class ClientUtilsABC(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def received_command(self, guild_id: int):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def moved_user(self, guild_id: int):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def moved_users(self, guild_id: int, count: int):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_client(self, dc_ic: int, guild_id: int):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def check_if_bot_is_ready_yet(self) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def check_if_bot_is_ready_yet_and_respond(self, ctx: Context) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def presence_game(self, t_key: str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_auto_complete_list(self, _l: List, current: str, select: Callable = None) -> List:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def is_message_xp_count_by_hour_higher_that_max_message_count_per_hour(
|
||||||
|
self,
|
||||||
|
created_at: datetime,
|
||||||
|
user: User,
|
||||||
|
settings: BaseServerSettings,
|
||||||
|
is_reaction: bool = False,
|
||||||
|
) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_ontime_for_user(self, user: User) -> float:
|
||||||
|
pass
|
@@ -1,27 +0,0 @@
|
|||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
from discord.ext.commands import Context
|
|
||||||
|
|
||||||
|
|
||||||
class ClientUtilsServiceABC(ABC):
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def __init__(self): pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def received_command(self, guild_id: int): pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def moved_user(self, guild_id: int): pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def get_client(self, dc_ic: int, guild_id: int): pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
async def check_if_bot_is_ready_yet(self) -> bool: pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
async def check_if_bot_is_ready_yet_and_respond(self, ctx: Context) -> bool: pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
async def presence_game(self, t_key: str): pass
|
|
@@ -9,52 +9,61 @@ from bot_core.configuration.file_logging_settings import FileLoggingSettings
|
|||||||
|
|
||||||
|
|
||||||
class CustomFileLoggerABC(Logger, ABC):
|
class CustomFileLoggerABC(Logger, ABC):
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self, key: str, config: ConfigurationABC, time_format: TimeFormatSettings, env: ApplicationEnvironmentABC):
|
def __init__(
|
||||||
|
self,
|
||||||
|
key: str,
|
||||||
|
config: ConfigurationABC,
|
||||||
|
time_format: TimeFormatSettings,
|
||||||
|
env: ApplicationEnvironmentABC,
|
||||||
|
):
|
||||||
self._key = key
|
self._key = key
|
||||||
settings: LoggingSettings = config.get_configuration(f'{FileLoggingSettings.__name__}_{key}')
|
self._settings: LoggingSettings = config.get_configuration(f"{FileLoggingSettings.__name__}_{key}")
|
||||||
Logger.__init__(self, settings, time_format, env)
|
Logger.__init__(self, self._settings, time_format, env)
|
||||||
self._begin_log()
|
self._begin_log()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def settings(self) -> LoggingSettings:
|
||||||
|
return self._settings
|
||||||
|
|
||||||
def _begin_log(self):
|
def _begin_log(self):
|
||||||
console_level = self._console.value
|
console_level = self._console.value
|
||||||
self._console = LoggingLevelEnum.OFF
|
self._console = LoggingLevelEnum.OFF
|
||||||
self.info(__name__, f'Starting...')
|
self.info(__name__, f"Starting...")
|
||||||
self._console = LoggingLevelEnum(console_level)
|
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(' ')
|
names = name_list_as_str.split(" ")
|
||||||
log_level = level.name
|
log_level = level.name
|
||||||
string = f'<{self._get_datetime_now()}> [ {log_level} ]'
|
string = f"<{self._get_datetime_now()}> [ {log_level} ]"
|
||||||
for name in names:
|
for name in names:
|
||||||
string += f' [ {name} ]'
|
string += f" [ {name} ]"
|
||||||
string += f': {message}'
|
string += f": {message}"
|
||||||
return string
|
return string
|
||||||
|
|
||||||
def header(self, string: str):
|
def header(self, string: str):
|
||||||
super().header(string)
|
super().header(string)
|
||||||
|
|
||||||
def trace(self, name: str, message: str):
|
def trace(self, name: str, message: str):
|
||||||
name = f'{name} {self._key}'
|
name = f"{name} {self._key}"
|
||||||
super().trace(name, message)
|
super().trace(name, message)
|
||||||
|
|
||||||
def debug(self, name: str, message: str):
|
def debug(self, name: str, message: str):
|
||||||
name = f'{name} {self._key}'
|
name = f"{name} {self._key}"
|
||||||
super().debug(name, message)
|
super().debug(name, message)
|
||||||
|
|
||||||
def info(self, name: str, message: str):
|
def info(self, name: str, message: str):
|
||||||
name = f'{name} {self._key}'
|
name = f"{name} {self._key}"
|
||||||
super().info(name, message)
|
super().info(name, message)
|
||||||
|
|
||||||
def warn(self, name: str, message: str):
|
def warn(self, name: str, message: str):
|
||||||
name = f'{name} {self._key}'
|
name = f"{name} {self._key}"
|
||||||
super().warn(name, message)
|
super().warn(name, message)
|
||||||
|
|
||||||
def error(self, name: str, message: str, ex: Exception = None):
|
def error(self, name: str, message: str, ex: Exception = None):
|
||||||
name = f'{name} {self._key}'
|
name = f"{name} {self._key}"
|
||||||
super().error(name, message, ex)
|
super().error(name, message, ex)
|
||||||
|
|
||||||
def fatal(self, name: str, message: str, ex: Exception = None):
|
def fatal(self, name: str, message: str, ex: Exception = None):
|
||||||
name = f'{name} {self._key}'
|
name = f"{name} {self._key}"
|
||||||
super().fatal(name, message, ex)
|
super().fatal(name, message, ex)
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Union
|
from typing import Union, Optional
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from cpl_query.extension import List
|
from cpl_query.extension import List
|
||||||
@@ -8,24 +8,58 @@ from discord.ext.commands import Context
|
|||||||
|
|
||||||
|
|
||||||
class MessageServiceABC(ABC):
|
class MessageServiceABC(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self): pass
|
async def delete_messages(self, messages: List[discord.Message], guild_id: int, without_tracking=False):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def delete_messages(self, messages: List[discord.Message], guild_id: int, without_tracking=False): pass
|
async def delete_message(self, message: discord.Message, without_tracking=False):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def delete_message(self, message: discord.Message, without_tracking=False): pass
|
async def send_channel_message(
|
||||||
|
self,
|
||||||
|
channel: discord.TextChannel,
|
||||||
|
message: Union[str, discord.Embed],
|
||||||
|
without_tracking=True,
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def send_channel_message(self, channel: discord.TextChannel, message: Union[str, discord.Embed], without_tracking=True): pass
|
async def send_dm_message(
|
||||||
|
self,
|
||||||
|
message: Union[str, discord.Embed],
|
||||||
|
receiver: Union[discord.User, discord.Member],
|
||||||
|
without_tracking=False,
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def send_dm_message(self, message: Union[str, discord.Embed], receiver: Union[discord.User, discord.Member], without_tracking=False): pass
|
async def send_ctx_msg(
|
||||||
|
self,
|
||||||
|
ctx: Context,
|
||||||
|
message: Union[str, discord.Embed],
|
||||||
|
file: discord.File = None,
|
||||||
|
is_persistent: bool = False,
|
||||||
|
is_public: bool = False,
|
||||||
|
wait_before_delete: int = None,
|
||||||
|
without_tracking=True,
|
||||||
|
) -> Optional[discord.Message]:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def send_ctx_msg(self, ctx: Context, message: Union[str, discord.Embed], file: discord.File = None, is_persistent: bool = False, wait_before_delete: int = None, without_tracking=True): pass
|
async def send_interaction_msg(
|
||||||
|
self,
|
||||||
@abstractmethod
|
interaction: Interaction,
|
||||||
async def send_interaction_msg(self, interaction: Interaction, message: Union[str, discord.Embed], is_persistent: bool = False, wait_before_delete: int = None, without_tracking=True): pass
|
message: Union[str, discord.Embed],
|
||||||
|
is_persistent: bool = False,
|
||||||
|
is_public: bool = False,
|
||||||
|
wait_before_delete: int = None,
|
||||||
|
without_tracking=True,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
@@ -7,7 +7,6 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
|||||||
|
|
||||||
|
|
||||||
class ModuleABC(StartupExtensionABC):
|
class ModuleABC(StartupExtensionABC):
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __init__(self, dc: DiscordCollectionABC, feature_flag: FeatureFlagsEnum):
|
def __init__(self, dc: DiscordCollectionABC, feature_flag: FeatureFlagsEnum):
|
||||||
StartupExtensionABC.__init__(self)
|
StartupExtensionABC.__init__(self)
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
"Version": {
|
"Version": {
|
||||||
"Major": "0",
|
"Major": "0",
|
||||||
"Minor": "3",
|
"Minor": "3",
|
||||||
"Micro": "dev70"
|
"Micro": "1"
|
||||||
},
|
},
|
||||||
"Author": "Sven Heidemann",
|
"Author": "Sven Heidemann",
|
||||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||||
@@ -16,10 +16,10 @@
|
|||||||
"LicenseName": "MIT",
|
"LicenseName": "MIT",
|
||||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"cpl-core>=0.3.dev70"
|
"cpl-core==2022.12.0"
|
||||||
],
|
],
|
||||||
"DevDependencies": [
|
"DevDependencies": [
|
||||||
"cpl-cli==2022.10.0"
|
"cpl-cli==2022.12.0"
|
||||||
],
|
],
|
||||||
"PythonVersion": ">=3.10.4",
|
"PythonVersion": ">=3.10.4",
|
||||||
"PythonPath": {},
|
"PythonPath": {},
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_core.configuration'
|
__title__ = "bot_core.configuration"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -8,7 +8,6 @@ from bot_core.configuration.file_logging_settings import FileLoggingSettings
|
|||||||
|
|
||||||
|
|
||||||
class BotLoggingSettings(ConfigurationModelABC):
|
class BotLoggingSettings(ConfigurationModelABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
self._files: List[FileLoggingSettings] = List(FileLoggingSettings)
|
self._files: List[FileLoggingSettings] = List(FileLoggingSettings)
|
||||||
@@ -22,12 +21,12 @@ class BotLoggingSettings(ConfigurationModelABC):
|
|||||||
files = List(FileLoggingSettings)
|
files = List(FileLoggingSettings)
|
||||||
for s in settings:
|
for s in settings:
|
||||||
st = FileLoggingSettings()
|
st = FileLoggingSettings()
|
||||||
settings[s]['Key'] = s
|
settings[s]["Key"] = s
|
||||||
st.from_dict(settings[s])
|
st.from_dict(settings[s])
|
||||||
files.append(st)
|
files.append(st)
|
||||||
self._files = files
|
self._files = files
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.set_foreground_color(ForegroundColorEnum.red)
|
Console.set_foreground_color(ForegroundColorEnum.red)
|
||||||
Console.write_line(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
|
Console.write_line(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||||
Console.write_line(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
Console.write_line(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
Console.set_foreground_color(ForegroundColorEnum.default)
|
Console.set_foreground_color(ForegroundColorEnum.default)
|
||||||
|
@@ -8,7 +8,6 @@ from bot_core.configuration.server_settings import ServerSettings
|
|||||||
|
|
||||||
|
|
||||||
class BotSettings(ConfigurationModelABC):
|
class BotSettings(ConfigurationModelABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
@@ -16,7 +15,8 @@ class BotSettings(ConfigurationModelABC):
|
|||||||
self._technicians: List[int] = List(int)
|
self._technicians: List[int] = List(int)
|
||||||
self._wait_for_restart = 2
|
self._wait_for_restart = 2
|
||||||
self._wait_for_shutdown = 2
|
self._wait_for_shutdown = 2
|
||||||
|
self._cache_max_messages = 1000
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def servers(self) -> List[ServerSettings]:
|
def servers(self) -> List[ServerSettings]:
|
||||||
return self._servers
|
return self._servers
|
||||||
@@ -33,6 +33,10 @@ class BotSettings(ConfigurationModelABC):
|
|||||||
def wait_for_shutdown(self) -> int:
|
def wait_for_shutdown(self) -> int:
|
||||||
return self._wait_for_shutdown
|
return self._wait_for_shutdown
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cache_max_messages(self) -> int:
|
||||||
|
return self._cache_max_messages
|
||||||
|
|
||||||
def from_dict(self, settings: dict):
|
def from_dict(self, settings: dict):
|
||||||
try:
|
try:
|
||||||
self._technicians = settings["Technicians"]
|
self._technicians = settings["Technicians"]
|
||||||
@@ -41,6 +45,11 @@ class BotSettings(ConfigurationModelABC):
|
|||||||
settings.pop("Technicians")
|
settings.pop("Technicians")
|
||||||
settings.pop("WaitForRestart")
|
settings.pop("WaitForRestart")
|
||||||
settings.pop("WaitForShutdown")
|
settings.pop("WaitForShutdown")
|
||||||
|
|
||||||
|
if "CacheMaxMessages" in settings:
|
||||||
|
self._cache_max_messages = settings["CacheMaxMessages"]
|
||||||
|
settings.pop("CacheMaxMessages")
|
||||||
|
|
||||||
servers = List(ServerSettings)
|
servers = List(ServerSettings)
|
||||||
for s in settings:
|
for s in settings:
|
||||||
st = ServerSettings()
|
st = ServerSettings()
|
||||||
@@ -49,5 +58,5 @@ class BotSettings(ConfigurationModelABC):
|
|||||||
servers.append(st)
|
servers.append(st)
|
||||||
self._servers = servers
|
self._servers = servers
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
|
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@@ -3,19 +3,19 @@ from enum import Enum
|
|||||||
|
|
||||||
class FeatureFlagsEnum(Enum):
|
class FeatureFlagsEnum(Enum):
|
||||||
# modules
|
# modules
|
||||||
api_module = 'ApiModule'
|
api_module = "ApiModule"
|
||||||
admin_module = 'AdminModule'
|
admin_module = "AdminModule"
|
||||||
auto_role_module = 'AutoRoleModule'
|
auto_role_module = "AutoRoleModule"
|
||||||
base_module = 'BaseModule'
|
base_module = "BaseModule"
|
||||||
boot_log_module = 'BootLogModule'
|
boot_log_module = "BootLogModule"
|
||||||
core_module = 'CoreModule'
|
core_module = "CoreModule"
|
||||||
core_extension_module = 'CoreExtensionModule'
|
core_extension_module = "CoreExtensionModule"
|
||||||
data_module = 'DataModule',
|
data_module = ("DataModule",)
|
||||||
database_module = 'DatabaseModule',
|
database_module = ("DatabaseModule",)
|
||||||
level_module = 'LevelModule'
|
level_module = "LevelModule"
|
||||||
moderator_module = 'ModeratorModule'
|
moderator_module = "ModeratorModule"
|
||||||
permission_module = 'PermissionModule'
|
permission_module = "PermissionModule"
|
||||||
stats_module = 'StatsModule'
|
stats_module = "StatsModule"
|
||||||
# features
|
# features
|
||||||
api_only = 'ApiOnly'
|
api_only = "ApiOnly"
|
||||||
presence = 'Presence'
|
presence = "Presence"
|
||||||
|
@@ -8,7 +8,6 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
|||||||
|
|
||||||
|
|
||||||
class FeatureFlagsSettings(ConfigurationModelABC):
|
class FeatureFlagsSettings(ConfigurationModelABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
@@ -47,5 +46,5 @@ class FeatureFlagsSettings(ConfigurationModelABC):
|
|||||||
for flag in [f.value for f in FeatureFlagsEnum]:
|
for flag in [f.value for f in FeatureFlagsEnum]:
|
||||||
self._load_flag(settings, FeatureFlagsEnum(flag))
|
self._load_flag(settings, FeatureFlagsEnum(flag))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
|
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@@ -5,11 +5,10 @@ from cpl_core.logging import LoggingSettings
|
|||||||
|
|
||||||
|
|
||||||
class FileLoggingSettings(LoggingSettings):
|
class FileLoggingSettings(LoggingSettings):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
LoggingSettings.__init__(self)
|
LoggingSettings.__init__(self)
|
||||||
|
|
||||||
self._key = ''
|
self._key = ""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def key(self) -> str:
|
def key(self) -> str:
|
||||||
@@ -17,8 +16,8 @@ class FileLoggingSettings(LoggingSettings):
|
|||||||
|
|
||||||
def from_dict(self, settings: dict):
|
def from_dict(self, settings: dict):
|
||||||
try:
|
try:
|
||||||
self._key = settings['Key']
|
self._key = settings["Key"]
|
||||||
super().from_dict(settings)
|
super().from_dict(settings)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings')
|
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@@ -5,7 +5,6 @@ from cpl_core.console import Console
|
|||||||
|
|
||||||
|
|
||||||
class ServerSettings(ConfigurationModelABC):
|
class ServerSettings(ConfigurationModelABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
@@ -22,8 +21,8 @@ class ServerSettings(ConfigurationModelABC):
|
|||||||
|
|
||||||
def from_dict(self, settings: dict):
|
def from_dict(self, settings: dict):
|
||||||
try:
|
try:
|
||||||
self._id = int(settings['Id'])
|
self._id = int(settings["Id"])
|
||||||
self._message_delete_timer = int(settings['MessageDeleteTimer'])
|
self._message_delete_timer = int(settings["MessageDeleteTimer"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings')
|
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in settings")
|
||||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_core.core_extension'
|
__title__ = "bot_core.core_extension"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -3,7 +3,7 @@ from cpl_core.configuration import ConfigurationABC
|
|||||||
from cpl_core.dependency_injection import ServiceProviderABC
|
from cpl_core.dependency_injection import ServiceProviderABC
|
||||||
from cpl_translation import TranslatePipe
|
from cpl_translation import TranslatePipe
|
||||||
|
|
||||||
from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC
|
from bot_core.abc.client_utils_abc import ClientUtilsABC
|
||||||
from bot_core.abc.message_service_abc import MessageServiceABC
|
from bot_core.abc.message_service_abc import MessageServiceABC
|
||||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||||
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
||||||
@@ -13,7 +13,6 @@ from modules.permission.abc.permission_service_abc import PermissionServiceABC
|
|||||||
|
|
||||||
|
|
||||||
class CoreExtension(ApplicationExtensionABC):
|
class CoreExtension(ApplicationExtensionABC):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
ApplicationExtensionABC.__init__(self)
|
ApplicationExtensionABC.__init__(self)
|
||||||
|
|
||||||
@@ -23,7 +22,7 @@ class CoreExtension(ApplicationExtensionABC):
|
|||||||
return
|
return
|
||||||
|
|
||||||
permissions: PermissionServiceABC = services.get_service(PermissionServiceABC)
|
permissions: PermissionServiceABC = services.get_service(PermissionServiceABC)
|
||||||
client_utils: ClientUtilsServiceABC = services.get_service(ClientUtilsServiceABC)
|
client_utils: ClientUtilsABC = services.get_service(ClientUtilsABC)
|
||||||
message_service: MessageServiceABC = services.get_service(MessageServiceABC)
|
message_service: MessageServiceABC = services.get_service(MessageServiceABC)
|
||||||
t: TranslatePipe = services.get_service(TranslatePipe)
|
t: TranslatePipe = services.get_service(TranslatePipe)
|
||||||
CommandChecks.init(permissions, client_utils, message_service, t)
|
CommandChecks.init(permissions, client_utils, message_service, t)
|
||||||
|
@@ -6,11 +6,12 @@ from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
|
|||||||
|
|
||||||
from bot_core.abc.module_abc import ModuleABC
|
from bot_core.abc.module_abc import ModuleABC
|
||||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||||
from bot_core.core_extension.core_extension_on_ready_event import CoreExtensionOnReadyEvent
|
from bot_core.core_extension.core_extension_on_ready_event import (
|
||||||
|
CoreExtensionOnReadyEvent,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CoreExtensionModule(ModuleABC):
|
class CoreExtensionModule(ModuleABC):
|
||||||
|
|
||||||
def __init__(self, dc: DiscordCollectionABC):
|
def __init__(self, dc: DiscordCollectionABC):
|
||||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_extension_module)
|
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_extension_module)
|
||||||
|
|
||||||
|
@@ -5,17 +5,16 @@ from cpl_discord.events import OnReadyABC
|
|||||||
from cpl_discord.service import DiscordBotServiceABC
|
from cpl_discord.service import DiscordBotServiceABC
|
||||||
from cpl_translation import TranslatePipe
|
from cpl_translation import TranslatePipe
|
||||||
|
|
||||||
from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC
|
from bot_core.abc.client_utils_abc import ClientUtilsABC
|
||||||
|
|
||||||
|
|
||||||
class CoreExtensionOnReadyEvent(OnReadyABC):
|
class CoreExtensionOnReadyEvent(OnReadyABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
logger: LoggerABC,
|
logger: LoggerABC,
|
||||||
bot: DiscordBotServiceABC,
|
bot: DiscordBotServiceABC,
|
||||||
client_utils: ClientUtilsServiceABC,
|
client_utils: ClientUtilsABC,
|
||||||
t: TranslatePipe
|
t: TranslatePipe,
|
||||||
):
|
):
|
||||||
OnReadyABC.__init__(self)
|
OnReadyABC.__init__(self)
|
||||||
|
|
||||||
@@ -24,9 +23,9 @@ class CoreExtensionOnReadyEvent(OnReadyABC):
|
|||||||
self._client_utils = client_utils
|
self._client_utils = client_utils
|
||||||
self._t = t
|
self._t = t
|
||||||
|
|
||||||
self._logger.info(__name__, f'Module {type(self)} loaded')
|
self._logger.info(__name__, f"Module {type(self)} loaded")
|
||||||
|
|
||||||
async def on_ready(self):
|
async def on_ready(self):
|
||||||
self._logger.debug(__name__, f'Module {type(self)} started')
|
self._logger.debug(__name__, f"Module {type(self)} started")
|
||||||
await self._client_utils.presence_game('common.presence.running')
|
await self._client_utils.presence_game("common.presence.running")
|
||||||
self._logger.trace(__name__, f'Module {type(self)} stopped')
|
self._logger.trace(__name__, f"Module {type(self)} stopped")
|
||||||
|
@@ -4,7 +4,7 @@ from cpl_core.environment import ApplicationEnvironmentABC
|
|||||||
from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum
|
from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum
|
||||||
from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
|
from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
|
||||||
|
|
||||||
from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC
|
from bot_core.abc.client_utils_abc import ClientUtilsABC
|
||||||
from bot_core.abc.message_service_abc import MessageServiceABC
|
from bot_core.abc.message_service_abc import MessageServiceABC
|
||||||
from bot_core.abc.module_abc import ModuleABC
|
from bot_core.abc.module_abc import ModuleABC
|
||||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||||
@@ -15,7 +15,6 @@ from bot_core.service.message_service import MessageService
|
|||||||
|
|
||||||
|
|
||||||
class CoreModule(ModuleABC):
|
class CoreModule(ModuleABC):
|
||||||
|
|
||||||
def __init__(self, dc: DiscordCollectionABC):
|
def __init__(self, dc: DiscordCollectionABC):
|
||||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_module)
|
ModuleABC.__init__(self, dc, FeatureFlagsEnum.core_module)
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@ class CoreModule(ModuleABC):
|
|||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||||
services.add_transient(MessageServiceABC, MessageService)
|
services.add_transient(MessageServiceABC, MessageService)
|
||||||
services.add_transient(ClientUtilsServiceABC, ClientUtilsService)
|
services.add_transient(ClientUtilsABC, ClientUtilsService)
|
||||||
|
|
||||||
# pipes
|
# pipes
|
||||||
services.add_transient(DateTimeOffsetPipe)
|
services.add_transient(DateTimeOffsetPipe)
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_core.events'
|
__title__ = "bot_core.events"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -3,17 +3,16 @@ from cpl_discord.events import OnReadyABC
|
|||||||
from cpl_discord.service import DiscordBotServiceABC
|
from cpl_discord.service import DiscordBotServiceABC
|
||||||
from cpl_translation import TranslatePipe
|
from cpl_translation import TranslatePipe
|
||||||
|
|
||||||
from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC
|
from bot_core.abc.client_utils_abc import ClientUtilsABC
|
||||||
|
|
||||||
|
|
||||||
class CoreOnReadyEvent(OnReadyABC):
|
class CoreOnReadyEvent(OnReadyABC):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
logger: LoggerABC,
|
logger: LoggerABC,
|
||||||
bot: DiscordBotServiceABC,
|
bot: DiscordBotServiceABC,
|
||||||
client_utils: ClientUtilsServiceABC,
|
client_utils: ClientUtilsABC,
|
||||||
t: TranslatePipe,
|
t: TranslatePipe,
|
||||||
):
|
):
|
||||||
OnReadyABC.__init__(self)
|
OnReadyABC.__init__(self)
|
||||||
|
|
||||||
@@ -22,9 +21,9 @@ class CoreOnReadyEvent(OnReadyABC):
|
|||||||
self._client_utils = client_utils
|
self._client_utils = client_utils
|
||||||
self._t = t
|
self._t = t
|
||||||
|
|
||||||
self._logger.info(__name__, f'Module {type(self)} loaded')
|
self._logger.info(__name__, f"Module {type(self)} loaded")
|
||||||
|
|
||||||
async def on_ready(self):
|
async def on_ready(self):
|
||||||
self._logger.debug(__name__, f'Module {type(self)} started')
|
self._logger.debug(__name__, f"Module {type(self)} started")
|
||||||
await self._client_utils.presence_game('common.presence.booting')
|
await self._client_utils.presence_game("common.presence.booting")
|
||||||
self._logger.trace(__name__, f'Module {type(self)} stopped')
|
self._logger.trace(__name__, f"Module {type(self)} stopped")
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
bot Keksdose bot
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__title__ = "bot_core.exception"
|
||||||
|
__author__ = "Sven Heidemann"
|
||||||
|
__license__ = "MIT"
|
||||||
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
|
# imports:
|
||||||
|
|
||||||
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
@@ -2,6 +2,5 @@ from discord.ext.commands import CommandError
|
|||||||
|
|
||||||
|
|
||||||
class CheckError(CommandError):
|
class CheckError(CommandError):
|
||||||
|
|
||||||
def __init__(self, message, *args):
|
def __init__(self, message, *args):
|
||||||
CommandError.__init__(self, message, *args)
|
CommandError.__init__(self, message, *args)
|
||||||
|
@@ -6,21 +6,21 @@ bot Keksdose bot
|
|||||||
|
|
||||||
Discord bot for the Keksdose discord Server
|
Discord bot for the Keksdose discord Server
|
||||||
|
|
||||||
:copyright: (c) 2022 sh-edraft.de
|
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||||
:license: MIT, see LICENSE for more details.
|
:license: MIT, see LICENSE for more details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__title__ = 'bot_core.helper'
|
__title__ = "bot_core.helper"
|
||||||
__author__ = 'Sven Heidemann'
|
__author__ = "Sven Heidemann"
|
||||||
__license__ = 'MIT'
|
__license__ = "MIT"
|
||||||
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
|
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||||
__version__ = '0.3.dev25'
|
__version__ = "0.3.1"
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
# imports:
|
# imports:
|
||||||
|
|
||||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||||
version_info = VersionInfo(major='0', minor='3', micro='dev25')
|
version_info = VersionInfo(major="0", minor="3", micro="1")
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user